Ticket 4.0 extension: Extended Supabase, Auth flow and persistent Profile schema#16
Conversation
Greptile SummaryImplements complete authentication system with Supabase Auth (sign-up, sign-in, password reset) and persistent user profiles. Creates Key Changes:
Notes:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant ProfilePage
participant AuthLib
participant ProfileLib
participant Supabase
participant Database
Note over User,Database: Sign Up Flow
User->>ProfilePage: Enter first name, last name, email, password
ProfilePage->>AuthLib: signUp(email, password, {firstName, lastName})
AuthLib->>Supabase: auth.signUp with user_metadata
Supabase->>Database: INSERT into auth.users
Database->>Database: Trigger: handle_new_user()
Database->>Database: INSERT into public.profiles
Supabase-->>AuthLib: return user + session
AuthLib-->>ProfilePage: Success
ProfilePage-->>User: Show success message
Note over User,Database: Sign In Flow
User->>ProfilePage: Enter email, password
ProfilePage->>AuthLib: signIn(email, password)
AuthLib->>Supabase: auth.signInWithPassword
Supabase-->>AuthLib: return session
AuthLib-->>ProfilePage: Success
ProfilePage->>ProfileLib: getProfile(user.id)
ProfileLib->>Supabase: SELECT from profiles WHERE id = user.id
Note right of Supabase: RLS policy: auth.uid() = id
Supabase-->>ProfileLib: return profile data
ProfileLib-->>ProfilePage: Display profile
Note over User,Database: Update Name Flow
User->>ProfilePage: Edit and save name
ProfilePage->>AuthLib: updateUserName(firstName, lastName)
AuthLib->>Supabase: auth.updateUser with metadata
Supabase-->>AuthLib: Success
ProfilePage->>ProfileLib: updateProfile(user.id, {first_name, last_name})
ProfileLib->>Supabase: UPSERT into profiles
Note right of Supabase: RLS policy: auth.uid() = id
Supabase-->>ProfileLib: Success
ProfilePage->>ProfileLib: getProfile(user.id)
ProfileLib-->>ProfilePage: return updated profile
ProfilePage-->>User: Show updated name
Note over User,Database: Password Reset Flow
User->>ProfilePage: Request password reset
ProfilePage->>AuthLib: requestPasswordReset(email)
AuthLib->>Supabase: auth.resetPasswordForEmail
Supabase->>User: Email with reset link
User->>ProfilePage: Click link, enter new password
ProfilePage->>AuthLib: updatePassword(newPassword)
AuthLib->>Supabase: auth.updateUser with new password
Supabase-->>AuthLib: Success
ProfilePage-->>User: Redirect to profile
Last reviewed commit: c523740 |
frontend/src/app/profile/page.tsx
Outdated
| return () => { | ||
| cancelled = true; | ||
| }; | ||
| }, [user?.id]); |
There was a problem hiding this comment.
Dependency array uses user?.id but should use user to re-fetch when user changes, not just when ID changes (which never happens for same user object).
| }, [user?.id]); | |
| }, [user]); |
| const testEmail = process.env.NEXT_PUBLIC_TEST_USER_EMAIL; | ||
| const testPassword = process.env.NEXT_PUBLIC_TEST_USER_PASSWORD; |
There was a problem hiding this comment.
Test credentials will be embedded in the client bundle (visible in browser DevTools and production builds) because NEXT_PUBLIC_* vars are exposed to the browser. Remove this feature or move auth to a server API route.
| first_name text, | ||
| last_name text, | ||
| display_name text, | ||
| canvas_api_key text, |
There was a problem hiding this comment.
Canvas API keys stored in plaintext - consider Supabase Vault encryption before production.
|
@greptile |
|
@greptile |
| { | ||
| id: userId, | ||
| ...updates, | ||
| updated_at: new Date().toISOString(), |
There was a problem hiding this comment.
Client-side timestamp can drift from server time. Consider adding a database trigger to auto-update updated_at on row modifications, or omit this field and let Postgres handle it.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Feature(Auth & Profile):
Implement Supabase Auth flow and persistent Profile schema
PR Summary
This PR adds working login (sign-in, sign-up, forgot password), a profile section where users can view and edit their name, and connects profile data to Supabase via a
public.profilestable with RLS and versioned migrations. Future profile features and user-scoped data can be added by extendingprofilesor new tables linked byuser_id.Overview
What feature/problem does this PR address?
What approach was taken?
public.profilestable viagetProfile/updateProfile(upsert). RLS limits access to the current user’s row; an insert policy allows creating a profile row on first save if missing.public.profilestable withid,email,first_name,last_name,display_name,canvas_api_key,created_at,updated_at. Trigger creates a profile row on sign-up; migrations add columns and policies over time (run in Supabase SQL Editor; seesupabase/README.md).Design decisions / trade-offs:
profilestable per user (no separate “user settings” table yet) to keep schema simple; new user-level settings can be added as columns or new tables withuser_id..sqlfile for clarity and safe updates.profilesfor future use; key should be used server-side only when calling Canvas.Checklist
supabase/README.md,SUMMARY.md(this file)Additional Notes
http://localhost:3000/profile/reset-password.NEXT_PUBLIC_TEST_USER_EMAILandNEXT_PUBLIC_TEST_USER_PASSWORDin.env.localand create that user in Supabase with “Auto Confirm User” enabled.user_id+ RLS, and backend/API routes that read profile data (e.g.canvas_api_key) from the DB.Jira Ticket
Jira Ticket(s) - (Not added yet)