import type { NextRequest } from 'next/server'; import { supabase } from '@/lib/supabase'; import type { User } from '@/types/database'; export type AuthContext = { user: User; isAdmin: boolean; accessibleProjectIds: string[]; }; export async function getAuthContext(request: NextRequest): Promise { const userId = request.cookies.get('okr_user_id')?.value; if (!userId) return null; const { data: user, error: userError } = await supabase .from('users') .select('id,name,role,avatar_url,username,created_at,updated_at') .eq('id', userId) .maybeSingle(); if (userError || !user) return null; const isAdmin = user.role === 'owner'; const accessibleProjectIds = await getAccessibleProjectIds(user.id, isAdmin); return { user, isAdmin, accessibleProjectIds }; } export async function getAccessibleProjectIds(userId: string, isAdmin: boolean) { if (isAdmin) return []; const [projectsRes, memberRes] = await Promise.all([ supabase .from('projects') .select('id') .or(`owner_id.eq.${userId},pm_id.eq.${userId}`), supabase .from('project_members') .select('project_id') .eq('user_id', userId), ]); const ids = new Set(); if (projectsRes.data) { for (const row of projectsRes.data as Array<{ id: string }>) ids.add(row.id); } if (memberRes.data) { for (const row of memberRes.data as Array<{ project_id: string }>) ids.add(row.project_id); } return Array.from(ids); } export function ensureAuthenticated(ctx: AuthContext | null) { if (!ctx) { return { ok: false as const, status: 401, error: '未登录' }; } return { ok: true as const }; } export function ensureAdmin(ctx: AuthContext | null) { if (!ctx) { return { ok: false as const, status: 401, error: '未登录' }; } if (!ctx.isAdmin) { return { ok: false as const, status: 403, error: '无权限' }; } return { ok: true as const }; } export function hasProjectAccess(ctx: AuthContext, projectId: string | null | undefined) { if (ctx.isAdmin) return true; if (!projectId) return false; return ctx.accessibleProjectIds.includes(projectId); }