Spaces:
Sleeping
Sleeping
| import { usersTable, tasksTable, clientsTable } from "@workspace/db"; | |
| import { eq, or } from "drizzle-orm"; | |
| export type User = typeof usersTable.$inferSelect; | |
| export type Task = typeof tasksTable.$inferSelect; | |
| export type Client = typeof clientsTable.$inferSelect; | |
| export const ROLES = { | |
| ADMIN: "admin", | |
| HEAD_OF_TEAM: "head_of_team", | |
| TEAM_LEAD: "team_lead", | |
| MEMBER: "member", | |
| } as const; | |
| /** | |
| * Check if a user is an admin. | |
| */ | |
| export function isAdmin(user: User): boolean { | |
| return user.role === ROLES.ADMIN; | |
| } | |
| /** | |
| * Check if a user is Head of Team (operational supervisor). | |
| */ | |
| export function isHeadOfTeam(user: User): boolean { | |
| return user.role === ROLES.HEAD_OF_TEAM; | |
| } | |
| /** | |
| * Check if a user is a Team Lead. | |
| * Includes legacy 'dept_manager' role compatibility. | |
| */ | |
| export function isTeamLead(user: User): boolean { | |
| return user.role === ROLES.TEAM_LEAD || user.role === "dept_manager"; | |
| } | |
| /** | |
| * Check if a user is a Member. | |
| */ | |
| export function isMember(user: User): boolean { | |
| return user.role === ROLES.MEMBER; | |
| } | |
| /** | |
| * Determines if a user has access to see tasks from all teams. | |
| */ | |
| export function canAccessAllTeams(user: User): boolean { | |
| return isAdmin(user) || isHeadOfTeam(user); | |
| } | |
| /** | |
| * Determines if a user can grant admin privileges. | |
| */ | |
| export function canGrantAdmin(requestingUser: User): boolean { | |
| return isAdmin(requestingUser); | |
| } | |
| /** | |
| * Determines if a user can manage sensitive system configuration. | |
| */ | |
| export function canManageSystemConfig(user: User): boolean { | |
| return isAdmin(user); | |
| } | |
| /** | |
| * Determines if a user can view a specific task. | |
| */ | |
| export function canAccessTask(user: User, task: Task): boolean { | |
| if (canAccessAllTeams(user)) return true; | |
| if (isTeamLead(user)) { | |
| return task.fromTeam === user.team || task.assignedTeam === user.team; | |
| } | |
| // Member: Only assigned, created, or involved. | |
| // Currently schema supports assigned and created fields. | |
| return ( | |
| task.createdByUserId === user.id || | |
| task.assignedUserId === user.id | |
| ); | |
| } | |
| /** | |
| * Determines if a user can modify a specific task. | |
| */ | |
| export function canModifyTask(user: User, task: Task): boolean { | |
| if (isAdmin(user)) return true; | |
| if (isHeadOfTeam(user)) return true; // Supervise full operations | |
| if (isTeamLead(user)) { | |
| return task.fromTeam === user.team || task.assignedTeam === user.team; | |
| } | |
| // Members can update tasks they created or are assigned to | |
| return task.createdByUserId === user.id || task.assignedUserId === user.id; | |
| } | |
| /** | |
| * Determines if a user can view another user's profile/data. | |
| */ | |
| export function canAccessUser(requestingUser: User, targetUser: User): boolean { | |
| if (isAdmin(requestingUser)) return true; | |
| if (isHeadOfTeam(requestingUser)) return true; | |
| if (isTeamLead(requestingUser) && requestingUser.team === targetUser.team) return true; | |
| return requestingUser.id === targetUser.id; | |
| } | |
| /** | |
| * Returns a Drizzle filter expression for task visibility based on the new role model. | |
| */ | |
| export function getTaskVisibilityFilter(user: User) { | |
| if (canAccessAllTeams(user)) return undefined; | |
| if (isTeamLead(user)) { | |
| return or( | |
| eq(tasksTable.fromTeam, user.team), | |
| eq(tasksTable.assignedTeam, user.team) | |
| ); | |
| } | |
| // Member: ONLY assigned or created | |
| return or( | |
| eq(tasksTable.createdByUserId, user.id), | |
| eq(tasksTable.assignedUserId, user.id) | |
| ); | |
| } | |