From 413dd194ae2a5ae00203c0fc2696f67289451771 Mon Sep 17 00:00:00 2001 From: Muhammad Mustapha Date: Thu, 2 Jul 2026 00:02:09 +0100 Subject: [PATCH 1/2] fix: add missing User schema fields (createdAt, updatedAt, emailVerified) --- src/schemas/user.schema.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/schemas/user.schema.ts b/src/schemas/user.schema.ts index e98947cd..9bbadece 100644 --- a/src/schemas/user.schema.ts +++ b/src/schemas/user.schema.ts @@ -10,6 +10,9 @@ export const UserSchema = z.object({ referralCode: z.string().optional(), referredBy: z.string().optional(), referralCount: z.number().default(0), + createdAt: z.string(), // ISO 8601 date string + updatedAt: z.string(), // ISO 8601 date string + emailVerified: z.boolean().default(false), }); export type User = z.infer; From ee1b77ccb3c5f85d3e3530056676bde4b9c6c411 Mon Sep 17 00:00:00 2001 From: Muhammad Mustapha Date: Fri, 3 Jul 2026 21:52:56 +0100 Subject: [PATCH 2/2] fix(types): narrow getUserFromRequest return type to subset of User --- src/lib/auth/acl.ts | 18 ++++++++++++------ src/lib/authMiddleware.ts | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/lib/auth/acl.ts b/src/lib/auth/acl.ts index 53527a8c..3aea0576 100644 --- a/src/lib/auth/acl.ts +++ b/src/lib/auth/acl.ts @@ -1,5 +1,11 @@ import { User, UserRole, Permission } from '@/types/api'; +/** + * Minimal object required by many auth checks: only the role is required. + * This allows callers that only have a partial user (AuthUser) to pass through. + */ +type RoleHolder = { role: UserRole }; + /** * Mapping of roles to their granted permissions. */ @@ -19,9 +25,9 @@ export const ROLES_PERMISSIONS: Record = { }; /** - * Check if a user has a specific permission based on their role. + * Check if a user (or any object that contains a role) has a specific permission. */ -export function hasPermission(user: User | null | undefined, permission: Permission): boolean { +export function hasPermission(user: RoleHolder | null | undefined, permission: Permission): boolean { if (!user) return false; const permissions = ROLES_PERMISSIONS[user.role] ?? []; @@ -32,7 +38,7 @@ export function hasPermission(user: User | null | undefined, permission: Permiss * Check if a user has any of the provided permissions. */ export function hasAnyPermission( - user: User | null | undefined, + user: RoleHolder | null | undefined, permissions: Permission[], ): boolean { if (!user) return false; @@ -44,7 +50,7 @@ export function hasAnyPermission( * Check if a user has all of the provided permissions. */ export function hasAllPermissions( - user: User | null | undefined, + user: RoleHolder | null | undefined, permissions: Permission[], ): boolean { if (!user) return false; @@ -56,7 +62,7 @@ export function hasAllPermissions( * Check if a user has at least the minimum required role. * Roles are hierarchical: ADMIN > INSTRUCTOR > STUDENT > GUEST */ -export function isAtLeast(user: User | null | undefined, role: UserRole): boolean { +export function isAtLeast(user: RoleHolder | null | undefined, role: UserRole): boolean { if (!user) return false; return isAtLeastRole(user.role, role); @@ -74,4 +80,4 @@ export function isAtLeastRole(userRole: UserRole | null | undefined, role: UserR const requiredRoleIndex = hierarchy.indexOf(role); return userRoleIndex >= requiredRoleIndex; -} +} \ No newline at end of file diff --git a/src/lib/authMiddleware.ts b/src/lib/authMiddleware.ts index c13f5fe9..2648dfb4 100644 --- a/src/lib/authMiddleware.ts +++ b/src/lib/authMiddleware.ts @@ -38,7 +38,10 @@ export async function requireAuth(request: NextRequest): Promise; + +export function getUserFromRequest(request: NextRequest): AuthUser | null { // Try to get user from Bearer token const authHeader = request.headers.get('authorization'); if (authHeader?.startsWith('Bearer ')) { @@ -68,4 +71,4 @@ export function getUserFromRequest(request: NextRequest): User | null { } return null; -} +} \ No newline at end of file