/**
* Admin/Moderator Access Check Utilities
*
* Centralized utilities for verifying admin and moderator access.
* Used by admin routes, API endpoints, and server actions.
*/
import { auth } from '@/auth';
import { createServerClient } from '@/lib/supabase-server';
export interface AdminCheckResult {
userId: string;
isAdmin: boolean;
isModerator: boolean;
}
/**
* Requires admin or moderator access.
* Throws an error if the user is not authenticated or lacks admin/moderator privileges.
*
* @returns User ID and role flags if authorized
* @throws Error if not authenticated or not admin/moderator
*
* @example
* ```tsx
* // In a Server Action or API route
* export async function moderatePost(postId: string) {
* const { userId, isAdmin, isModerator } = await requireAdmin();
* // User is authorized as admin or moderator
* }
* ```
*/
export async function requireAdmin(): Promise<AdminCheckResult> {
const session = await auth();
if (!session?.user?.id) {
throw new Error('Unauthorized: Not authenticated');
}
const supabase = await createServerClient();
const { data, error } = await supabase
.from('user_profiles')
.select('is_admin, is_moderator')
.eq('id', session.user.id)
.single();
if (error) {
console.error('Error checking admin status:', error);
throw new Error('Unauthorized: Could not verify permissions');
}
if (!data?.is_admin && !data?.is_moderator) {
throw new Error('Unauthorized: Admin or moderator access required');
}
return {
userId: session.user.id,
isAdmin: data.is_admin ?? false,
isModerator: data.is_moderator ?? false,
};
}
/**
* Requires full admin access (not just moderator).
* Use for sensitive operations like permanent bans, promoting users, etc.
*
* @returns User ID if authorized as admin
* @throws Error if not authenticated or not an admin
*
* @example
* ```tsx
* export async function promoteToModerator(userId: string) {
* const { userId: adminId } = await requireFullAdmin();
* // Only full admins can promote users
* }
* ```
*/
export async function requireFullAdmin(): Promise<AdminCheckResult> {
const result = await requireAdmin();
if (!result.isAdmin) {
throw new Error('Unauthorized: Full admin access required');
}
return result;
}
/**
* Checks if the current user has admin or moderator access without throwing.
* Returns null if not authorized.
*
* @returns User ID and role flags, or null if not authorized
*
* @example
* ```tsx
* const adminCheck = await checkAdminAccess();
* if (!adminCheck) {
* redirect('/');
* }
* ```
*/
export async function checkAdminAccess(): Promise<AdminCheckResult | null> {
try {
return await requireAdmin();
} catch {
return null;
}
}
/**
* Checks if the current user is a full admin without throwing.
*
* @returns True if user is a full admin, false otherwise
*/
export async function isFullAdmin(): Promise<boolean> {
try {
const result = await requireAdmin();
return result.isAdmin;
} catch {
return false;
}
}