- Updated verifyAdminAuth to check for adminToken cookie in addition to Bearer token - Added fallback to parse cookie from request headers when cookies() API fails - This fixes admin dashboard login issues where authentication was failing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
174 lines
4.3 KiB
TypeScript
174 lines
4.3 KiB
TypeScript
import { NextRequest } from 'next/server';
|
|
import { verify, sign } from 'jsonwebtoken';
|
|
import { prisma } from '@/lib/db';
|
|
import { cookies } from 'next/headers';
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET || 'fallback-secret-key';
|
|
|
|
export enum AdminPermission {
|
|
READ_USERS = 'read_users',
|
|
WRITE_USERS = 'write_users',
|
|
DELETE_USERS = 'delete_users',
|
|
READ_CONTENT = 'read_content',
|
|
WRITE_CONTENT = 'write_content',
|
|
DELETE_CONTENT = 'delete_content',
|
|
READ_ANALYTICS = 'read_analytics',
|
|
READ_CHAT = 'read_chat',
|
|
WRITE_CHAT = 'write_chat',
|
|
DELETE_CHAT = 'delete_chat',
|
|
SYSTEM_BACKUP = 'system_backup',
|
|
SYSTEM_HEALTH = 'system_health',
|
|
SUPER_ADMIN = 'super_admin'
|
|
}
|
|
|
|
export interface AdminUser {
|
|
id: string;
|
|
email: string;
|
|
name: string | null;
|
|
role: string;
|
|
}
|
|
|
|
export async function verifyAdminAuth(request: NextRequest): Promise<AdminUser | null> {
|
|
try {
|
|
let token: string | null = null;
|
|
|
|
// First try to get token from Authorization header
|
|
const authHeader = request.headers.get('authorization');
|
|
if (authHeader?.startsWith('Bearer ')) {
|
|
token = authHeader.substring(7);
|
|
}
|
|
|
|
// If no Authorization header, try to get token from cookie
|
|
if (!token) {
|
|
try {
|
|
const cookieStore = await cookies();
|
|
token = cookieStore.get('adminToken')?.value || null;
|
|
} catch (error) {
|
|
// If cookies() fails (e.g., in middleware), try to get cookie from request headers
|
|
const cookieHeader = request.headers.get('cookie');
|
|
if (cookieHeader) {
|
|
const matches = cookieHeader.match(/adminToken=([^;]+)/);
|
|
if (matches) {
|
|
token = matches[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!token) {
|
|
return null;
|
|
}
|
|
|
|
let payload: any;
|
|
try {
|
|
payload = verify(token, JWT_SECRET);
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
|
|
if (!payload.userId) {
|
|
return null;
|
|
}
|
|
|
|
const user = await prisma.user.findUnique({
|
|
where: {
|
|
id: payload.userId,
|
|
role: { in: ['admin', 'moderator'] }
|
|
},
|
|
select: {
|
|
id: true,
|
|
email: true,
|
|
name: true,
|
|
role: true
|
|
}
|
|
});
|
|
|
|
if (!user) {
|
|
return null;
|
|
}
|
|
|
|
return user;
|
|
} catch (error) {
|
|
console.error('Error verifying admin auth:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function hasAdminAccess(user: AdminUser | null): boolean {
|
|
return user?.role === 'admin' || user?.role === 'moderator';
|
|
}
|
|
|
|
export function isSuperAdmin(user: AdminUser | null): boolean {
|
|
return user?.role === 'admin';
|
|
}
|
|
|
|
// Generate JWT token for admin authentication
|
|
export function generateAdminToken(user: AdminUser): string {
|
|
return sign(
|
|
{
|
|
userId: user.id,
|
|
email: user.email,
|
|
role: user.role,
|
|
type: 'admin'
|
|
},
|
|
JWT_SECRET,
|
|
{ expiresIn: '24h' }
|
|
);
|
|
}
|
|
|
|
// Get current admin from request
|
|
export async function getCurrentAdmin(request: NextRequest): Promise<AdminUser | null> {
|
|
return await verifyAdminAuth(request);
|
|
}
|
|
|
|
// Check if user has specific permission
|
|
export function hasPermission(user: AdminUser | null, permission: AdminPermission): boolean {
|
|
if (!user) return false;
|
|
|
|
// Super admin has all permissions
|
|
if (user.role === 'admin') return true;
|
|
|
|
// Define moderator permissions
|
|
const moderatorPermissions = [
|
|
AdminPermission.READ_USERS,
|
|
AdminPermission.WRITE_USERS,
|
|
AdminPermission.READ_CONTENT,
|
|
AdminPermission.WRITE_CONTENT,
|
|
AdminPermission.DELETE_CONTENT,
|
|
AdminPermission.READ_ANALYTICS,
|
|
AdminPermission.READ_CHAT,
|
|
AdminPermission.WRITE_CHAT
|
|
];
|
|
|
|
// Check if moderator has the requested permission
|
|
if (user.role === 'moderator') {
|
|
return moderatorPermissions.includes(permission);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Get user permissions based on role
|
|
export function getUserPermissions(user: AdminUser | null): AdminPermission[] {
|
|
if (!user) return [];
|
|
|
|
if (user.role === 'admin') {
|
|
// Admin has all permissions
|
|
return Object.values(AdminPermission);
|
|
}
|
|
|
|
if (user.role === 'moderator') {
|
|
return [
|
|
AdminPermission.READ_USERS,
|
|
AdminPermission.WRITE_USERS,
|
|
AdminPermission.READ_CONTENT,
|
|
AdminPermission.WRITE_CONTENT,
|
|
AdminPermission.DELETE_CONTENT,
|
|
AdminPermission.READ_ANALYTICS,
|
|
AdminPermission.READ_CHAT,
|
|
AdminPermission.WRITE_CHAT
|
|
];
|
|
}
|
|
|
|
return [];
|
|
} |