import type { DatabaseClient } from "./database"; import { getRequestPrincipal } from "./user-auth"; export type OwnerScope = | { kind: "full" } | { kind: "owner"; wecomUserId: string }; export async function getOwnerScope(request: Request): Promise { const principal = await getRequestPrincipal(request); if (!principal) return { kind: "owner", wecomUserId: "" }; if (principal.kind === "internal") return { kind: "full" }; if ( principal.user.role === "super_admin" || principal.user.role === "admin" ) { return { kind: "full" }; } return { kind: "owner", wecomUserId: principal.user.wecom_userid ?? "" }; } export function ownerScopeUserid(scope: OwnerScope): string | undefined { return scope.kind === "owner" ? scope.wecomUserId : undefined; } export async function isTaskOwner( db: DatabaseClient, taskId: string, wecomUserId: string, options?: { strict?: boolean }, ) { const id = String(taskId ?? "").trim(); if (!id || !wecomUserId) return false; const row = await db .prepare( options?.strict ? "SELECT id FROM tasks WHERE id = ? AND owner_userid = ? LIMIT 1" : `SELECT t.id FROM tasks t LEFT JOIN projects p ON p.id = t.project_id WHERE t.id = ? AND (t.owner_userid = ? OR p.owner_userid = ?) LIMIT 1`, ) .bind(...(options?.strict ? [id, wecomUserId] : [id, wecomUserId, wecomUserId])) .first<{ id: string }>(); return Boolean(row); } export async function isDistributionOwner( db: DatabaseClient, distributionId: string, wecomUserId: string, ) { const id = String(distributionId ?? "").trim(); if (!id || !wecomUserId) return false; const row = await db .prepare( `SELECT d.id FROM distributions d JOIN tasks t ON t.id = d.task_id LEFT JOIN projects p ON p.id = t.project_id WHERE d.id = ? AND (t.owner_userid = ? OR p.owner_userid = ?) LIMIT 1`, ) .bind(id, wecomUserId, wecomUserId) .first<{ id: string }>(); return Boolean(row); } export async function isProjectOwner( db: DatabaseClient, projectId: string, wecomUserId: string, ) { const id = String(projectId ?? "").trim(); if (!id || !wecomUserId) return false; const row = await db .prepare("SELECT id FROM projects WHERE id = ? AND owner_userid = ? LIMIT 1") .bind(id, wecomUserId) .first<{ id: string }>(); return Boolean(row); } export async function isTaskProjectOwner( db: DatabaseClient, taskId: string, wecomUserId: string, ) { const id = String(taskId ?? "").trim(); if (!id || !wecomUserId) return false; const row = await db .prepare( `SELECT t.id FROM tasks t JOIN projects p ON p.id = t.project_id WHERE t.id = ? AND p.owner_userid = ? LIMIT 1`, ) .bind(id, wecomUserId) .first<{ id: string }>(); return Boolean(row); } export function ownerForbidden() { return Response.json({ error: "该任务未分配给您,无权操作" }, { status: 403 }); } export function projectForbidden() { return Response.json({ error: "您不是该项目负责人,无权操作" }, { status: 403 }); }