Implements the authentication and authorization layer for the backend API. - #22
Merged
Conversation
Move ThemeProvider into a client ThemeRegistry. Replace the Next.js starter page with a temporary CivicLens UI. Co-authored-by: Cursor <cursoragent@cursor.com>
fix(frontend): UI issue fixes
There was a problem hiding this comment.
Pull request overview
This PR adds a first-pass authentication/authorization layer to the backend API (JWT auth + refresh, RBAC middleware, tenant scoping), alongside database bootstrapping (embedded migrations + initial seeding). It also includes some frontend scaffolding/theme wiring updates that appear orthogonal to the backend auth work.
Changes:
- Added JWT login/refresh endpoints plus middleware for extracting claims and enforcing permissions on protected routes.
- Introduced embedded DB migrations and a startup seeding step for an initial super-admin account.
- Updated the frontend app shell (MUI theme registry + a temporary “dev start” scaffold) and adjusted the Home page test accordingly.
Reviewed changes
Copilot reviewed 37 out of 45 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/theme/ThemeRegistry.tsx | Adds an App Router–compatible MUI theme registry wrapper. |
| frontend/src/components/DevStartScaffold.tsx | Introduces a temporary landing scaffold for frontend development. |
| frontend/src/app/page.tsx | Replaces starter page content with the dev scaffold component. |
| frontend/src/app/page.test.tsx | Updates the Home page test assertions to match the new scaffold content. |
| frontend/src/app/layout.tsx | Refactors global layout to delegate MUI setup to ThemeRegistry. |
| frontend/src/app/globals.css | Simplifies global styles to remove old background/foreground theming. |
| frontend/package-lock.json | Updates lockfile metadata (platform libc entries removed). |
| frontend/next.config.ts | Adds a Turbopack root configuration for the frontend package. |
| backend-api/tests/api/role_test.go | Adds a validation-focused test for role creation. |
| backend-api/tests/api/rbac_test.go | Adds RBAC tests for forbidden/allowed/super-admin permission cases. |
| backend-api/tests/api/auth_test.go | Adds a login success test using a mock sqlc querier. |
| backend-api/sqlc/sqlc.yaml | Adjusts sqlc paths/output location for schema/queries generation. |
| backend-api/sqlc/schema/001_multi_tenancy.sql | Adds initial multi-tenant schema definitions for sqlc parsing. |
| backend-api/sqlc/queries/users.sql | Adds user-related queries including tenant-scoped listing and role updates. |
| backend-api/sqlc/queries/roles.sql | Adds role creation and tenant-scoped role listing queries. |
| backend-api/sqlc/queries/auth.sql | Adds auth queries for users and refresh token lifecycle. |
| backend-api/Makefile | Improves cross-platform build/clean targets and adds new utility targets. |
| backend-api/internal/router/router.go | Mounts auth endpoints, configures JWT middleware, and protects routes. |
| backend-api/internal/repository/repository.go | Introduces a tenant-aware repository wrapper for entity scoping. |
| backend-api/internal/middleware/rbac.go | Adds middleware to enforce a required permission. |
| backend-api/internal/middleware/jwt.go | Adds AuthContext extraction from JWT claims and permission helpers. |
| backend-api/internal/handler/user.go | Implements create/list/update role endpoints for users. |
| backend-api/internal/handler/role.go | Implements create/list endpoints for roles. |
| backend-api/internal/handler/health.go | Adds explicit JSON error handling for the health response. |
| backend-api/internal/handler/handler.go | Adds sqlc querier wiring and a helper to construct a tenant repo. |
| backend-api/internal/handler/auth.go | Implements login/refresh endpoints and a protected /auth/me endpoint. |
| backend-api/internal/db/sqlcdb/users.sql.go | Generated sqlc code for user queries. |
| backend-api/internal/db/sqlcdb/roles.sql.go | Generated sqlc code for role queries. |
| backend-api/internal/db/sqlcdb/querier.go | Generated sqlc interface aggregating query methods. |
| backend-api/internal/db/sqlcdb/models.go | Generated sqlc models for entities/users/roles/refresh tokens. |
| backend-api/internal/db/sqlcdb/db.go | Generated sqlc DBTX wrapper and transaction support. |
| backend-api/internal/db/sqlcdb/auth.sql.go | Generated sqlc code for auth/refresh-token queries. |
| backend-api/internal/db/seed.go | Adds initial super-admin seeding logic. |
| backend-api/internal/db/seed_test.go | Adds tests for seeding idempotency and creation behavior. |
| backend-api/internal/db/migrations/000001_multi_tenancy.up.sql | Adds initial DB migration for entities/roles/users/refresh_tokens. |
| backend-api/internal/db/migrations/000001_multi_tenancy.down.sql | Adds rollback for the initial migration. |
| backend-api/internal/db/migrate.go | Adds embedded-migration runner using golang-migrate. |
| backend-api/internal/config/config.go | Adds initial account config fields and defaults. |
| backend-api/internal/config/config_test.go | Adds tests for config loading defaults and validation behavior. |
| backend-api/go.sum | Updates dependency checksums for new auth/migrate dependencies. |
| backend-api/go.mod | Updates Go version and adds dependencies for JWT, migrate, echo-jwt, etc. |
| backend-api/coverage | Adds a coverage artifact file (likely accidental). |
| backend-api/cmd/server/main.go | Runs migrations + seeding at startup and improves shutdown error check. |
| backend-api/.golangci.yml | Updates golangci-lint config format and enabled linters/comments. |
| backend-api/.env.example | Documents new env vars for initial accounts / auto-seeding. |
Files not reviewed (7)
- backend-api/internal/db/sqlcdb/auth.sql.go: Generated file
- backend-api/internal/db/sqlcdb/db.go: Generated file
- backend-api/internal/db/sqlcdb/models.go: Generated file
- backend-api/internal/db/sqlcdb/querier.go: Generated file
- backend-api/internal/db/sqlcdb/roles.sql.go: Generated file
- backend-api/internal/db/sqlcdb/users.sql.go: Generated file
- frontend/package-lock.json: Generated file
Comments suppressed due to low confidence (1)
backend-api/Makefile:108
make helpstill advertises race detection formake test, but thetesttarget only runs coverage now. This can mislead developers relying on the help output.
@echo Usage:
@echo make run - start the development server
@echo make test - run all tests with race detection
@echo make test-v - run tests with verbose output
@echo make lint - run golangci-lint
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export default function ThemeRegistry({ | ||
| children, | ||
| }: { | ||
| children: React.ReactNode; |
| return c.JSON(http.StatusUnauthorized, echo.Map{"error": "invalid token claims"}) //nolint:wrapcheck | ||
| } | ||
|
|
||
| userID := claims["sub"].(string) |
Comment on lines
+21
to
+22
| Email string `json:"email" form:"email"` | ||
| Password string `json:"password" form:"password"` |
| @@ -0,0 +1,35 @@ | |||
| CREATE TABLE entities ( | |||
| @@ -0,0 +1,35 @@ | |||
| CREATE TABLE entities ( | |||
| @@ -0,0 +1 @@ | |||
| mode: atomic | |||
| if err := c.Bind(&req); err != nil { | ||
| return c.JSON(http.StatusBadRequest, echo.Map{"error": "invalid request format"}) //nolint:wrapcheck | ||
| } | ||
|
|
Comment on lines
+14
to
+17
| -- name: UpdateUserRole :exec | ||
| UPDATE users | ||
| SET role_id = $2, updated_at = NOW() | ||
| WHERE id = $1 AND entity_id = $3; |
Comment on lines
+1
to
+4
| import DevStartScaffold from "@/components/DevStartScaffold"; | ||
|
|
||
| export default function Home() { | ||
| return ( | ||
| <div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black"> | ||
| <main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start"> | ||
| <Image | ||
| className="dark:invert" | ||
| src="/next.svg" | ||
| alt="Next.js logo" | ||
| width={100} | ||
| height={20} | ||
| priority | ||
| /> | ||
| <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left"> | ||
| <h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50"> | ||
| To get started, edit the page.tsx file. | ||
| </h1> | ||
| <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400"> | ||
| Looking for a starting point or more instructions? Head over to{" "} | ||
| <a | ||
| href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" | ||
| className="font-medium text-zinc-950 dark:text-zinc-50" | ||
| > | ||
| Templates | ||
| </a>{" "} | ||
| or the{" "} | ||
| <a | ||
| href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" | ||
| className="font-medium text-zinc-950 dark:text-zinc-50" | ||
| > | ||
| Learning | ||
| </a>{" "} | ||
| center. | ||
| </p> | ||
| </div> | ||
| <div className="flex flex-col gap-4 text-base font-medium sm:flex-row"> | ||
| <a | ||
| className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]" | ||
| href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| <Image | ||
| className="dark:invert" | ||
| src="/vercel.svg" | ||
| alt="Vercel logomark" | ||
| width={16} | ||
| height={16} | ||
| /> | ||
| Deploy Now | ||
| </a> | ||
| <a | ||
| className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]" | ||
| href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| Documentation | ||
| </a> | ||
| </div> | ||
| </main> | ||
| </div> | ||
| ); | ||
| return <DevStartScaffold />; |
| InitialUserEmail: getEnv("INITIAL_USER_EMAIL", "user@civiclens.org"), | ||
| InitialUserPassword: getEnv("INITIAL_USER_PASSWORD", "UserPass123!"), | ||
| } | ||
|
|
specfor
approved these changes
Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
entity_id,role_id, and user permissions.ExtractClaimsmiddleware to provide a strongly typed authentication context.RequirePermissionmiddleware for role-based access control (RBAC).