2026-06-11 19:56:20 +05:30

166 lines
5.2 KiB
TypeScript

/**
* 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<string, boolean> = 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<string[]> => {
// 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<boolean> => {
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<boolean> - true if user can create, false otherwise
*/
export const hasCreatePermission = async (doctype: string): Promise<boolean> => {
// 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<void> => {
console.log('[PermissionService] Preloading permissions for:', doctypes);
await Promise.all(doctypes.map(doctype => hasCreatePermission(doctype)));
};
export default {
getUserRoles,
checkHasRole,
hasCreatePermission,
clearPermissionCache,
preloadPermissions,
};