/** * QuickCreate Permission Service * * Checks if the current user has permission to create records. * Uses custom API: asset_lite.api.user_roles.has_create_permission * which uses ignore_permissions=True to query Custom DocPerm */ // Cache for permissions to avoid repeated API calls const permissionCache: Map = new Map(); let userRolesCache: string[] | null = null; let cacheTimestamp: number = 0; const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes /** * Get current user's roles using custom API * Uses: asset_lite.api.user_roles.get_user_roles */ export const getUserRoles = async (): Promise => { // Check cache const now = Date.now(); if (userRolesCache && (now - cacheTimestamp) < CACHE_DURATION) { console.log('[PermissionService] Using cached roles:', userRolesCache); return userRolesCache; } try { const response = await fetch('/api/method/asset_lite.api.user_roles.get_user_roles', { method: 'GET', headers: { 'Content-Type': 'application/json' }, credentials: 'include', }); const data = await response.json(); if (data.message && Array.isArray(data.message)) { userRolesCache = data.message; cacheTimestamp = now; console.log('[PermissionService] User roles fetched:', data.message); return data.message; } console.warn('[PermissionService] Unexpected roles response:', data); return []; } catch (err) { console.error('[PermissionService] Error fetching user roles:', err); return []; } }; /** * Check if user has specific roles using custom API * Uses: asset_lite.api.user_roles.check_has_role */ export const checkHasRole = async (roles: string[]): Promise => { try { const response = await fetch('/api/method/asset_lite.api.user_roles.check_has_role', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ roles: roles.join(',') }) }); const data = await response.json(); return data.message?.has_role === true; } catch (err) { console.error('[PermissionService] Error checking roles:', err); return false; } }; /** * Check if user has create permission for a doctype * Uses custom API: asset_lite.api.user_roles.has_create_permission * This API uses ignore_permissions=True to query Custom DocPerm * * @param doctype - The doctype to check permission for * @returns Promise - true if user can create, false otherwise */ export const hasCreatePermission = async (doctype: string): Promise => { // Check cache first const cacheKey = `create_${doctype}`; if (permissionCache.has(cacheKey)) { const cached = permissionCache.get(cacheKey)!; console.log(`[PermissionService] ${doctype} (cached): ${cached}`); return cached; } console.log(`[PermissionService] Checking create permission for: ${doctype}`); try { // Use custom API that has ignore_permissions=True const response = await fetch('/api/method/asset_lite.api.user_roles.has_create_permission', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ doctype }) }); const data = await response.json(); console.log(`[PermissionService] has_create_permission response for ${doctype}:`, data); // Check response const hasPermission = data.message?.has_permission === true; if (hasPermission) { console.log(`[PermissionService] ${doctype}: Permission GRANTED via ${data.message?.reason} (role: ${data.message?.role})`); } else { console.log(`[PermissionService] ${doctype}: Permission DENIED - ${data.message?.reason}`); } // Cache the result permissionCache.set(cacheKey, hasPermission); return hasPermission; } catch (err) { console.error(`[PermissionService] Error checking permission for ${doctype}:`, err); // Fallback: Check if System Manager try { const isAdmin = await checkHasRole(['System Manager', 'Administrator']); if (isAdmin) { console.log('[PermissionService] Fallback: User is admin, granting permission'); permissionCache.set(cacheKey, true); return true; } } catch (e) { console.error('[PermissionService] Fallback check failed:', e); } // On error, default to false (safer) permissionCache.set(cacheKey, false); return false; } }; /** * Clear permission cache * Call this when user logs in/out or permissions change */ export const clearPermissionCache = (): void => { permissionCache.clear(); userRolesCache = null; cacheTimestamp = 0; console.log('[PermissionService] Cache cleared'); }; /** * Preload permissions for multiple doctypes * Useful for initial page load * * @param doctypes - Array of doctypes to preload permissions for */ export const preloadPermissions = async (doctypes: string[]): Promise => { console.log('[PermissionService] Preloading permissions for:', doctypes); await Promise.all(doctypes.map(doctype => hasCreatePermission(doctype))); }; export default { getUserRoles, checkHasRole, hasCreatePermission, clearPermissionCache, preloadPermissions, };