From 685ae341d67fb1d054123496dc564a0be80b4596 Mon Sep 17 00:00:00 2001 From: datadunia Date: Thu, 21 May 2026 14:18:18 +0700 Subject: [PATCH] chore: add CORS config, plan doc, update submodule --- .env.example | 10 +++ .sisyphus/plans/nxg-fix-cors.md | 111 ++++++++++++++++++++++++++++++++ apps/server-core | 2 +- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 .sisyphus/plans/nxg-fix-cors.md diff --git a/.env.example b/.env.example index 44f9316..cd45215 100644 --- a/.env.example +++ b/.env.example @@ -30,3 +30,13 @@ VITE_API_BASE_URL=http://localhost:8080/api/v1 # 6. General Settings GIN_MODE=release LOG_LEVEL=info + +# 7. CORS Configuration +# Comma-separated list of allowed origins for the API. +# Use '*' to allow all origins (NOT recommended for production). +# Example: https://dash.yourdomain.com,https://admin.yourdomain.com +CORS_ALLOWED_ORIGINS=http://localhost:5173 + +# 8. Share Link Configuration +# TTL for peer config share links (Go duration format) +SHARE_LINK_TTL=24h diff --git a/.sisyphus/plans/nxg-fix-cors.md b/.sisyphus/plans/nxg-fix-cors.md new file mode 100644 index 0000000..252f030 --- /dev/null +++ b/.sisyphus/plans/nxg-fix-cors.md @@ -0,0 +1,111 @@ +# Plan: Fix CORS Configuration + +**Scope**: Trivial — 3 files, ~20 lines +**Goal**: Ensure server-core CORS properly accepts requests from frontend origins, configurable via `CORS_ALLOWED_ORIGINS` env var, documented in `.env.example`. + +--- + +## Context + +Current CORS config in `main.go:114-130`: +- Uses `CORS_ALLOWED_ORIGINS` env var (defaults to `*`) +- Has BOTH `AllowOrigins` AND `AllowOriginFunc` — redundant +- `strings.Contains(corsOrigins, origin)` is weak (substring match: `"example.com"` matches `"notexample.com"`) +- `AllowCredentials: true` is needed for JWT `Authorization` header +- `CORS_ALLOWED_ORIGINS` is NOT documented in any `.env.example` file +- `SHARE_LINK_TTL` (from Phase 5.0) also missing from `.env.example` + +--- + +## Task 1: Fix CORS config in `main.go` + +**File**: `apps/server-core/main.go` lines 114-130 + +**Replace** the current CORS block with: + +```go +// CORS Configuration +corsOrigins := os.Getenv("CORS_ALLOWED_ORIGINS") +if corsOrigins == "" { + corsOrigins = "*" +} + +corsConfig := cors.Config{ + AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"}, + AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-Admin-Key", "X-Device-Token"}, + ExposeHeaders: []string{"Content-Length"}, + AllowCredentials: true, +} + +if corsOrigins == "*" { + // Wildcard: allow all origins but use AllowOriginFunc so the response + // header echoes the actual origin (required when AllowCredentials=true). + corsConfig.AllowOriginFunc = func(origin string) bool { + return true + } +} else { + // Explicit list: split by comma, trim spaces, exact match only. + origins := strings.Split(corsOrigins, ",") + for i := range origins { + origins[i] = strings.TrimSpace(origins[i]) + } + corsConfig.AllowOrigins = origins +} + +r.Use(cors.New(corsConfig)) +``` + +**Key changes**: +1. Remove simultaneous `AllowOrigins` + `AllowOriginFunc` (pick one based on `*` vs explicit) +2. When `*`: use `AllowOriginFunc` returning `true` → gin-contrib/cors echoes the requesting origin (compatible with `AllowCredentials: true`) +3. When explicit: use `AllowOrigins` with trimmed values, exact match (no more `strings.Contains` substring bug) + +**Verify**: `go build ./...` passes + +--- + +## Task 2: Add `CORS_ALLOWED_ORIGINS` to root `.env.example` + +**File**: `.env.example` + +**Add** after `VITE_API_BASE_URL` line (section 5): + +```env +# 7. CORS Configuration +# Comma-separated list of allowed origins for the API. +# Use '*' to allow all origins (NOT recommended for production). +# Example: https://dash.yourdomain.com,https://admin.yourdomain.com +CORS_ALLOWED_ORIGINS=http://localhost:5173 + +# 8. Share Link Configuration +# TTL for peer config share links (Go duration format) +SHARE_LINK_TTL=24h +``` + +--- + +## Task 3: Add `CORS_ALLOWED_ORIGINS` to server-core `.env.example` + +**File**: `apps/server-core/.env.example` + +**Add** at the end: + +```env +# CORS +# Comma-separated allowed origins. '*' = allow all (not recommended for production) +CORS_ALLOWED_ORIGINS=http://localhost:5173 + +# Share Link TTL (Go duration format) +SHARE_LINK_TTL=24h +``` + +**Verify**: all `.env.example` files contain `CORS_ALLOWED_ORIGINS` + +--- + +## Final Verification Wave + +- [ ] `go build ./...` passes in `apps/server-core/` +- [ ] `CORS_ALLOWED_ORIGINS` present in root `.env.example` +- [ ] `CORS_ALLOWED_ORIGINS` present in `apps/server-core/.env.example` +- [ ] No other files reference `CORS_ALLOWED_ORIGINS` that need updating diff --git a/apps/server-core b/apps/server-core index 24b32dc..fae1abf 160000 --- a/apps/server-core +++ b/apps/server-core @@ -1 +1 @@ -Subproject commit 24b32dc831d9fad095d1c04684bcda838a1ec0a2 +Subproject commit fae1abf339f93e89f53397f513e047c325df170a