Your commit message here

This commit is contained in:
Chop
2025-06-25 00:22:12 +02:00
parent 4b2a544870
commit 035a0386d7
16 changed files with 1091 additions and 19 deletions

116
src/lib/middleware/auth.js Normal file
View File

@@ -0,0 +1,116 @@
import { getToken } from "next-auth/jwt"
import { NextResponse } from "next/server"
import db from "../db.js"
// Role hierarchy for permission checking
const ROLE_HIERARCHY = {
'admin': 4,
'project_manager': 3,
'user': 2,
'read_only': 1
}
export function withAuth(handler, options = {}) {
return async (req, context) => {
try {
const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET })
// Check if user is authenticated
if (!token?.userId) {
return NextResponse.json(
{ error: "Authentication required" },
{ status: 401 }
)
}
// Check if user account is active
const user = db.prepare("SELECT is_active FROM users WHERE id = ?").get(token.userId)
if (!user?.is_active) {
return NextResponse.json(
{ error: "Account deactivated" },
{ status: 403 }
)
}
// Check role-based permissions
if (options.requiredRole && !hasPermission(token.role, options.requiredRole)) {
logAuditEvent(token.userId, 'ACCESS_DENIED', options.resource || 'api', req.url)
return NextResponse.json(
{ error: "Insufficient permissions" },
{ status: 403 }
)
}
// Check resource-specific permissions
if (options.checkResourceAccess) {
const hasAccess = await options.checkResourceAccess(token, context.params)
if (!hasAccess) {
return NextResponse.json(
{ error: "Access denied to this resource" },
{ status: 403 }
)
}
}
// Add user info to request
req.user = {
id: token.userId,
email: token.email,
name: token.name,
role: token.role
}
// Call the original handler
return await handler(req, context)
} catch (error) {
console.error("Auth middleware error:", error)
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
)
}
}
}
export function hasPermission(userRole, requiredRole) {
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole]
}
// Helper for read-only operations
export function withReadAuth(handler) {
return withAuth(handler, { requiredRole: 'read_only' })
}
// Helper for user-level operations
export function withUserAuth(handler) {
return withAuth(handler, { requiredRole: 'user' })
}
// Helper for project manager operations
export function withManagerAuth(handler) {
return withAuth(handler, { requiredRole: 'project_manager' })
}
// Helper for admin operations
export function withAdminAuth(handler) {
return withAuth(handler, { requiredRole: 'admin' })
}
// Audit logging helper
function logAuditEvent(userId, action, resourceType, resourceId, req = null) {
try {
db.prepare(`
INSERT INTO audit_logs (user_id, action, resource_type, resource_id, ip_address, user_agent)
VALUES (?, ?, ?, ?, ?, ?)
`).run(
userId,
action,
resourceType,
resourceId,
req?.ip || req?.socket?.remoteAddress || 'unknown',
req?.headers?.['user-agent'] || 'unknown'
)
} catch (error) {
console.error("Audit log error:", error)
}
}