feat(website): sync user with backend on login, use internal user ID#1202
Open
fhennig wants to merge 6 commits into
Open
feat(website): sync user with backend on login, use internal user ID#1202fhennig wants to merge 6 commits into
fhennig wants to merge 6 commits into
Conversation
Adds a users_table (BIGSERIAL PK, nullable github_id) with upsert via
POST /users/sync and lookup via GET /users/{id}. Migrates owned_by and
user_id columns in collections and subscriptions from GitHub ID strings
to BIGINT foreign keys referencing the new table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…/users/{id}
Extracts the shared now() instant helper into util/InstantProvider.kt to
avoid duplication across models. Adds PublicUser DTO (id + name only) so
the public GET /users/{id} endpoint does not expose email.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…trollerTest Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
42de45d to
d0613f3
Compare
…for ownership
On GitHub login, mapProfileToUser calls POST /users/sync to upsert the user
in the backend and stores the returned internal Long ID as internalUserId in
the better-auth session (stateless JWE cookie). This replaces the previous
use of the GitHub ID for ownership checks on collections and subscriptions.
- auth.ts: async mapProfileToUser syncs user, adds internalUserId additional field
- authMiddleware.ts: reads internalUserId from session user
- backendProxy.ts: forwards internalUserId as userId query param instead of githubId
- Collection.ts: ownedBy changed from string to number to match backend Long
- PublicUser.ts: new Zod schema for GET /users/{id} response
- backendService.ts: adds getUser() to resolve owner names
- pages/api/users/[id].ts: new proxy route for public user lookup
- collection detail/edit pages: use internalUserId for ownership, display owner name
- E2E tests: sync user via POST /users/sync in beforeAll to get internal ID
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(website): fix lint errors in auth.ts and authMiddleware.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refactor(website): rename internalUserId to gsUserId
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(website): make login fail if backend user sync fails, simplify gsUserId handling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(website): make ownerName non-optional, simplify collection detail page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refactor(website): simplify gsUserId assignment in authMiddleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
foo
d0613f3 to
02444de
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the website’s authentication + ownership model to use a backend-issued internal numeric user ID (synced on GitHub login) instead of the GitHub user ID, and uses that to display a human-readable owner name on collection detail pages.
Changes:
- Sync GitHub users to the backend on login (
POST /users/sync) and store the returned internal ID (gsUserId) in the session; propagategsUserIdvia middleware and backend proxy. - Switch collection/subscription ownership logic to use numeric internal user IDs (
ownedBy: number), and resolve/display owner name viaGET /users/{id}. - Update unit/browser/E2E tests and fixtures for the new numeric ownership ID model.
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| website/src/auth.ts | Sync user on GitHub login and store internal gsUserId in the session |
| website/src/middleware/authMiddleware.ts | Copy gsUserId into Astro.locals and switch locals “logged out” to undefined |
| website/src/env.d.ts | Update locals typing (undefined + add gsUserId) |
| website/src/backendApi/backendProxy.ts | Forward internal numeric user id as userId query param |
| website/src/backendApi/backendService.ts | Add getUser() for owner name resolution |
| website/src/types/PublicUser.ts | New Zod schema/type for public user response |
| website/src/types/Collection.ts | Change ownedBy from string to number |
| website/src/pages/api/users/[id].ts | Add unauthenticated proxy route for public user lookup |
| website/src/pages/collections/[organism]/[id]/index.astro | Redirect handling + owner name lookup + internal ID ownership check |
| website/src/pages/collections/[organism]/[id]/edit.astro | Use internal gsUserId for ownership checks |
| website/src/components/collections/detail/CollectionDetail.tsx | Display resolved owner name (string) |
| website/src/pages/collections/[organism]/index.astro | Switch “logged in” checks to user !== undefined |
| website/src/pages/collections/[organism]/create.astro | Switch “logged in” checks to user !== undefined |
| website/src/pages/subscriptions/index.astro | Switch “logged in” checks to user !== undefined |
| website/src/pages/subscriptions/create.astro | Switch “logged in” checks to user !== undefined |
| website/src/layouts/base/header/HamburgerMenu.astro | Switch “logged in” checks to user !== undefined |
| website/src/backendApi/backendService.spec.ts | Update fixture to numeric ownedBy |
| website/src/components/collections/overview/CollectionsOverview.browser.spec.tsx | Update fixtures to numeric ownedBy |
| website/tests/helpers/auth.ts | Update E2E session cookie payload to use gsUserId |
| website/tests/collections/collectionForm.spec.ts | Sync E2E user via backend and use internal id for collection operations |
| website/tests/collections/collectionDetail.spec.ts | Sync E2E user via backend and use internal id for collection operations |
Comments suppressed due to low confidence (1)
website/src/pages/collections/[organism]/[id]/index.astro:83
- Because the server code above now returns early when
collection === undefined, this render path can never hit the fallback branch. Simplify the template by removing the now-unreachable conditional/fallback (or revert the early redirect if you still want to show a “failed to load” message).
lapisConfig={lapisConfig}
isOwner={userIsOwner}
ownerName={ownerName}
client:load
/>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| if (response.ok) { | ||
| const user = (await response.json()) as { id: number }; | ||
| return { gsUserId: String(user.id) }; |
| createdAt: now.toISOString(), | ||
| updatedAt: now.toISOString(), | ||
| githubId: '1234567', | ||
| gsUserId: '1', |
Comment on lines
37
to
+41
| logger.error(`Failed to fetch collection ${id}: ${getErrorLogMessage(error)}`); | ||
| } | ||
|
|
||
| const collectionTitle = collection !== undefined ? `#${id} ${collection.name}` : `Collection #${id}`; | ||
| if (collection === undefined) { | ||
| return Astro.redirect('/404'); |
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.
resolves #1190
Summary
mapProfileToUsercallsPOST /users/syncto upsert the user in the backend and stores the returned internal ID asgsUserIdin the better-auth session (stateless JWE cookie)GET /users/{id}and displayed on the collection detail pageChanges
Auth & middleware
auth.ts:mapProfileToUsersyncs user with backend, storesgsUserId(number); throws on failure to abort loginauthMiddleware.ts: readsgsUserIdfrom session intoAstro.localsbackendProxy.ts: forwardsgsUserIdasuserIdquery paramTypes & API
types/Collection.ts:ownedBychanged fromstringtonumberto match backendLongtypes/PublicUser.ts: new Zod schema forGET /users/{id}responsebackendService.ts: addsgetUser()to resolve owner names server-sidepages/api/users/[id].ts: new proxy route for public user lookupCollection pages
ownerNameis always astringgsUserIdfor ownership checkTests
ownedByfrom string to number in fixturesPOST /users/syncinbeforeAllto obtain internal ID for collection ownershipNotes
This branch depends on the backend changes in
feat/user-table(users table,POST /users/sync,GET /users/{id}endpoints).🤖 Generated with Claude Code