Skip to content

feat: add VCell account linking profile page - #114

Open
androemeda wants to merge 5 commits into
mainfrom
feat/vcell-account-linking
Open

feat: add VCell account linking profile page#114
androemeda wants to merge 5 commits into
mainfrom
feat/vcell-account-linking

Conversation

@androemeda

Copy link
Copy Markdown
Collaborator

Summary

Adds a /profile page where a logged-in user can link their VCell account - either by signing in with existing VCell credentials, or by creating a new VCell account - plus the backend routes that talk to VCell's /api/v1/users/* endpoints on their behalf.

Users authenticate with Auth0 today, but that login has no connection to a VCell identity until the two are mapped. This PR provides the UI and API for making that mapping.

Architecture

The frontend never calls vcell.cam.uchc.edu directly - every VCell call goes frontend → FastAPI → VCell.

Backend

New routes → controllers → services slice, matching the existing layering:

Route Forwards to
GET /users/vcell/mapped GET /users/mappedUser
POST /users/vcell/map POST /users/mapUser
POST /users/vcell/new POST /users/newUser
POST /users/vcell/recover POST /users/requestRecoveryEmail
DELETE /users/vcell/mapped PUT /users/unmapUser/{userName}

Each route declares both verify_auth0_token (to enforce verification) and get_bearer_token (to get the raw string to forward).

Error handling

  • mapUser returns 200 true/false, never an error status. A wrong password and a login already linked to a different VCell account are indistinguishable from the response, so false400 with a message covering both cases.
  • An empty password is a 500 on VCell's side (it digests unconditionally and throws "Empty password not allowed"). The request schema enforces min_length=1 so this is rejected as a 422 before it leaves us.
  • newUser returns an empty body, despite the spec describing it as returning the identity. Nothing is parsed from it; 409"That VCell username is already taken."
  • mappedUser returns 200 {"mapped": false} for unlinked users, not 404 - treated as a normal state, not an error.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few concrete correctness/UX issues (response model type coercion, unlink dialog double-submit, and an overly-generic unlink failure message) that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds end-to-end VCell account linking (Auth0-authenticated user ↔ VCell identity) via a new /profile UI and a new FastAPI routes → controllers → services slice that proxies VCell /api/v1/users/* identity endpoints (frontend → backend → VCell only).

Changes:

  • Add /profile page UI to link an existing VCell account, create a new one, request recovery email, and unlink.
  • Add backend VCell identity router/controllers/services + Pydantic schemas to forward identity operations to VCell.
  • Add navigation entry for Profile in the app sidebar and register the new router in backend/app/main.py.
File summaries
File Description
frontend/components/app-sidebar.tsx Adds a “Profile” nav entry under an Account section when logged in.
frontend/app/profile/page.tsx Implements the account-linking UI and calls the new backend endpoints with Auth0 tokens.
backend/app/services/vcell_identity_service.py Proxies identity-related requests to VCell /api/v1/users/*, including redirect-to-login handling.
backend/app/schemas/vcell_identity_schema.py Adds request/response models for mapping/creating/recovering/unmapping VCell identity.
backend/app/routes/vcell_identity_router.py Exposes FastAPI routes for identity linking with Auth0 verification + raw token forwarding.
backend/app/main.py Registers the new vcell_identity_router.
backend/app/controllers/vcell_identity_controller.py Maps VCell responses/errors into consistent API responses for the frontend.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +42 to +46
mapped: bool
userName: Optional[str] = None
id: Optional[float] = None
subject: Optional[str] = None
insertDate: Optional[str] = None
Comment on lines +559 to +562
<Button variant="destructive" onClick={handleUnlink}>
<Link2Off className="h-4 w-4" />
Unlink account
</Button>
Comment thread backend/app/controllers/vcell_identity_controller.py
Comment on lines +164 to +165
if not unmapped:
raise HTTPException(status_code=400, detail="Could not unlink.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants