Add complete user authentication with NextAuth.js supporting: - Email/password credentials authentication - OAuth providers (GitHub, Google) with optional configuration - JWT-based session management with 30-day expiry - Role-based access control (USER, GROWER, FARM_MANAGER, ADMIN) - Permission system with granular access control - Secure password hashing with bcrypt (12 rounds) - Rate limiting on auth endpoints - Password reset flow with secure tokens - Email verification system Files added: - lib/auth/: Core auth library (types, permissions, context, hooks, middleware) - pages/api/auth/: Auth API routes (NextAuth, register, forgot-password, verify-email) - pages/auth/: Auth pages (signin, signup, forgot-password, reset-password, verify-email) - components/auth/: Reusable auth components (LoginForm, RegisterForm, AuthGuard, etc.) Updated _app.tsx to include SessionProvider for auth state management.
107 lines
2.6 KiB
TypeScript
107 lines
2.6 KiB
TypeScript
import { UserRole } from './types'
|
|
|
|
export const ROLE_HIERARCHY: Record<UserRole, number> = {
|
|
[UserRole.USER]: 0,
|
|
[UserRole.GROWER]: 1,
|
|
[UserRole.FARM_MANAGER]: 2,
|
|
[UserRole.ADMIN]: 3,
|
|
}
|
|
|
|
export const ROLE_PERMISSIONS: Record<UserRole, string[]> = {
|
|
[UserRole.USER]: [
|
|
'plants:read',
|
|
'plants:register',
|
|
'transport:read',
|
|
'demand:read',
|
|
'demand:signal',
|
|
'transparency:read',
|
|
],
|
|
[UserRole.GROWER]: [
|
|
'plants:read',
|
|
'plants:write',
|
|
'plants:register',
|
|
'plants:clone',
|
|
'transport:read',
|
|
'transport:write',
|
|
'demand:read',
|
|
'demand:signal',
|
|
'demand:supply',
|
|
'transparency:read',
|
|
'environment:read',
|
|
'environment:write',
|
|
],
|
|
[UserRole.FARM_MANAGER]: [
|
|
'plants:read',
|
|
'plants:write',
|
|
'plants:register',
|
|
'plants:clone',
|
|
'plants:delete',
|
|
'transport:read',
|
|
'transport:write',
|
|
'demand:read',
|
|
'demand:signal',
|
|
'demand:supply',
|
|
'demand:forecast',
|
|
'transparency:read',
|
|
'transparency:write',
|
|
'environment:read',
|
|
'environment:write',
|
|
'vertical-farm:read',
|
|
'vertical-farm:write',
|
|
'vertical-farm:manage',
|
|
],
|
|
[UserRole.ADMIN]: [
|
|
'plants:*',
|
|
'transport:*',
|
|
'demand:*',
|
|
'transparency:*',
|
|
'environment:*',
|
|
'vertical-farm:*',
|
|
'users:*',
|
|
'system:*',
|
|
],
|
|
}
|
|
|
|
export function hasPermission(role: UserRole, permission: string): boolean {
|
|
const permissions = ROLE_PERMISSIONS[role] || []
|
|
|
|
// Check for exact match
|
|
if (permissions.includes(permission)) {
|
|
return true
|
|
}
|
|
|
|
// Check for wildcard permissions (e.g., 'plants:*' matches 'plants:read')
|
|
const [resource] = permission.split(':')
|
|
const wildcardPermission = `${resource}:*`
|
|
if (permissions.includes(wildcardPermission)) {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export function hasRole(userRole: UserRole, requiredRole: UserRole): boolean {
|
|
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole]
|
|
}
|
|
|
|
export function hasAnyPermission(role: UserRole, permissions: string[]): boolean {
|
|
return permissions.some(permission => hasPermission(role, permission))
|
|
}
|
|
|
|
export function hasAllPermissions(role: UserRole, permissions: string[]): boolean {
|
|
return permissions.every(permission => hasPermission(role, permission))
|
|
}
|
|
|
|
export function getRoleLabel(role: UserRole): string {
|
|
const labels: Record<UserRole, string> = {
|
|
[UserRole.USER]: 'User',
|
|
[UserRole.GROWER]: 'Grower',
|
|
[UserRole.FARM_MANAGER]: 'Farm Manager',
|
|
[UserRole.ADMIN]: 'Administrator',
|
|
}
|
|
return labels[role] || 'Unknown'
|
|
}
|
|
|
|
export function getAvailableRoles(): UserRole[] {
|
|
return Object.values(UserRole)
|
|
}
|