From e5fd59f3edff34b160f1d0182e29b54863ae3449 Mon Sep 17 00:00:00 2001 From: KartoffelChipss Date: Wed, 6 May 2026 19:00:28 +0200 Subject: [PATCH] Switch to modernc.org/sqlite and update dockerfile --- .gitignore | 3 ++ Dockerfile | 45 +++++++++++++---- backend/app/handlers/static.go | 15 +++++- backend/app/middleware/api_host_guard.go | 7 ++- backend/app/routes/routes.go | 32 ++++++------ backend/config.example.yaml | 48 ------------------ backend/go.mod | 16 ++++-- backend/go.sum | 56 +++++++++++++++++---- backend/internal/database/site_sqlite.go | 1 - backend/internal/database/sqlite.go | 4 +- backend/internal/database/user_sqlite.go | 8 +-- backend/internal/envconfig/envconfig.go | 24 +++++---- backend/internal/fiberconfig/fiberconfig.go | 14 ------ backend/main.go | 10 ++-- docker-compose-dev.yml | 3 ++ docker-compose.yml | 3 ++ 16 files changed, 162 insertions(+), 127 deletions(-) create mode 100644 .gitignore delete mode 100644 backend/config.example.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8dbef7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +storage +config \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3f46c28..db9763a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,53 @@ -FROM golang:1.25-alpine AS builder +# Stage 1: Build frontend +FROM node:20-alpine AS frontend-builder WORKDIR /app -RUN apk add --no-cache build-base libwebp-dev +COPY frontend/package.json frontend/pnpm-lock.yaml ./ + +RUN npm install -g pnpm \ + && pnpm install --frozen-lockfile + +COPY frontend . + +RUN pnpm run build + +# Stage 2: Build backend +FROM golang:1.25-alpine AS backend-builder + +WORKDIR /backend + +ARG TARGETOS +ARG TARGETARCH + +COPY backend/go.mod backend/go.sum ./ -COPY go.mod go.sum ./ RUN go mod download -COPY . . +COPY backend . -RUN go build -tags "fts5" -o quay +RUN CGO_ENABLED=0 \ + GOOS=$TARGETOS \ + GOARCH=$TARGETARCH \ + go build -o server ./ -FROM alpine:3.19 +# Stage 3: Final image +FROM alpine:latest +RUN apk add --no-cache ca-certificates tzdata -WORKDIR /app +# backend +COPY --from=backend-builder /backend/server /server -RUN apk add --no-cache libwebp libstdc++ +# frontend +COPY --from=frontend-builder /app/dist /app/dist -COPY --from=builder /app/quay . +RUN mkdir -p /config ENV PORT=4321 ENV CONFIG_DIR=/config ENV STORAGE_PATH=/storage +ENV STATIC_DASHBOARD_PATH=/app/dist EXPOSE 4321 -CMD ["./quay"] \ No newline at end of file +CMD ["/server"] \ No newline at end of file diff --git a/backend/app/handlers/static.go b/backend/app/handlers/static.go index 96b8a75..26db961 100644 --- a/backend/app/handlers/static.go +++ b/backend/app/handlers/static.go @@ -10,9 +10,22 @@ import ( "github.com/gofiber/fiber/v3" ) -func NewStaticHandler(storagePath string, siteRepo repository.SiteRepository) fiber.Handler { +func NewStaticHandler(storagePath string, siteRepo repository.SiteRepository, staticDashboardPath, dashboardHost string) fiber.Handler { return func(c fiber.Ctx) error { domain := c.Hostname() + + if staticDashboardPath != "" && domain == dashboardHost { + urlPath := c.Path() + filePath := filepath.Join(staticDashboardPath, filepath.Clean(urlPath)) + + info, err := os.Stat(filePath) + if err == nil && !info.IsDir() { + return c.SendFile(filePath) + } + + return c.SendFile(filepath.Join(staticDashboardPath, "index.html")) + } + site, err := siteRepo.GetSiteByDomain(domain) if err != nil { return c.Status(fiber.StatusInternalServerError).SendString("Failed to resolve site") diff --git a/backend/app/middleware/api_host_guard.go b/backend/app/middleware/api_host_guard.go index d6a69cc..8a6555d 100644 --- a/backend/app/middleware/api_host_guard.go +++ b/backend/app/middleware/api_host_guard.go @@ -2,10 +2,13 @@ package middleware import "github.com/gofiber/fiber/v3" -func APIHostGuard(allowedHost string) fiber.Handler { +func APIHostGuard(allowedHost string, alternativeHandler fiber.Handler) fiber.Handler { return func(c fiber.Ctx) error { if c.Hostname() != allowedHost { - return c.Status(fiber.StatusNotFound).SendString("Not Found") + if alternativeHandler != nil { + return alternativeHandler(c) + } + return c.Status(fiber.StatusForbidden).SendString("Forbidden: Invalid API host") } return c.Next() } diff --git a/backend/app/routes/routes.go b/backend/app/routes/routes.go index 0ecb90f..7bcccf0 100644 --- a/backend/app/routes/routes.go +++ b/backend/app/routes/routes.go @@ -7,18 +7,19 @@ import ( "quay/app/handlers" "quay/app/middleware" "quay/app/models" - "quay/internal/config" "quay/internal/database" "quay/internal/envconfig" "quay/internal/security" + "github.com/Flussen/swagger-fiber-v3" "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/static" ) const BootstrapUserUsername = "admin" const BootstrapUserPassword = "admin" -func Register(app *fiber.App, cfg *config.Config, envCfg *envconfig.EnvConfig, db *sql.DB) { +func Register(app *fiber.App, envCfg *envconfig.EnvConfig, db *sql.DB) { siteRepository := database.NewSQLiteSiteRepository(db) deploymentRepository := database.NewSQLiteDeploymentRepository(db) userRepository := database.NewSQLiteUserRepository(db) @@ -45,13 +46,19 @@ func Register(app *fiber.App, cfg *config.Config, envCfg *envconfig.EnvConfig, d } } + storagePath, err := filepath.Abs(envCfg.StoragePath) + if err != nil { + log.Fatalf("Failed to resolve storage path: %v", err) + } + siteHandler := handlers.NewSiteHandler(siteRepository) deploySiteHandler := handlers.NewDeploySiteHandler(envCfg, siteRepository, gitServerRepository, deploymentRepository) userHandler := handlers.NewUserHandler(userRepository) gitServerHandler := handlers.NewGitServerHandler(gitServerRepository) deploymentsHandler := handlers.NewDeploymentHandler(deploymentRepository) + staticSiteHandler := handlers.NewStaticHandler(storagePath, siteRepository, envCfg.StaticDashboardPath, envCfg.DashboardHost) - api := app.Group("/api/v1", middleware.APIHostGuard(envCfg.DashboardHost)) + api := app.Group("/api/v1", middleware.APIHostGuard(envCfg.DashboardHost, staticSiteHandler)) public := api.Group("") public.Get("/health", handlers.HealthCheck) @@ -61,6 +68,13 @@ func Register(app *fiber.App, cfg *config.Config, envCfg *envconfig.EnvConfig, d public.Post("/deploy", deploySiteHandler.PostDeploy) + public.Get("/api/docs.json", static.New("./docs/swagger.json")) + + public.Get("/api/swagger/*", swagger.New(swagger.Config{ + URL: "/api/docs.json", + Title: "mcheads.net API Documentation", + })) + // Protected routes - require auth for everything by default protected := api.Group("", middleware.RequireAuth()) @@ -119,15 +133,5 @@ func Register(app *fiber.App, cfg *config.Config, envCfg *envconfig.EnvConfig, d }) }) - storagePath, err := filepath.Abs(envCfg.StoragePath) - if err != nil { - log.Fatalf("Failed to resolve storage path: %v", err) - } - - siteMap := make(map[string]config.SiteConfig) - for _, site := range cfg.Sites { - siteMap[site.Domain] = site - } - - app.Use(handlers.NewStaticHandler(storagePath, siteRepository)) + app.Use(staticSiteHandler) } diff --git a/backend/config.example.yaml b/backend/config.example.yaml deleted file mode 100644 index 03f378d..0000000 --- a/backend/config.example.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Configuration file for Quay -# This file defines the global settings and the sites to be deployed. -# You can use ${VARIABLE_NAME} to reference environment variables for sensitive information. - -sites: - - repo: my-lib-docs - owner: yourname - branch: gh-pages - domain: docs.my-lib.com - deploy_token: "${MY_LIB_DEPLOY_TOKEN}" - enabled: true - not_found_file: 404.html - forward_rules: - - source: /npm - destination: https://www.npmjs.com/package/my-lib - status_code: 302 - - source: ^/docs/v(\d+)$ - destination: https://v$1.docs.my-lib.com/ - status_code: 301 - regex: true - - source: ^/blog/(?P[^/]+)$ - destination: /posts/${slug} - status_code: 302 - regex: true - custom_headers: - - source: /json/* # glob (default) - headers: - Content-Type: "application/json" - Cache-Control: "max-age=7200, must-revalidate" - - source: ^/api/v\d+/ # regex opt-in - regex: true - headers: - Cache-Control: "no-store" - - - repo: portfolio - owner: yourname - branch: main - domain: yourname.com - spa: true - deploy_token: "${PORTFOLIO_DEPLOY_TOKEN}" - enabled: true - - - repo: other-docs - owner: yourname - branch: gh-pages - domain: other-docs.yourdomain.com - deploy_token: "${OTHER_DOCS_DEPLOY_TOKEN}" - enabled: true \ No newline at end of file diff --git a/backend/go.mod b/backend/go.mod index 4f2378f..50376db 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -8,10 +8,10 @@ require ( github.com/golang-jwt/jwt/v5 v5.0.0 github.com/google/uuid v1.6.0 github.com/joho/godotenv v1.5.1 - github.com/mattn/go-sqlite3 v1.14.38 + github.com/maypok86/otter/v2 v2.3.0 github.com/swaggo/swag v1.16.4 golang.org/x/crypto v0.48.0 - gopkg.in/yaml.v3 v3.0.1 + modernc.org/sqlite v1.50.0 ) require ( @@ -20,6 +20,7 @@ require ( github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect github.com/go-openapi/spec v0.20.4 // indirect @@ -31,16 +32,21 @@ require ( github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/maypok86/otter/v2 v2.3.0 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/stretchr/testify v1.11.1 // indirect github.com/tinylib/msgp v1.6.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.69.0 // indirect golang.org/x/net v0.50.0 // indirect - golang.org/x/sys v0.41.0 // indirect + golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.34.0 // indirect - golang.org/x/tools v0.41.0 // indirect + golang.org/x/tools v0.42.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.72.0 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 0da04f6..83d81bd 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -12,6 +12,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -32,8 +34,12 @@ github.com/gofiber/utils/v2 v2.0.2 h1:ShRRssz0F3AhTlAQcuEj54OEDtWF7+HJDwEi/aa6QL github.com/gofiber/utils/v2 v2.0.2/go.mod h1:+9Ub4NqQ+IaJoTliq5LfdmOJAA/Hzwf4pXOxOa3RrJ0= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -53,16 +59,18 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-sqlite3 v1.14.38 h1:tDUzL85kMvOrvpCt8P64SbGgVFtJB11GPi2AdmITgb4= -github.com/mattn/go-sqlite3 v1.14.38/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/maypok86/otter/v2 v2.3.0 h1:8H8AVVFUSzJwIegKwv1uF5aGitTY+AIrtktg7OcLs8w= github.com/maypok86/otter/v2 v2.3.0/go.mod h1:XgIdlpmL6jYz882/CAx1E4C1ukfgDKSaw4mWq59+7l8= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/shamaton/msgpack/v3 v3.1.0 h1:jsk0vEAqVvvS9+fTZ5/EcQ9tz860c9pWxJ4Iwecz8gU= github.com/shamaton/msgpack/v3 v3.1.0/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -84,26 +92,26 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= @@ -115,3 +123,31 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U= +modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8= +modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU= +modernc.org/ccgo/v4 v4.32.4/go.mod h1:lY7f+fiTDHfcv6YlRgSkxYfhs+UvOEEzj49jAn2TOx0= +modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= +modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.72.0 h1:IEu559v9a0XWjw0DPoVKtXpO2qt5NVLAnFaBbjq+n8c= +modernc.org/libc v1.72.0/go.mod h1:tTU8DL8A+XLVkEY3x5E/tO7s2Q/q42EtnNWda/L5QhQ= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM= +modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/backend/internal/database/site_sqlite.go b/backend/internal/database/site_sqlite.go index 2a40c07..9ace9cd 100644 --- a/backend/internal/database/site_sqlite.go +++ b/backend/internal/database/site_sqlite.go @@ -8,7 +8,6 @@ import ( "quay/app/repository" "github.com/google/uuid" - _ "github.com/mattn/go-sqlite3" ) type SQLiteSiteRepository struct { diff --git a/backend/internal/database/sqlite.go b/backend/internal/database/sqlite.go index 7ae0da6..1ac981b 100644 --- a/backend/internal/database/sqlite.go +++ b/backend/internal/database/sqlite.go @@ -3,11 +3,11 @@ package database import ( "database/sql" - _ "github.com/mattn/go-sqlite3" + _ "modernc.org/sqlite" ) func ConnectSQLite(dbPath string) (*sql.DB, error) { - db, err := sql.Open("sqlite3", dbPath+"?_busy_timeout=5000&_journal_mode=WAL") + db, err := sql.Open("sqlite", dbPath+"?_busy_timeout=5000&_journal_mode=WAL") if err != nil { return nil, err } diff --git a/backend/internal/database/user_sqlite.go b/backend/internal/database/user_sqlite.go index 6c9011e..fdc1664 100644 --- a/backend/internal/database/user_sqlite.go +++ b/backend/internal/database/user_sqlite.go @@ -8,7 +8,8 @@ import ( "quay/app/repository" "github.com/google/uuid" - "github.com/mattn/go-sqlite3" + "modernc.org/sqlite" + sqlite3 "modernc.org/sqlite/lib" ) type SQLiteUserRepository struct { @@ -149,10 +150,9 @@ func (r *SQLiteUserRepository) AdminUserExists() (bool, error) { } func isSQLiteUniqueConstraintError(err error) bool { - var sqliteErr sqlite3.Error + var sqliteErr *sqlite.Error if !errors.As(err, &sqliteErr) { return false } - - return sqliteErr.Code == sqlite3.ErrConstraint && sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique + return sqliteErr.Code() == sqlite3.SQLITE_CONSTRAINT_UNIQUE } diff --git a/backend/internal/envconfig/envconfig.go b/backend/internal/envconfig/envconfig.go index 6d891f8..efcdbae 100644 --- a/backend/internal/envconfig/envconfig.go +++ b/backend/internal/envconfig/envconfig.go @@ -5,11 +5,12 @@ import ( ) type EnvConfig struct { - Port string - ConfigDir string - GithubPat string - StoragePath string - DashboardHost string + Port string + ConfigDir string + GithubPat string + StoragePath string + DashboardHost string + StaticDashboardPath string } func Load() EnvConfig { @@ -38,11 +39,14 @@ func Load() EnvConfig { dashboardHost = "localhost" } + staticDashboardPath := os.Getenv("STATIC_DASHBOARD_PATH") + return EnvConfig{ - Port: port, - ConfigDir: configDir, - GithubPat: githubPat, - StoragePath: storagePath, - DashboardHost: dashboardHost, + Port: port, + ConfigDir: configDir, + GithubPat: githubPat, + StoragePath: storagePath, + DashboardHost: dashboardHost, + StaticDashboardPath: staticDashboardPath, } } diff --git a/backend/internal/fiberconfig/fiberconfig.go b/backend/internal/fiberconfig/fiberconfig.go index ec9f095..1d3f860 100644 --- a/backend/internal/fiberconfig/fiberconfig.go +++ b/backend/internal/fiberconfig/fiberconfig.go @@ -1,25 +1,11 @@ package fiberconfig import ( - "github.com/Flussen/swagger-fiber-v3" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/logger" - "github.com/gofiber/fiber/v3/middleware/static" ) func Setup(app *fiber.App) { - app.Get("/api/docs.json", static.New("./docs/swagger.json")) - - app.Get("/api/swagger/*", swagger.New(swagger.Config{ - URL: "/api/docs.json", - Title: "mcheads.net API Documentation", - })) - - app.Use("/api", func(c fiber.Ctx) error { - c.Set("Content-Type", "application/json") - return c.Next() - }) - app.Use(logger.New(logger.Config{ Format: "[${time}] ${status} - ${method} ${path} (${latency}) - ${ip}\n", TimeFormat: "2006-01-02 15:04:05", diff --git a/backend/main.go b/backend/main.go index cfe3964..be22a6e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -3,9 +3,9 @@ package main import ( "database/sql" "log" + "os" "path/filepath" "quay/app/routes" - "quay/internal/config" "quay/internal/database" "quay/internal/envconfig" "quay/internal/fiberconfig" @@ -37,10 +37,8 @@ func main() { envCfg := envconfig.Load() - configFilePath := filepath.Join(envCfg.ConfigDir, "config.yaml") - cfg, err := config.Load(configFilePath) - if err != nil { - panic("Failed to load config: " + err.Error()) + if os.Getenv("JWT_SECRET") == "" || os.Getenv("JWT_SECRET") == "CHANGE_ME" { + log.Fatal("JWT_SECRET environment variable is not set or is set to the default value. Please set it to a secure random string before running the application.") } dbPath := filepath.Join(envCfg.ConfigDir, "db.sqlite") @@ -64,7 +62,7 @@ func main() { app := fiber.New() fiberconfig.Setup(app) - routes.Register(app, cfg, &envCfg, db) + routes.Register(app, &envCfg, db) log.Fatal(app.Listen(":" + envCfg.Port)) } diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 0c5f7e0..18f3c1b 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -6,6 +6,9 @@ services: container_name: quay env_file: - .env + environment: + - JWT_SECRET=b9bddc359f9f1b346582e9b50ce65c3c6c6242a8b6e21421a7411b325b8682c4 + - DASHBOARD_HOST=localhost ports: - '8080:4321' volumes: diff --git a/docker-compose.yml b/docker-compose.yml index f0395cb..3ad4481 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,9 @@ services: container_name: quay env_file: - .env + environment: + - JWT_SECRET=b9bddc359f9f1b346582e9b50ce65c3c6c6242a8b6e21421a7411b325b8682c4 + - DASHBOARD_HOST=localhost ports: - '8080:4321' volumes: