import { KNOWN_RESOURCE_TYPE_ID } from './known-resource-types.js'; import type { Model } from './model/index.js'; import type { ResourceTypeId } from './resource-id.js'; import type { Resource } from './resource.js'; /** 资源权限 */ export enum ResourcePermission { /** 列出资源、读取元数据和权限数据 */ READ_META = 2 ** 0, /** 读取资源内容数据 */ READ = 2 ** 1, /** 修改资源元数据 */ WRITE_META = 2 ** 2, /** 修改资源内容数据 */ WRITE = 2 ** 3, /** 修改资源权限数据 */ ADMIN = 2 ** 4, /** 修改资源发布数据 */ PUBLISH = 2 ** 5, // 6~14 保留 /** 删除资源 */ DELETE = 2 ** 15, // 16~30 资源自定义权限 /** 作为子模块参与仿真 */ MODEL_SUBMODULE = 2 ** 16, /** 运行函数 */ FUNCTION_EXECUTE = 2 ** 16, /** 通过数据视图获取数据内容 */ DATASOURCE_VIEW = 2 ** 16, } /** 预设资源权限组合 */ export interface ResourcePermissionsPreset { /** 用于识别的 key */ key: string; /** 验证是否可用 */ valid: (doc: Resource) => boolean; /** 组合值 */ value: ResourcePermissions; } export namespace ResourcePermission { /** 空权限 */ export const EMPTY = 0 as ResourcePermission; /** 检查是否有指定权限 */ export function has(self: ResourcePermission, ...permissions: ResourcePermission[]): boolean { for (const permission of permissions) { if ((self & permission) !== permission) return false; } return true; } /** 添加权限 */ export function add(self: ResourcePermission, ...permissionsToAdd: ResourcePermission[]): ResourcePermission { for (const permission of permissionsToAdd) { self |= permission; } return self; } /** 移除权限 */ export function remove(self: ResourcePermission, ...permissionsToRemove: ResourcePermission[]): ResourcePermission { for (const permission of permissionsToRemove) { self &= ~permission; } return self; } /** 创建组合权限 */ export function create(...permissions: ResourcePermission[]): ResourcePermission { return add(ResourcePermission.EMPTY, ...permissions); } /** 规格化权限,根据已有权限标签,添加隐式获取的标签 */ export function normalize(self: ResourcePermission): ResourcePermission { if (!self) return ResourcePermission.EMPTY; self = add(self, ResourcePermission.READ_META); if (has(self, ResourcePermission.WRITE)) { self = add(self, ResourcePermission.WRITE_META, ResourcePermission.READ); } return self; } /** 计算包含的权限数量 */ export function count(self: ResourcePermission): number { let n = self; n = n - ((n >> 1) & 0x5555_5555); n = (n & 0x3333_3333) + ((n >> 2) & 0x3333_3333); return (((n + (n >> 4)) & 0xf0f_0f0f) * 0x101_0101) >> 24; } const ALL_COMMON: ResourcePermission = 2 ** 16 - 1; /** 检查权限是否仅包含通用权限 */ export function isCommon(self: ResourcePermission): boolean { return (self & ALL_COMMON) === self; } const ALL_CUSTOM: ResourcePermission = 2 ** 31 - 2 ** 16; /** 检查权限是否仅包含自定义权限 */ export function isCustom(self: ResourcePermission): boolean { return (self & ALL_CUSTOM) === self; } const DEFAULT_MODERATOR = (type: ResourceTypeId): ResourcePermission => ResourcePermission.READ_META | ResourcePermission.READ | ResourcePermission.WRITE_META | ResourcePermission.WRITE | ResourcePermission.ADMIN | ResourcePermission.PUBLISH | ResourcePermission.DELETE | (type === KNOWN_RESOURCE_TYPE_ID.model ? ResourcePermission.MODEL_SUBMODULE : type === KNOWN_RESOURCE_TYPE_ID.function ? ResourcePermission.FUNCTION_EXECUTE : type === KNOWN_RESOURCE_TYPE_ID.datasource ? ResourcePermission.DATASOURCE_VIEW : type === KNOWN_RESOURCE_TYPE_ID.application ? ResourcePermission.EMPTY : ResourcePermission.EMPTY); const DEFAULT_MEMBER = (type: ResourceTypeId): ResourcePermission => ResourcePermission.READ_META | ResourcePermission.READ | ResourcePermission.WRITE_META | ResourcePermission.WRITE | (type === KNOWN_RESOURCE_TYPE_ID.model ? ResourcePermission.MODEL_SUBMODULE : type === KNOWN_RESOURCE_TYPE_ID.function ? ResourcePermission.FUNCTION_EXECUTE : type === KNOWN_RESOURCE_TYPE_ID.datasource ? ResourcePermission.DATASOURCE_VIEW : type === KNOWN_RESOURCE_TYPE_ID.application ? ResourcePermission.EMPTY : ResourcePermission.EMPTY); const DEFAULT_EVERYONE = (type: ResourceTypeId): ResourcePermission => ResourcePermission.READ_META | ResourcePermission.READ | (type === KNOWN_RESOURCE_TYPE_ID.model ? ResourcePermission.MODEL_SUBMODULE : type === KNOWN_RESOURCE_TYPE_ID.function ? ResourcePermission.FUNCTION_EXECUTE : type === KNOWN_RESOURCE_TYPE_ID.datasource ? ResourcePermission.DATASOURCE_VIEW : type === KNOWN_RESOURCE_TYPE_ID.application ? ResourcePermission.EMPTY : ResourcePermission.EMPTY); /** 预设资源权限组合 */ export function presets(type: ResourceTypeId): ResourcePermissionsPreset[] { const presets: ResourcePermissionsPreset[] = [ { key: 'private', valid: () => true, value: { moderator: DEFAULT_MODERATOR(type), member: DEFAULT_MEMBER(type), everyone: ResourcePermission.EMPTY, }, }, { key: 'public', valid: () => true, value: { moderator: DEFAULT_MODERATOR(type), member: DEFAULT_MEMBER(type), everyone: DEFAULT_EVERYONE(type), }, }, ]; switch (type) { case 'application': break; case 'datasource': { presets.splice(1, 0, { key: 'public-view', valid: () => true, value: { moderator: DEFAULT_MODERATOR(type), member: DEFAULT_MEMBER(type), everyone: ResourcePermission.remove(DEFAULT_EVERYONE(type), ResourcePermission.READ), }, }); break; } case 'function': { presets.splice(1, 0, { key: 'public-execute', valid: () => true, value: { moderator: DEFAULT_MODERATOR(type), member: DEFAULT_MEMBER(type), everyone: ResourcePermission.remove(DEFAULT_EVERYONE(type), ResourcePermission.READ), }, }); break; } case 'model': { presets.splice(1, 0, { key: 'public-submodule', valid: (doc) => (doc as Model)?.context?.category === 'component', value: { moderator: DEFAULT_MODERATOR(type), member: DEFAULT_MEMBER(type), everyone: ResourcePermission.remove(DEFAULT_EVERYONE(type), ResourcePermission.READ), }, }); break; } default: break; } return presets; } } /** 资源权限 */ export interface ResourcePermissions { /** 管理员权限 */ moderator: ResourcePermission; /** 成员权限 */ member: ResourcePermission; /** 访客权限 */ everyone: ResourcePermission; } export const ResourcePermissionRole = Object.freeze(['moderator', 'member', 'everyone'] as const); /** 可配置资源权限的角色,不包含默认拥有所有权限的 `'owner'` */ export type ResourcePermissionRole = (typeof ResourcePermissionRole)[number];