import { storage } from "../storage"; import type { User } from "@shared/schema"; interface RoleNode { id: number; parentId: number | null; managerId: number | null; children: RoleNode[]; } function buildRoleTree(roles: { id: number; parentId: number | null; managerId: number | null }[]): RoleNode[] { const map = new Map(); for (const role of roles) { map.set(role.id, { id: role.id, parentId: role.parentId, managerId: role.managerId, children: [] }); } const roots: RoleNode[] = []; for (const node of map.values()) { if (node.parentId && map.has(node.parentId)) { map.get(node.parentId)!.children.push(node); } else { roots.push(node); } } return roots; } function findRoleNode(tree: RoleNode[], roleId: number): RoleNode | null { for (const node of tree) { if (node.id === roleId) return node; const found = findRoleNode(node.children, roleId); if (found) return found; } return null; } function collectSubtreeRoleIds(node: RoleNode): number[] { const ids = [node.id]; for (const child of node.children) { ids.push(...collectSubtreeRoleIds(child)); } return ids; } export async function getManagedUserIds( currentUserId: number, organizationId: number ): Promise> { const roles = await storage.getRoles(organizationId); const managedRoleIds = roles .filter(r => r.managerId === currentUserId) .map(r => r.id); if (managedRoleIds.length === 0) return new Set(); const tree = buildRoleTree(roles.map(r => ({ id: r.id, parentId: r.parentId, managerId: r.managerId }))); const allManagedRoleIds = new Set(); for (const roleId of managedRoleIds) { const node = findRoleNode(tree, roleId); if (node) { for (const id of collectSubtreeRoleIds(node)) { allManagedRoleIds.add(id); } } } const managedUserIds = new Set(); for (const role of roles) { if (allManagedRoleIds.has(role.id)) { for (const member of role.members) { managedUserIds.add(member.userId); } } } return managedUserIds; } export async function canManageUser( currentUser: User | undefined, targetUserId: number, organizationId: number ): Promise { if (!currentUser) return false; if (currentUser.appRole === "admin") return true; if (currentUser.id === targetUserId) return true; const managedIds = await getManagedUserIds(currentUser.id, organizationId); return managedIds.has(targetUserId); } export async function filterUsersByAccess( currentUser: User | undefined, organizationId: number, users: { id: number }[] ): Promise<{ id: number }[]> { if (!currentUser) return []; if (currentUser.appRole === "admin") return users; const managedIds = await getManagedUserIds(currentUser.id, organizationId); return users.filter(u => managedIds.has(u.id) || u.id === currentUser.id); }