mirror of
https://github.com/kjanat/livedash-node.git
synced 2026-01-16 14:12:10 +01:00
fix: resolve all TypeScript compilation errors and enable production build
- Fixed missing type imports in lib/api/index.ts - Updated Zod error property from 'errors' to 'issues' for compatibility - Added missing lru-cache dependency for performance caching - Fixed LRU Cache generic type constraints for TypeScript compliance - Resolved Map iteration ES5 compatibility issues using Array.from() - Fixed Redis configuration by removing unsupported socket options - Corrected Prisma relationship naming (auditLogs vs securityAuditLogs) - Applied type casting for missing database schema fields - Created missing security types file for enhanced security service - Disabled deprecated ESLint during build (using Biome for linting) - Removed deprecated critters dependency and disabled CSS optimization - Achieved successful production build with all 47 pages generated
This commit is contained in:
390
lib/api/authorization.ts
Normal file
390
lib/api/authorization.ts
Normal file
@ -0,0 +1,390 @@
|
||||
/**
|
||||
* Centralized Authorization System
|
||||
*
|
||||
* Provides role-based access control with granular permissions,
|
||||
* company-level access control, and audit trail integration.
|
||||
*/
|
||||
|
||||
import { AuthorizationError } from "./errors";
|
||||
import type { APIContext } from "./handler";
|
||||
|
||||
/**
|
||||
* System permissions enumeration
|
||||
*/
|
||||
export enum Permission {
|
||||
// Audit & Security
|
||||
READ_AUDIT_LOGS = "audit_logs:read",
|
||||
EXPORT_AUDIT_LOGS = "audit_logs:export",
|
||||
MANAGE_SECURITY = "security:manage",
|
||||
|
||||
// User Management
|
||||
READ_USERS = "users:read",
|
||||
MANAGE_USERS = "users:manage",
|
||||
INVITE_USERS = "users:invite",
|
||||
|
||||
// Company Management
|
||||
READ_COMPANIES = "companies:read",
|
||||
MANAGE_COMPANIES = "companies:manage",
|
||||
MANAGE_COMPANY_SETTINGS = "companies:settings",
|
||||
|
||||
// Dashboard & Analytics
|
||||
READ_DASHBOARD = "dashboard:read",
|
||||
READ_SESSIONS = "sessions:read",
|
||||
MANAGE_SESSIONS = "sessions:manage",
|
||||
|
||||
// System Administration
|
||||
PLATFORM_ADMIN = "platform:admin",
|
||||
CACHE_MANAGE = "cache:manage",
|
||||
SCHEDULER_MANAGE = "schedulers:manage",
|
||||
|
||||
// AI & Processing
|
||||
MANAGE_AI_PROCESSING = "ai:manage",
|
||||
READ_AI_METRICS = "ai:read",
|
||||
|
||||
// Import & Export
|
||||
IMPORT_DATA = "data:import",
|
||||
EXPORT_DATA = "data:export",
|
||||
}
|
||||
|
||||
/**
|
||||
* User roles with their associated permissions
|
||||
*/
|
||||
export const ROLE_PERMISSIONS: Record<string, Permission[]> = {
|
||||
USER: [Permission.READ_DASHBOARD, Permission.READ_SESSIONS],
|
||||
|
||||
AUDITOR: [
|
||||
Permission.READ_DASHBOARD,
|
||||
Permission.READ_SESSIONS,
|
||||
Permission.READ_AUDIT_LOGS,
|
||||
Permission.EXPORT_AUDIT_LOGS,
|
||||
Permission.READ_AI_METRICS,
|
||||
],
|
||||
|
||||
ADMIN: [
|
||||
// Inherit USER permissions
|
||||
Permission.READ_DASHBOARD,
|
||||
Permission.READ_SESSIONS,
|
||||
Permission.MANAGE_SESSIONS,
|
||||
|
||||
// Inherit AUDITOR permissions
|
||||
Permission.READ_AUDIT_LOGS,
|
||||
Permission.EXPORT_AUDIT_LOGS,
|
||||
Permission.READ_AI_METRICS,
|
||||
|
||||
// Admin-specific permissions
|
||||
Permission.READ_USERS,
|
||||
Permission.MANAGE_USERS,
|
||||
Permission.INVITE_USERS,
|
||||
Permission.MANAGE_COMPANY_SETTINGS,
|
||||
Permission.MANAGE_SECURITY,
|
||||
Permission.MANAGE_AI_PROCESSING,
|
||||
Permission.IMPORT_DATA,
|
||||
Permission.EXPORT_DATA,
|
||||
Permission.CACHE_MANAGE,
|
||||
],
|
||||
|
||||
PLATFORM_ADMIN: [
|
||||
// Include all ADMIN permissions
|
||||
Permission.READ_DASHBOARD,
|
||||
Permission.READ_SESSIONS,
|
||||
Permission.MANAGE_SESSIONS,
|
||||
Permission.READ_AUDIT_LOGS,
|
||||
Permission.EXPORT_AUDIT_LOGS,
|
||||
Permission.READ_AI_METRICS,
|
||||
Permission.READ_USERS,
|
||||
Permission.MANAGE_USERS,
|
||||
Permission.INVITE_USERS,
|
||||
Permission.MANAGE_COMPANY_SETTINGS,
|
||||
Permission.MANAGE_SECURITY,
|
||||
Permission.MANAGE_AI_PROCESSING,
|
||||
Permission.IMPORT_DATA,
|
||||
Permission.EXPORT_DATA,
|
||||
Permission.CACHE_MANAGE,
|
||||
|
||||
// Platform-specific permissions
|
||||
Permission.PLATFORM_ADMIN,
|
||||
Permission.READ_COMPANIES,
|
||||
Permission.MANAGE_COMPANIES,
|
||||
Permission.SCHEDULER_MANAGE,
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Resource types for company-level access control
|
||||
*/
|
||||
export enum ResourceType {
|
||||
AUDIT_LOG = "audit_log",
|
||||
SESSION = "session",
|
||||
USER = "user",
|
||||
COMPANY = "company",
|
||||
AI_REQUEST = "ai_request",
|
||||
}
|
||||
|
||||
/**
|
||||
* Company access validation result
|
||||
*/
|
||||
export interface CompanyAccessResult {
|
||||
allowed: boolean;
|
||||
reason?: string;
|
||||
companyId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user has a specific permission
|
||||
*/
|
||||
export function hasPermission(
|
||||
userRole: string,
|
||||
permission: Permission
|
||||
): boolean {
|
||||
const rolePermissions = ROLE_PERMISSIONS[userRole];
|
||||
return rolePermissions?.includes(permission) ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user has any of the specified permissions
|
||||
*/
|
||||
export function hasAnyPermission(
|
||||
userRole: string,
|
||||
permissions: Permission[]
|
||||
): boolean {
|
||||
return permissions.some((permission) => hasPermission(userRole, permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user has all of the specified permissions
|
||||
*/
|
||||
export function hasAllPermissions(
|
||||
userRole: string,
|
||||
permissions: Permission[]
|
||||
): boolean {
|
||||
return permissions.every((permission) => hasPermission(userRole, permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all permissions for a user role
|
||||
*/
|
||||
export function getUserPermissions(userRole: string): Permission[] {
|
||||
return ROLE_PERMISSIONS[userRole] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate permission access and throw if unauthorized
|
||||
*/
|
||||
export function requirePermission(permission: Permission) {
|
||||
return (context: APIContext) => {
|
||||
if (!context.user) {
|
||||
throw new AuthorizationError("Authentication required");
|
||||
}
|
||||
|
||||
if (!hasPermission(context.user.role, permission)) {
|
||||
throw new AuthorizationError(`Permission required: ${permission}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate any of the specified permissions
|
||||
*/
|
||||
export function requireAnyPermission(permissions: Permission[]) {
|
||||
return (context: APIContext) => {
|
||||
if (!context.user) {
|
||||
throw new AuthorizationError("Authentication required");
|
||||
}
|
||||
|
||||
if (!hasAnyPermission(context.user.role, permissions)) {
|
||||
throw new AuthorizationError(
|
||||
`One of these permissions required: ${permissions.join(", ")}`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all of the specified permissions
|
||||
*/
|
||||
export function requireAllPermissions(permissions: Permission[]) {
|
||||
return (context: APIContext) => {
|
||||
if (!context.user) {
|
||||
throw new AuthorizationError("Authentication required");
|
||||
}
|
||||
|
||||
if (!hasAllPermissions(context.user.role, permissions)) {
|
||||
throw new AuthorizationError(
|
||||
`All of these permissions required: ${permissions.join(", ")}`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can access resources from a specific company
|
||||
*/
|
||||
export function validateCompanyAccess(
|
||||
context: APIContext,
|
||||
targetCompanyId: string,
|
||||
resourceType?: ResourceType
|
||||
): CompanyAccessResult {
|
||||
if (!context.user) {
|
||||
return {
|
||||
allowed: false,
|
||||
reason: "Authentication required",
|
||||
};
|
||||
}
|
||||
|
||||
// Platform admins can access all companies
|
||||
if (context.user.role === "PLATFORM_ADMIN") {
|
||||
return {
|
||||
allowed: true,
|
||||
companyId: targetCompanyId,
|
||||
};
|
||||
}
|
||||
|
||||
// Regular users can only access their own company's resources
|
||||
if (context.user.companyId !== targetCompanyId) {
|
||||
return {
|
||||
allowed: false,
|
||||
reason: `Access denied to company ${targetCompanyId}`,
|
||||
companyId: context.user.companyId,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
allowed: true,
|
||||
companyId: targetCompanyId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Require company access validation
|
||||
*/
|
||||
export function requireCompanyAccess(
|
||||
targetCompanyId: string,
|
||||
resourceType?: ResourceType
|
||||
) {
|
||||
return (context: APIContext) => {
|
||||
const accessResult = validateCompanyAccess(
|
||||
context,
|
||||
targetCompanyId,
|
||||
resourceType
|
||||
);
|
||||
|
||||
if (!accessResult.allowed) {
|
||||
throw new AuthorizationError(accessResult.reason);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract company ID from request and validate access
|
||||
*/
|
||||
export function requireCompanyAccessFromRequest(
|
||||
getCompanyId: (context: APIContext) => string | Promise<string>,
|
||||
resourceType?: ResourceType
|
||||
) {
|
||||
return async (context: APIContext) => {
|
||||
const companyId = await getCompanyId(context);
|
||||
const accessResult = validateCompanyAccess(
|
||||
context,
|
||||
companyId,
|
||||
resourceType
|
||||
);
|
||||
|
||||
if (!accessResult.allowed) {
|
||||
throw new AuthorizationError(accessResult.reason);
|
||||
}
|
||||
|
||||
return companyId;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Role hierarchy helper - check if role A is higher than role B
|
||||
*/
|
||||
export function isRoleHigherThan(roleA: string, roleB: string): boolean {
|
||||
const roleHierarchy = {
|
||||
USER: 1,
|
||||
AUDITOR: 2,
|
||||
ADMIN: 3,
|
||||
PLATFORM_ADMIN: 4,
|
||||
};
|
||||
|
||||
const levelA = roleHierarchy[roleA as keyof typeof roleHierarchy] || 0;
|
||||
const levelB = roleHierarchy[roleB as keyof typeof roleHierarchy] || 0;
|
||||
|
||||
return levelA > levelB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can manage another user (role hierarchy)
|
||||
*/
|
||||
export function canManageUser(
|
||||
managerRole: string,
|
||||
targetUserRole: string
|
||||
): boolean {
|
||||
// Platform admins can manage anyone
|
||||
if (managerRole === "PLATFORM_ADMIN") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Admins can manage users and auditors, but not other admins or platform admins
|
||||
if (managerRole === "ADMIN") {
|
||||
return ["USER", "AUDITOR"].includes(targetUserRole);
|
||||
}
|
||||
|
||||
// Other roles cannot manage users
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require user management permission
|
||||
*/
|
||||
export function requireUserManagementPermission(targetUserRole: string) {
|
||||
return (context: APIContext) => {
|
||||
if (!context.user) {
|
||||
throw new AuthorizationError("Authentication required");
|
||||
}
|
||||
|
||||
if (!canManageUser(context.user.role, targetUserRole)) {
|
||||
throw new AuthorizationError(
|
||||
`Insufficient permissions to manage ${targetUserRole} users`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a permission checker function
|
||||
*/
|
||||
export function createPermissionChecker(context: APIContext) {
|
||||
return {
|
||||
has: (permission: Permission) =>
|
||||
hasPermission(context.user?.role || "", permission),
|
||||
hasAny: (permissions: Permission[]) =>
|
||||
hasAnyPermission(context.user?.role || "", permissions),
|
||||
hasAll: (permissions: Permission[]) =>
|
||||
hasAllPermissions(context.user?.role || "", permissions),
|
||||
require: (permission: Permission) => requirePermission(permission)(context),
|
||||
requireAny: (permissions: Permission[]) =>
|
||||
requireAnyPermission(permissions)(context),
|
||||
requireAll: (permissions: Permission[]) =>
|
||||
requireAllPermissions(permissions)(context),
|
||||
canAccessCompany: (companyId: string, resourceType?: ResourceType) =>
|
||||
validateCompanyAccess(context, companyId, resourceType),
|
||||
requireCompanyAccess: (companyId: string, resourceType?: ResourceType) =>
|
||||
requireCompanyAccess(companyId, resourceType)(context),
|
||||
canManageUser: (targetUserRole: string) =>
|
||||
canManageUser(context.user?.role || "", targetUserRole),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware function to attach permission checker to context
|
||||
*/
|
||||
export function withPermissions<T extends APIContext>(
|
||||
context: T
|
||||
): T & { permissions: ReturnType<typeof createPermissionChecker> } {
|
||||
return {
|
||||
...context,
|
||||
permissions: createPermissionChecker(context),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user