// Session 17 — requireAuth's on-demand users-row upsert path. // // The audit found that authenticated users with valid Supabase auth // tokens were getting 401 "User profile not found" on /api/stripe/ // checkout because their corresponding row in public.users had never // been inserted. The fix: when `.single()` on the users select // returns PGRST116 ("no rows"), upsert a default row and re-read. // // These tests build a chainable Supabase fake that lets us steer the // select to PGRST116 / success and assert which path requireAuth // takes. const { requireAuth } = require('../../src/middleware/auth'); function makeFake({ getUserResult, selectResult, selectAfterUpsertResult, upsertError = null }) { // The middleware calls `supabase.from('users')` multiple times in // the missing-profile recovery path (initial select, then upsert, // then reread). State that distinguishes "first select" from // "select-after-upsert" has to live on the supabase fake, not on // a fresh-per-call `from()` proxy. We track `hasUpserted` and // route `.single()` to the appropriate result. const upserts = []; let hasUpserted = false; const supabase = { auth: { getUser: () => Promise.resolve(getUserResult) }, from() { const proxy = { select() { return proxy; }, eq() { return proxy; }, single() { return Promise.resolve(hasUpserted ? selectAfterUpsertResult : selectResult); }, upsert(row, opts) { upserts.push({ row, opts }); if (!upsertError) hasUpserted = true; return Promise.resolve({ data: null, error: upsertError }); }, }; return proxy; }, _upserts: upserts, }; return supabase; } let mockSupabaseFake; jest.mock('../../src/utils/supabase', () => ({ getSupabaseServiceClient: () => mockSupabaseFake, })); function runMiddleware(req) { return new Promise((resolve) => { const res = { _status: null, _body: null, status(code) { this._status = code; return this; }, json(body) { this._body = body; resolve({ status: this._status, body, fellThrough: false }); return this; }, }; requireAuth(req, res, () => resolve({ status: 200, body: null, fellThrough: true, req })); }); } const VALID_USER = { id: 'user-1', email: 'a@b.com' }; const EXISTING_PROFILE = { id: 'user-1', email: 'a@b.com', tier: 'free', scan_count: 0, scan_reset_date: '2026-06-12', founder_status: false, grace_period_until: null, stripe_customer_id: null, }; describe('requireAuth — pre-Session 17 behavior preserved', () => { test('valid token + existing profile → next() called with req.user set', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: EXISTING_PROFILE, error: null }, }); const req = { headers: { authorization: 'Bearer good-token' } }; const out = await runMiddleware(req); expect(out.fellThrough).toBe(true); expect(req.user.id).toBe('user-1'); expect(req.user.tier).toBe('free'); expect(mockSupabaseFake._upserts).toHaveLength(0); }); test('missing Authorization header → 401', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: null }, error: { message: 'no' } }, selectResult: { data: null, error: null }, }); const out = await runMiddleware({ headers: {} }); expect(out.status).toBe(401); expect(out.body.error).toMatch(/Authentication required/); }); test('non-Bearer scheme → 401', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: null }, error: { message: 'no' } }, selectResult: { data: null, error: null }, }); const out = await runMiddleware({ headers: { authorization: 'Basic xyz' } }); expect(out.status).toBe(401); }); test('Supabase getUser error → 401 invalid token', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: null }, error: { message: 'token expired' } }, selectResult: { data: null, error: null }, }); const out = await runMiddleware({ headers: { authorization: 'Bearer bad' } }); expect(out.status).toBe(401); expect(out.body.error).toMatch(/Invalid or expired/); }); }); describe('requireAuth — Session 17 missing-profile recovery', () => { test('missing users row (PGRST116) → upsert default + retry succeeds', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: null, error: { code: 'PGRST116', message: 'no rows' } }, selectAfterUpsertResult: { data: EXISTING_PROFILE, error: null }, }); const req = { headers: { authorization: 'Bearer good' } }; const out = await runMiddleware(req); expect(out.fellThrough).toBe(true); expect(req.user.id).toBe('user-1'); expect(mockSupabaseFake._upserts).toHaveLength(1); const u = mockSupabaseFake._upserts[0]; expect(u.row.id).toBe('user-1'); expect(u.row.email).toBe('a@b.com'); expect(u.row.tier).toBe('free'); expect(u.row.scan_count).toBe(0); expect(u.row.founder_status).toBe(false); expect(u.opts.onConflict).toBe('id'); }); test('PGRST116 detected by message text (no code field)', async () => { // Some Supabase client versions surface the error sans code field. mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: null, error: { message: 'JSON object requested, multiple (or no) rows returned' } }, selectAfterUpsertResult: { data: EXISTING_PROFILE, error: null }, }); const out = await runMiddleware({ headers: { authorization: 'Bearer good' } }); expect(out.fellThrough).toBe(true); expect(mockSupabaseFake._upserts).toHaveLength(1); }); test('upsert itself fails → 401 with distinct message', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: null, error: { code: 'PGRST116', message: 'no rows' } }, selectAfterUpsertResult: { data: EXISTING_PROFILE, error: null }, upsertError: { message: 'check_violation' }, }); const out = await runMiddleware({ headers: { authorization: 'Bearer good' } }); expect(out.status).toBe(401); expect(out.body.error).toMatch(/User profile creation failed/); }); test('post-upsert reread still empty → 401 User profile not found', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: null, error: { code: 'PGRST116', message: 'no rows' } }, selectAfterUpsertResult: { data: null, error: null }, }); const out = await runMiddleware({ headers: { authorization: 'Bearer good' } }); expect(out.status).toBe(401); expect(out.body.error).toMatch(/User profile not found/); }); test('non-PGRST116 select error → 401 immediately (no upsert)', async () => { mockSupabaseFake = makeFake({ getUserResult: { data: { user: VALID_USER }, error: null }, selectResult: { data: null, error: { code: '42501', message: 'permission denied' } }, selectAfterUpsertResult: { data: EXISTING_PROFILE, error: null }, }); const out = await runMiddleware({ headers: { authorization: 'Bearer good' } }); expect(out.status).toBe(401); // Critically, no upsert attempt — we don't recover from a real DB error. expect(mockSupabaseFake._upserts).toHaveLength(0); }); });