Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //server/fd/fd-toolbox-asp-net/permission-data-provider.ts
- /* eslint-disable max-lines */
- import { FdMemoryCacheOptions } from "@server/fd/fd-toolbox/cachings/fd-memory-cache-options";
- import { Permission } from "@/fd/fd-toolbox-asp-net-models/permissions/permission.resource";
- import { type Uuid } from "@server/fd/fd-toolbox/types/uuid";
- import { PermissionPackageToPermission } from "@/fd/fd-toolbox-asp-net-models/permissions/permission-package-to-permission.resource";
- import { PermissionDto } from "@server/auth/permission-dto";
- import {
- PermissionLevel,
- permissionType,
- PermissionType,
- } from "@/fd/fd-toolbox-core/auth/permissions/permission-enums";
- import { setCoreCache, tryGetObjectFromCoreCache } from "@server/fd/fd-toolbox/cachings/core-memory-cache";
- import { addListValueToDictionary, addMapValueToMap } from "@server/fd/fd-toolbox/services/dictionaries";
- import { RoleToPermission } from "@server/auth/role-to-permission";
- import { getAllIncludingUserToRoles } from "@server/auth/role-db";
- import { resourceSchema, permissionSchema as permissionTable, roleToPermissionSchema } from "@plugin/schema";
- import { eq, getTableColumns } from "drizzle-orm";
- import { getQuery } from "@server/web/drizzle";
- import { UserRole } from "@/users/user-role.resource";
- import { getPermissionPackageToPermissions } from "../fd-toolbox-web/auth/permissions/permission-package-to-permission-db";
- import { getRoleToPermissionPackages } from "../fd-toolbox-web/models/roles/role-to-permission-package-db";
- import { getPermissionCacheKey, createShallowPermission } from "../fd-toolbox-web/permissions/permissions";
- import { fdCacheKeys } from "../fd-toolbox-web/constants/fd-cache-keys";
- // Add permission cache
- const permissionCache = new Map<Uuid, Permission>();
- export async function getUserRoleIdsToRoleLevels() {
- const roles = await getAllIncludingUserToRoles();
- const userRoleIdsLevels = new Map<Uuid, Map<Uuid, PermissionLevel>>();
- for (const roleItem of roles) {
- if (roleItem.userRoleList) {
- for (const userRoleItem of roleItem.userRoleList.filter(
- (ur: UserRole) => ur.roleId === roleItem.id,
- )) {
- addMapValueToMap(userRoleIdsLevels, userRoleItem.userId, userRoleItem.roleId, roleItem.level);
- }
- }
- }
- return userRoleIdsLevels;
- }
- export async function saveRoleToPermissionsToCache(
- rolePackageToPermissions: Map<Uuid, Uuid[]>,
- ids: Uuid[],
- type: PermissionType,
- ) {
- const cacheKeyPrefix = getCacheKeyPrefix(type);
- const uncachedIds = [];
- // Check cache first
- for (const id of ids) {
- const cached = await tryGetFromCache(id, cacheKeyPrefix);
- if (cached) {
- rolePackageToPermissions.set(id, cached);
- } else {
- uncachedIds.push(id);
- }
- }
- // Batch fetch uncached data
- if (uncachedIds.length) {
- await saveRoleToPermissionsBatch(uncachedIds);
- for (const id of uncachedIds) {
- const cached = await tryGetFromCache(id, cacheKeyPrefix);
- if (cached) {
- rolePackageToPermissions.set(id, cached);
- }
- }
- }
- return rolePackageToPermissions;
- }
- export async function getRoleToPermissionList() {
- return (await getQuery(roleToPermissionSchema)) as RoleToPermission[];
- }
- export async function getUserPermissionCacheKey(type: PermissionType, userId: Uuid) {
- return getPermissionCacheKey(type.toString(), userId);
- }
- export async function getUserResourcePermissionCacheKey(
- type: PermissionType,
- resourceName: string,
- userId: Uuid,
- ) {
- return getPermissionCacheKey(await getPermissionCacheKey(type.toString(), resourceName), userId);
- }
- export async function saveUserPermissionsToMemoryCache(
- userPermissionKey: string,
- type: PermissionType,
- userPermissions: Map<string, PermissionDto>,
- ) {
- const cacheKey = await getUserPermissionCacheKey(type, userPermissionKey);
- await saveToMemoryCache(cacheKey, userPermissions);
- }
- export async function getUserRoleIdsToRolePermissionLevels(userId: Uuid) {
- const roleIdsLevels = new Map<Uuid, PermissionLevel>();
- const memoryCacheKey = await getPermissionCacheKey(fdCacheKeys.userRolePermissionLevels, userId);
- const cachedUserRoleIdsLevels = tryGetObjectFromCoreCache<Map<Uuid, PermissionLevel>>(memoryCacheKey);
- if (cachedUserRoleIdsLevels) {
- return cachedUserRoleIdsLevels;
- } else {
- await saveUserRoleIdsToRolePermissionLevelsToCache();
- const rolesToLevels = tryGetObjectFromCoreCache<Map<Uuid, PermissionLevel>>(memoryCacheKey);
- if (rolesToLevels) {
- return rolesToLevels;
- }
- }
- return roleIdsLevels;
- }
- export async function savePackageToPermissionsToCache(
- rolePackageToPermissions: Map<Uuid, Uuid[]>,
- ids: Uuid[],
- type: PermissionType,
- ) {
- let cacheKeyPrefix;
- switch (type) {
- case permissionType.resource:
- cacheKeyPrefix = fdCacheKeys.packagesToResourcePermissions;
- break;
- case permissionType.property:
- cacheKeyPrefix = fdCacheKeys.packagesToPropertyPermissions;
- break;
- default:
- cacheKeyPrefix = fdCacheKeys.packagesToDefaultPermissions;
- }
- for (const id of ids) {
- await addMapFromCache(rolePackageToPermissions, id, cacheKeyPrefix);
- if (!rolePackageToPermissions.has(id)) {
- await privateSavePackageToPermissionsToCache(id);
- await addMapFromCache(rolePackageToPermissions, id, cacheKeyPrefix);
- }
- }
- return rolePackageToPermissions;
- }
- export async function getPermission(id: Uuid) {
- // Check memory cache first
- if (permissionCache.has(id)) {
- return createShallowPermission(permissionCache.get(id)!);
- }
- const cacheKey = await getPermissionCacheKey(fdCacheKeys.permission, id);
- let permission = tryGetObjectFromCoreCache<Permission>(cacheKey);
- if (!permission) {
- await savePermissionsToCache();
- permission = tryGetObjectFromCoreCache(cacheKey);
- }
- if (permission) {
- permissionCache.set(id, permission);
- return createShallowPermission(permission);
- }
- return null;
- }
- export async function addPackageToPermissions(
- rolesToPermissions: Map<Uuid, Uuid[]>,
- packageToPermissionList: PermissionPackageToPermission[],
- type: PermissionType,
- ) {
- for (const packageToPermission of packageToPermissionList) {
- const permission = await getPermission(packageToPermission.permissionId);
- if (permission?.type === type) {
- addListValueToDictionary(
- rolesToPermissions,
- packageToPermission.permissionPackageId,
- packageToPermission.permissionId,
- );
- }
- }
- }
- export async function savePermissionsToCache() {
- const query = getQuery(permissionTable, {
- ...getTableColumns(permissionTable),
- resource: getTableColumns(resourceSchema),
- });
- const permissions = (await query.leftJoin(
- resourceSchema,
- eq(permissionTable.resourceId, resourceSchema.id),
- )) as Permission[];
- for (const permission of permissions) {
- const memoryKey = await getPermissionCacheKey(fdCacheKeys.permission, permission.id);
- const newPermission = createShallowPermission(permission);
- saveToMemoryCache(memoryKey, newPermission);
- }
- }
- export async function getRoleToPackages(ids: Uuid[]) {
- const roleToPackages = new Map<Uuid, Uuid[]>();
- for (const id of ids) {
- await addMapFromCache(roleToPackages, id, fdCacheKeys.roleToPackages);
- if (!roleToPackages.has(id)) {
- await saveRoleToPermissionPackagesToCache();
- await addMapFromCache(roleToPackages, id, fdCacheKeys.roleToPackages);
- }
- }
- return roleToPackages;
- }
- async function addMapFromCache<T>(map: Map<Uuid, T[]>, id: Uuid, cacheKeyPrefix: string) {
- const memoryCacheKey = await getPermissionCacheKey(cacheKeyPrefix, id);
- const cachedValue = tryGetObjectFromCoreCache<T[]>(memoryCacheKey);
- if (cachedValue) {
- map.set(id, cachedValue);
- }
- }
- export async function saveRoleToPermissionsToCacheById(id: Uuid) {
- const rolesToResourcePermissions: Map<Uuid, Uuid[]> = new Map();
- const rolesToDefaultPermissions: Map<Uuid, Uuid[]> = new Map();
- const rolesToPropertyPermissions: Map<Uuid, Uuid[]> = new Map();
- const roleToPermissionList = await getRoleToPermissionList();
- let roleIds = [id, ...roleToPermissionList.map((x) => x.roleId)];
- roleIds = [...new Set(roleIds)];
- await addRoleToPermissions(rolesToResourcePermissions, roleToPermissionList, permissionType.resource);
- await addRoleToPermissions(rolesToDefaultPermissions, roleToPermissionList, permissionType.default);
- await addRoleToPermissions(rolesToPropertyPermissions, roleToPermissionList, permissionType.property);
- await saveToMemoryCacheByCacheKeyPrefix(
- rolesToResourcePermissions,
- fdCacheKeys.roleToResourcePermissions,
- );
- await saveToMemoryCacheByCacheKeyPrefix(rolesToDefaultPermissions, fdCacheKeys.roleToDefaultPermissions);
- await saveToMemoryCacheByCacheKeyPrefix(
- rolesToPropertyPermissions,
- fdCacheKeys.roleToPropertyPermissions,
- );
- }
- async function addRoleToPermissions(
- rolesToPermissions: Map<Uuid, Uuid[]>,
- roleToPermissionList: RoleToPermission[],
- type: PermissionType,
- ) {
- for (const roleToPermissionItem of roleToPermissionList) {
- const permission = await getPermission(roleToPermissionItem.permissionId);
- if (permission?.type === type) {
- addListValueToDictionary(
- rolesToPermissions,
- roleToPermissionItem.roleId,
- roleToPermissionItem.permissionId,
- );
- }
- }
- }
- async function applyPermissionsToPackages(
- permissionMap: Map<Uuid, Uuid[]>,
- permissionList: PermissionPackageToPermission[],
- permissionTypeParam: PermissionType,
- packageIds: Uuid[],
- ) {
- await addPackageToPermissions(permissionMap, permissionList, permissionTypeParam);
- if (permissionMap.size === 0) {
- for (const packId of packageIds) {
- permissionMap.set(packId, []);
- }
- }
- }
- async function privateSavePackageToPermissionsToCache(id: Uuid) {
- const packagesToResourcePermissions = new Map<Uuid, Uuid[]>();
- const packagesToDefaultPermissions = new Map<Uuid, Uuid[]>();
- const packagesToPropertyPermissions = new Map<Uuid, Uuid[]>();
- const packageToPermissionList = await getPermissionPackageToPermissions();
- let permissionPackageIds = [id];
- permissionPackageIds = permissionPackageIds.concat(
- packageToPermissionList.map((x) => x.permissionPackageId),
- );
- permissionPackageIds = Array.from(new Set(permissionPackageIds));
- await applyPermissionsToPackages(
- packagesToResourcePermissions,
- packageToPermissionList,
- permissionType.resource,
- permissionPackageIds,
- );
- await applyPermissionsToPackages(
- packagesToDefaultPermissions,
- packageToPermissionList,
- permissionType.default,
- permissionPackageIds,
- );
- await applyPermissionsToPackages(
- packagesToPropertyPermissions,
- packageToPermissionList,
- permissionType.property,
- permissionPackageIds,
- );
- await saveToMemoryCacheByCacheKeyPrefix(
- packagesToResourcePermissions,
- fdCacheKeys.packagesToResourcePermissions,
- );
- await saveToMemoryCacheByCacheKeyPrefix(
- packagesToDefaultPermissions,
- fdCacheKeys.packagesToDefaultPermissions,
- );
- await saveToMemoryCacheByCacheKeyPrefix(
- packagesToPropertyPermissions,
- fdCacheKeys.packagesToPropertyPermissions,
- );
- }
- async function saveRoleToPermissionPackagesToCache() {
- const rolesToPackages = new Map<Uuid, Uuid[]>();
- const roleToPermissionPackageList = await getRoleToPermissionPackages();
- for (const roleToPermissionPackage of roleToPermissionPackageList) {
- addListValueToDictionary(
- rolesToPackages,
- roleToPermissionPackage.roleId,
- roleToPermissionPackage.permissionPackageId,
- );
- }
- await saveToMemoryCacheByCacheKeyPrefix(rolesToPackages, fdCacheKeys.roleToPackages);
- }
- async function saveToMemoryCacheByCacheKeyPrefix(
- idsToPermissions: Map<Uuid, Uuid[]>,
- cacheKeyPrefix: string,
- ) {
- for (const [key, value] of idsToPermissions) {
- const newKey = await getPermissionCacheKey(cacheKeyPrefix, key);
- await saveToMemoryCache(newKey, value);
- }
- }
- async function saveUserRoleIdsToRolePermissionLevelsToCache() {
- const userIdRoleIdsToRolePermissionLevels = await getUserRoleIdsToRoleLevels();
- for (const [userId, rolePermissionLevels] of userIdRoleIdsToRolePermissionLevels.entries()) {
- const key = await getPermissionCacheKey(fdCacheKeys.userRolePermissionLevels, userId);
- await saveToMemoryCache(key, rolePermissionLevels);
- }
- }
- async function saveToMemoryCache<T extends object>(key: string, value: T) {
- const fdMemoryCacheOptions: FdMemoryCacheOptions = {
- absoluteExpirationRelativeToNowSeconds: 24 * fdCacheKeys.secondsInAHour,
- };
- setCoreCache(key, value, fdMemoryCacheOptions);
- }
- // Helper functions
- function getCacheKeyPrefix(type: PermissionType) {
- switch (type) {
- case permissionType.resource:
- return fdCacheKeys.roleToResourcePermissions;
- case permissionType.property:
- return fdCacheKeys.roleToPropertyPermissions;
- default:
- return fdCacheKeys.roleToDefaultPermissions;
- }
- }
- async function tryGetFromCache(id: Uuid, cacheKeyPrefix: string) {
- const memoryCacheKey = await getPermissionCacheKey(cacheKeyPrefix, id);
- return tryGetObjectFromCoreCache<Uuid[]>(memoryCacheKey);
- }
- async function saveRoleToPermissionsBatch(roleIds: Uuid[]) {
- const roleToPermissionList = await getRoleToPermissionList();
- const rolesToResourcePermissions: Map<Uuid, Uuid[]> = new Map();
- const rolesToDefaultPermissions: Map<Uuid, Uuid[]> = new Map();
- const rolesToPropertyPermissions: Map<Uuid, Uuid[]> = new Map();
- // Process all roles in one pass
- await Promise.all([
- addRoleToPermissions(rolesToResourcePermissions, roleToPermissionList, permissionType.resource),
- addRoleToPermissions(rolesToDefaultPermissions, roleToPermissionList, permissionType.default),
- addRoleToPermissions(rolesToPropertyPermissions, roleToPermissionList, permissionType.property),
- ]);
- // Save all to cache in parallel
- await Promise.all([
- saveToMemoryCacheByCacheKeyPrefix(rolesToResourcePermissions, fdCacheKeys.roleToResourcePermissions),
- saveToMemoryCacheByCacheKeyPrefix(rolesToDefaultPermissions, fdCacheKeys.roleToDefaultPermissions),
- saveToMemoryCacheByCacheKeyPrefix(rolesToPropertyPermissions, fdCacheKeys.roleToPropertyPermissions),
- ]);
- }
- //server/fd/fd-toolbox-web/permissions/permission-checker.ts
- /* eslint-disable max-lines */
- import { PermissionCheckConfig } from "@server/fd/fd-toolbox/auth/permissions/permission-check-config";
- import { PermissionDto } from "@server/auth/permission-dto";
- import {
- PermissionLevel,
- permissionType,
- PermissionType,
- } from "@/fd/fd-toolbox-core/auth/permissions/permission-enums";
- import { ResourceMeta } from "@/fd/fd-toolbox/fd-meta/resource-meta";
- import { getResourceMeta } from "@server/meta/fd-meta/services/metas";
- import { getResourcePermissionChecker } from "@server/meta/fd-meta/auth/permissions/resource-permission-checker-provider";
- import { crudAction, CrudAction } from "@/fd/fd-toolbox-core/enums/enums";
- import { createError } from "@/fd/fd-toolbox/errors/errors";
- import { getPermissionCheckConfig } from "@server/meta/fd-meta/services/permission-check-config-provider";
- import { type Uuid } from "@server/fd/fd-toolbox/types/uuid";
- import {
- getPermission,
- getRoleToPackages,
- getUserPermissionCacheKey,
- getUserResourcePermissionCacheKey,
- getUserRoleIdsToRolePermissionLevels,
- savePackageToPermissionsToCache,
- saveRoleToPermissionsToCache,
- saveUserPermissionsToMemoryCache,
- } from "@server/fd/fd-toolbox-asp-net/permission-data-provider";
- import { WithIndexer } from "@server/fd/fd-toolbox/types/with-indexer";
- import { Permission } from "@/fd/fd-toolbox-asp-net-models/permissions/permission.resource";
- import { getEmptyUuid, isValidUuid } from "@/fd/fd-toolbox/uuids";
- import { setCoreCache, tryGetObjectFromCoreCache } from "@server/fd/fd-toolbox/cachings/core-memory-cache";
- import { isNullOrUndefined } from "@/fd/fd-toolbox/functions/value-checking-functions";
- import { UserPermissionList } from "@server/users/user-permission";
- import { withUserIdProps } from "@server/fd/fd-toolbox-core/base-resources/props/with-user-id-props";
- import { WithId } from "@server/fd/fd-toolbox-core/base-resources/with-id";
- import { WithUserId } from "@server/fd/fd-toolbox-core/base-resources/with-user-id";
- import {
- getPermissionNameFromCrud,
- convertCrudActionToPermissionAction,
- createPermissionDto,
- } from "./permissions";
- const minPermissionLevel = 0;
- // Add new cache for request-level data
- const requestCache = new Map<
- string,
- {
- roleIdsLevels: Map<Uuid, PermissionLevel>;
- rolesToPackages: Map<Uuid, Uuid[]>;
- }
- >();
- export async function hasPermissionByPermissionCheckConfig(permissionCheckConfig: PermissionCheckConfig) {
- if (permissionCheckConfig.resourceName && !isNullOrUndefined(permissionCheckConfig.crudAction)) {
- permissionCheckConfig.permissionName = getPermissionNameFromCrud(
- permissionCheckConfig.resourceName,
- permissionCheckConfig.crudAction!,
- );
- }
- if (!permissionCheckConfig.permissionName) {
- throw createError(`${permissionCheckConfig.permissionName} is empty`);
- }
- const userHasPermission = await checkUserPermission(permissionCheckConfig);
- if (permissionCheckConfig.throwIfNoPermission && !userHasPermission) {
- throw createError(
- `No permission ${permissionCheckConfig.permissionName} for ${permissionCheckConfig.userId}`,
- );
- }
- return userHasPermission;
- }
- export async function hasPermissionByUserId(resourceName: string, action: CrudAction, userId: string) {
- const resourceMeta: ResourceMeta = await getResourceMeta(resourceName);
- const permissionCheckConfig: PermissionCheckConfig = getPermissionCheckConfig(
- userId,
- resourceMeta,
- undefined,
- action,
- );
- return hasPermissionByPermissionCheckConfig(permissionCheckConfig);
- }
- export async function hasPropertyPermission(propertyId: Uuid, permissionCheckConfig: PermissionCheckConfig) {
- if (!permissionCheckConfig.resourceId || !permissionCheckConfig.crudAction) {
- return false;
- }
- const userPermission = await getUserPermission(
- permissionCheckConfig.userId,
- permissionType.property,
- propertyId,
- );
- if (
- userPermission &&
- userPermission.action &&
- convertCrudActionToPermissionAction(userPermission.action).includes(permissionCheckConfig.crudAction)
- ) {
- return true;
- }
- return true;
- }
- async function checkUserPermission(permissionCheckConfig: PermissionCheckConfig) {
- let userHasPermission = await hasDefaultOrResourcePermission(permissionCheckConfig);
- if (permissionCheckConfig.resource && permissionCheckConfig.resourceName) {
- const resourceMeta: ResourceMeta = await getResourceMeta(permissionCheckConfig.resourceName);
- if (!userHasPermission) {
- userHasPermission = checkBelowLevelAllowedCrudByUserId(resourceMeta, permissionCheckConfig);
- }
- const resourcePermissionChecker = getResourcePermissionChecker(resourceMeta.resourceName);
- if (resourcePermissionChecker) {
- const result = await resourcePermissionChecker(
- permissionCheckConfig.resource,
- permissionCheckConfig.userId,
- permissionCheckConfig.crudAction ?? crudAction.view,
- );
- if (result) {
- userHasPermission = result;
- }
- }
- }
- return userHasPermission;
- }
- function mapToWithIndexer<T>(map: Map<string, T>): WithIndexer<T> {
- const result: WithIndexer<T> = {};
- map.forEach((value, key) => {
- result[key] = value;
- });
- return result;
- }
- export async function getUserPermissions(userId: Uuid) {
- // Cache role data at request level
- const roleData = await cacheRoleData(userId);
- if (!roleData) {
- throw createError("Role data not found");
- }
- const [resourcePermissions, propertyPermissions, defaultPermissions] = await Promise.all([
- getUserPermissionsByPermissionType(userId, permissionType.resource, roleData),
- getUserPermissionsByPermissionType(userId, permissionType.property, roleData),
- getUserPermissionsByPermissionType(userId, permissionType.default, roleData),
- ]);
- const userPermissions: UserPermissionList = {
- resourcePermissions: mapToWithIndexer(resourcePermissions),
- propertyPermissions: mapToWithIndexer(propertyPermissions),
- defaultPermissions: mapToWithIndexer(defaultPermissions),
- };
- // Clear request cache after use
- requestCache.clear();
- return userPermissions;
- }
- async function getUserPermissionsByPermissionType(
- userId: Uuid,
- type: PermissionType,
- roleData: {
- roleIdsLevels: Map<Uuid, PermissionLevel>;
- rolesToPackages: Map<Uuid, Uuid[]>;
- },
- ) {
- if (!roleData?.roleIdsLevels || !roleData?.rolesToPackages) {
- throw createError("Invalid role data provided");
- }
- const cacheKey = await getUserPermissionCacheKey(type, userId);
- const cached = tryGetObjectFromCoreCache<Map<string, PermissionDto>>(cacheKey);
- if (cached !== null) return cached;
- const { roleIdsLevels, rolesToPackages } = roleData;
- const roleIds = [...roleIdsLevels.keys()];
- const maxPermissionRoleLevel = Math.max(...[...roleIdsLevels.values()], minPermissionLevel);
- const [rolesToPermissions, packagesToPermissions] = await Promise.all([
- getRolePermissions(roleIds, type),
- getPackagePermissions(rolesToPackages, type),
- ]);
- const userPermissions = await buildUserPermissions(
- roleIds,
- rolesToPermissions,
- packagesToPermissions,
- rolesToPackages,
- maxPermissionRoleLevel,
- );
- const userPermissionsMap = convertWithIndexerToMap(userPermissions);
- await saveUserPermissionsToMemoryCache(userId, type, userPermissionsMap);
- return userPermissionsMap;
- }
- // Cache role data at request level
- async function cacheRoleData(userId: Uuid) {
- const cacheKey = `roleData_${userId}`;
- if (requestCache.has(cacheKey)) {
- return requestCache.get(cacheKey);
- }
- const roleIdsLevels = await getUserRoleIdsToRolePermissionLevels(userId);
- const roleIds = [...roleIdsLevels.keys()];
- const rolesToPackages = await getRoleToPackages(roleIds);
- const data = { roleIdsLevels, rolesToPackages };
- requestCache.set(cacheKey, data);
- return data;
- }
- // Optimize permission fetching with batch operations
- async function getRolePermissions(roleIds: Uuid[], type: PermissionType) {
- const rolesToPermissions = new Map<Uuid, Uuid[]>();
- await saveRoleToPermissionsToCache(rolesToPermissions, roleIds, type);
- return rolesToPermissions;
- }
- async function getPackagePermissions(rolesToPackages: Map<Uuid, Uuid[]>, type: PermissionType) {
- const packageIds = [...new Set([...rolesToPackages.values()].flat())];
- const packagesToPermissions = new Map<Uuid, Uuid[]>();
- await savePackageToPermissionsToCache(packagesToPermissions, packageIds, type);
- return packagesToPermissions;
- }
- function checkBelowLevelAllowedCrudByUserId(
- resourceMeta: ResourceMeta,
- permissionCheckConfig: PermissionCheckConfig,
- ) {
- if (!permissionCheckConfig.resource) return false;
- const resource: WithId = permissionCheckConfig.resource;
- let withUserId;
- if (withUserIdProps.userId in resourceMeta.properties) {
- withUserId = resource as unknown as WithUserId;
- }
- if (
- withUserId &&
- permissionCheckConfig.crudAction !== undefined &&
- resourceMeta.auth.belowLevelAllowedCrudByUserId.includes(permissionCheckConfig.crudAction)
- ) {
- if (withUserId && permissionCheckConfig.userId === withUserId.userId) {
- return true;
- }
- }
- return false;
- }
- async function addHigherPermission<TKey>(
- permissions: Map<TKey, PermissionDto>,
- key: TKey,
- permission: Permission,
- permissionRoleLevel: PermissionLevel,
- ) {
- if (!permissions.has(key)) {
- permissions.set(key, await createPermissionDto(permission, permissionRoleLevel));
- } else {
- const permissionDto = permissions.get(key)!;
- if (permissionDto.id !== permission.id) {
- if (permissionDto.action && permission.action) {
- permission.id = getEmptyUuid();
- permission.action |= permissionDto.action;
- const newPermissionDto = await createPermissionDto(permission, permissionRoleLevel);
- permissions.set(key, newPermissionDto);
- } else {
- const newPermissionDto = await createPermissionDto(permission, permissionRoleLevel);
- permissions.set(key, newPermissionDto);
- }
- }
- }
- }
- async function hasDefaultOrResourcePermission(permissionCheckConfig: PermissionCheckConfig) {
- let userHasPermission = false;
- if (permissionCheckConfig.resourceId) {
- const userPermission = await getUserPermission(
- permissionCheckConfig.userId,
- permissionType.resource,
- permissionCheckConfig.resourceId,
- );
- if (
- userPermission &&
- userPermission.action &&
- permissionCheckConfig.crudAction !== undefined &&
- convertCrudActionToPermissionAction(userPermission.action).includes(
- permissionCheckConfig.crudAction,
- )
- ) {
- userHasPermission = true;
- }
- } else {
- if (permissionCheckConfig.permissionName) {
- const userPermission = await getUserPermission(
- permissionCheckConfig.userId,
- permissionType.default,
- permissionCheckConfig.permissionName,
- );
- if (userPermission && userPermission.name === permissionCheckConfig.permissionName) {
- userHasPermission = true;
- }
- }
- }
- return userHasPermission;
- }
- async function addUserPermissions(
- roleIds: Uuid[],
- rolesToPermissions: Map<Uuid, Uuid[]>,
- packagesToPermissions: Map<Uuid, Uuid[]>,
- rolesToPackages: Map<Uuid, Uuid[]>,
- maxPermissionRoleLevel: PermissionLevel,
- userPermissions: WithIndexer<PermissionDto>,
- ) {
- for (const role of roleIds) {
- if (rolesToPermissions.has(role)) {
- for (const permissionId of rolesToPermissions.get(role)!) {
- await addPermissionIfNeeded(permissionId, userPermissions, maxPermissionRoleLevel);
- }
- }
- if (rolesToPackages.has(role)) {
- for (const rolePackageName of rolesToPackages.get(role)!) {
- if (packagesToPermissions.has(rolePackageName)) {
- for (const permissionId of packagesToPermissions.get(rolePackageName)!) {
- await addPermissionIfNeeded(permissionId, userPermissions, maxPermissionRoleLevel);
- }
- }
- }
- }
- }
- }
- async function addPermissionIfNeeded(
- permissionId: Uuid,
- userPermissions: WithIndexer<PermissionDto>,
- maxPermissionRoleLevel: PermissionLevel,
- ) {
- const permission = await getPermission(permissionId);
- if (permission) {
- const userPermissionsMap = convertWithIndexerToMap<PermissionDto>(userPermissions);
- if (permission.type === permissionType.resource || permission.type === permissionType.property) {
- const key =
- permission.type === permissionType.resource
- ? permission.resourceId!
- : permission.resourcePropertyId!;
- await addHigherPermission(userPermissionsMap, key, permission, maxPermissionRoleLevel);
- } else if (permission.type === permissionType.default) {
- await addHigherPermission(
- userPermissionsMap,
- permission.name!,
- permission,
- maxPermissionRoleLevel,
- );
- }
- userPermissionsMap.forEach((value, key) => {
- userPermissions[key] = value;
- });
- }
- }
- function convertWithIndexerToMap<T>(obj: WithIndexer<T>) {
- return new Map(Object.entries(obj));
- }
- async function getUserPermission(userId: Uuid, type: PermissionType, resourceIdOrPropertyIdOrName: Uuid) {
- const cacheKey = await getUserResourcePermissionCacheKey(type, resourceIdOrPropertyIdOrName, userId);
- let userPermission = tryGetObjectFromCoreCache<PermissionDto>(cacheKey);
- if (userPermission !== null) {
- return userPermission;
- }
- const roleData = await cacheRoleData(userId);
- if (!roleData) {
- throw createError("Role data not found");
- }
- const userPermissions = await getUserPermissionsByPermissionType(userId, type, roleData);
- userPermission = null;
- if (type === permissionType.resource || type === permissionType.property) {
- if (isValidUuid(resourceIdOrPropertyIdOrName) && userPermissions.has(resourceIdOrPropertyIdOrName)) {
- userPermission = userPermissions.get(resourceIdOrPropertyIdOrName)!;
- }
- } else if (type === permissionType.default) {
- const permissionName = resourceIdOrPropertyIdOrName.toString();
- if (userPermissions.has(permissionName)) {
- userPermission = userPermissions.get(permissionName)!;
- }
- }
- if (userPermission) {
- setCoreCache(cacheKey, userPermission);
- }
- return userPermission;
- }
- async function buildUserPermissions(
- roleIds: Uuid[],
- rolesToPermissions: Map<Uuid, Uuid[]>,
- packagesToPermissions: Map<Uuid, Uuid[]>,
- rolesToPackages: Map<Uuid, Uuid[]>,
- maxPermissionRoleLevel: PermissionLevel,
- ): Promise<WithIndexer<PermissionDto>> {
- const userPermissions: WithIndexer<PermissionDto> = {};
- await addUserPermissions(
- roleIds,
- rolesToPermissions,
- packagesToPermissions,
- rolesToPackages,
- maxPermissionRoleLevel,
- userPermissions,
- );
- return userPermissions;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement