Skip to content

Commit 090b96f

Browse files
committed
draft deploy with ui
1 parent e5ad22d commit 090b96f

26 files changed

+493
-7
lines changed

.air.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tmp_dir = "tmp"
77
bin = "./tmp/main"
88
cmd = "go build -o ./tmp/main ./cmd/main.go"
99
delay = 1000
10-
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
10+
exclude_dir = ["assets", "tmp", "vendor", "testdata", "web", "build"]
1111
exclude_file = []
1212
exclude_regex = ["_test.go"]
1313
exclude_unchanged = false

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
tmp
2-
secret.sh
2+
secret.sh
3+
build

Dockerfile

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,31 @@ COPY . ./
1616

1717
RUN go build -o /server ./cmd/main.go
1818

19+
##
20+
## Build UI
21+
##
22+
23+
FROM oven/bun:1.0 AS ui
24+
25+
WORKDIR /app
26+
27+
COPY web ./
28+
29+
RUN bun install
30+
31+
RUN bun run build
1932

2033
##
2134
## Deploy
2235
##
23-
FROM gcr.io/distroless/base-debian12:nonroot
36+
FROM busybox:1.35.0-uclibc AS deploy
2437

2538
WORKDIR /
2639

40+
RUN mkdir -p /web
41+
2742
COPY --from=build /server .
43+
COPY --from=ui /app/build /web/build
2844

2945
EXPOSE 16321
3046
EXPOSE 6321

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@ tidy:
77
lint:
88
@echo "Running linter..."
99
@golangci-lint run
10+
11+
ui:
12+
@cd web && bun run build
13+
14+
docker:
15+
@docker build -t quickmq:latest .

cmd/main.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,29 @@ import (
77
"time"
88

99
"github.com/ochom/gutils/logs"
10+
"github.com/ochom/quickmq/src/api"
1011
"github.com/ochom/quickmq/src/app"
1112
)
1213

1314
func main() {
14-
svr := app.New()
15-
port := ":16321"
15+
coreServer := app.New()
16+
webServer := api.New()
17+
18+
// run core
1619
go func() {
17-
if err := svr.Listen(port); err != nil {
20+
if err := coreServer.Listen(":6321"); err != nil {
1821
panic(err)
1922
}
2023
}()
2124

25+
// run api and web
26+
go func() {
27+
if err := webServer.Listen(":16321"); err != nil {
28+
panic(err)
29+
}
30+
}()
31+
32+
// go run consumer daemon
2233
go func() {
2334
stopSignal := make(chan bool, 1)
2435
logs.Info("starting consumers daemon")
@@ -34,7 +45,13 @@ func main() {
3445
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
3546
defer cancel()
3647

37-
if err := svr.ShutdownWithContext(ctx); err != nil {
48+
// shutdown core server
49+
if err := coreServer.ShutdownWithContext(ctx); err != nil {
50+
panic(err)
51+
}
52+
53+
// shutdown api server
54+
if err := webServer.ShutdownWithContext(ctx); err != nil {
3855
panic(err)
3956
}
4057

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
require (
1111
github.com/andybalholm/brotli v1.1.0 // indirect
1212
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
13+
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
1314
github.com/google/uuid v1.6.0 // indirect
1415
github.com/joho/godotenv v1.5.1 // indirect
1516
github.com/klauspost/compress v1.17.9 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ github.com/gofiber/fiber/v3 v3.0.0-beta.2 h1:mVVgt8PTaHGup3NGl/+7U7nEoZaXJ5OComV
66
github.com/gofiber/fiber/v3 v3.0.0-beta.2/go.mod h1:w7sdfTY0okjZ1oVH6rSOGvuACUIt0By1iK0HKUb3uqM=
77
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
88
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
9+
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
10+
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
911
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
1012
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1113
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=

src/api/app.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package api
2+
3+
import (
4+
"github.com/gofiber/fiber/v3"
5+
)
6+
7+
func New() *fiber.App {
8+
app := fiber.New()
9+
10+
// rest apis
11+
app.Post("/login", login)
12+
app.Get("/user", loadUSer)
13+
14+
// serve other static files
15+
app.Static("/", "web/build")
16+
app.Get("*", func(c fiber.Ctx) error {
17+
return c.SendFile("web/build/index.html")
18+
})
19+
20+
return app
21+
}

src/api/auth.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package api
2+
3+
import (
4+
"time"
5+
6+
"github.com/gofiber/fiber/v3"
7+
"github.com/ochom/gutils/auth"
8+
"github.com/ochom/gutils/env"
9+
"github.com/ochom/gutils/uuid"
10+
)
11+
12+
func login(c fiber.Ctx) error {
13+
var data struct {
14+
Username string `json:"username"`
15+
Password string `json:"password"`
16+
}
17+
if err := c.Bind().Body(&data); err != nil {
18+
return err
19+
}
20+
21+
username := env.Get("QUICK_MQ_USERNAME", "admin")
22+
password := env.Get("QUICK_MQ_PASSWORD", "admin")
23+
24+
if data.Username != username {
25+
return c.Status(400).JSON(fiber.Map{"status": "error", "message": "Invalid username"})
26+
}
27+
28+
if data.Password != password {
29+
return c.Status(400).JSON(fiber.Map{"status": "error", "message": "Invalid password"})
30+
}
31+
32+
token, err := auth.GenerateAuthTokens(map[string]string{"user": "admin", "session_id": uuid.New()})
33+
if err != nil {
34+
return err
35+
}
36+
37+
// Set a cookie
38+
cookie := fiber.Cookie{
39+
Name: "jwt",
40+
Value: token["token"],
41+
Expires: time.Now().Add(time.Hour * 24),
42+
HTTPOnly: true,
43+
}
44+
c.Cookie(&cookie)
45+
46+
return c.JSON(fiber.Map{"status": "success", "message": "Logged in", "username": "admin"})
47+
}
48+
49+
func loadUSer(c fiber.Ctx) error {
50+
token := c.Cookies("jwt")
51+
claims, err := auth.GetAuthClaims(token)
52+
if err != nil {
53+
return c.Status(401).JSON(fiber.Map{"status": "error", "message": "Unauthorized", "data": err.Error()})
54+
}
55+
56+
if claims["user"] != "admin" {
57+
return c.Status(401).JSON(fiber.Map{"status": "error", "message": "Unauthorized"})
58+
}
59+
60+
return c.JSON(fiber.Map{"status": "success", "message": "Logged in", "username": "admin"})
61+
}

web/.eslintrc.cjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
root: true,
3+
env: { browser: true, es2020: true },
4+
extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],
5+
ignorePatterns: ['dist', '.eslintrc.cjs'],
6+
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
7+
settings: { react: { version: '18.2' } },
8+
plugins: ['react-refresh'],
9+
rules: {
10+
'react/jsx-no-target-blank': 'off',
11+
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
12+
'react/prop-types': 'off'
13+
}
14+
};

0 commit comments

Comments
 (0)