diff --git a/apps/dashboard/lib/auth/actions.ts b/apps/dashboard/lib/auth/actions.ts index a3525f626..fc6fe0b95 100644 --- a/apps/dashboard/lib/auth/actions.ts +++ b/apps/dashboard/lib/auth/actions.ts @@ -24,24 +24,66 @@ import { import { deleteCookie } from './cookies'; import { redirect } from 'next/navigation'; +// Helper function to check authentication +async function requireAuth(): Promise { + const user = await auth.getCurrentUser(); + if (!user) { + redirect('/auth/sign-in'); + } + return user; +} + +// Helper function to check organization access +async function requireOrgAccess(orgId: string, userId: string): Promise { + const memberships = await auth.listMemberships(userId); + const hasAccess = memberships.data.some(m => m.organization.id === orgId); + if (!hasAccess) { + throw new Error('You do not have access to this organization'); + } +} + +// Helper to check admin status +async function requireOrgAdmin(orgId: string, userId: string): Promise { + const memberships = await auth.listMemberships(userId); + const isAdmin = memberships.data.some( + m => m.organization.id === orgId && m.role === 'admin' + ); + if (!isAdmin) { + throw new Error('This action requires admin privileges'); + } +} + export async function getCurrentUser(): Promise { return await auth.getCurrentUser(); } export async function listMemberships(userId?: string): Promise { - return await auth.listMemberships(userId); + const user = await requireAuth(); + // Only allow users to list their own memberships unless they provide a userId + if (userId && userId !== user.id) { + throw new Error('Unauthorized to view other users memberships'); + } + return await auth.listMemberships(userId || user.id); } export async function refreshSession(orgId: string): Promise { + const user = await requireAuth(); + await requireOrgAccess(orgId, user.id); return await auth.refreshSession(orgId); } export async function getSignOutUrl(): Promise { + await requireAuth(); // Ensure user is authenticated const url = await auth.getSignOutUrl(); return url; } export async function createTenant(params: { name: string, userId: string }): Promise { + const user = await requireAuth(); + // Only allow users to create tenants for themselves + if (params.userId !== user.id) { + throw new Error('Unauthorized to create tenant for another user'); + } return await auth.createTenant(params); } @@ -51,16 +93,16 @@ export async function signInViaOAuth(options: SignInViaOAuthOptions): Promise { try { + await requireAuth(); const url = await getSignOutUrl(); if (url) { - redirect(url) + redirect(url); } - else redirect("/auth/sign-in") + else redirect("/auth/sign-in"); } - catch(error) { console.error("Failed to get sign out url:", error); - redirect("/auth/sign-in") + redirect("/auth/sign-in"); } finally { await deleteCookie(UNKEY_SESSION_COOKIE); @@ -68,9 +110,13 @@ export async function signOut(): Promise { } export async function inviteMember(params: OrgInvite): Promise { + const user = await requireAuth(); + await requireOrgAdmin(params.orgId, user.id); return await auth.inviteMember(params); } export async function getOrg(orgId: string): Promise { + const user = await requireAuth(); + await requireOrgAccess(orgId, user.id); return await auth.getOrg(orgId); } \ No newline at end of file