Files
FastGPT/packages/global/support/permission/controller.ts
Finley Ge 57e1ef1176 refactor: permission role & app read chat log permission (#5416)
* refactor: permission role

* refactor: permission type

* fix: permission manage

* fix: group owner cannot be deleted

* chore: common per map

* chore: openapi

* chore: rename

* fix: type error

* chore: app chat log permission

* chore: add initv4112
2025-08-11 10:51:44 +08:00

139 lines
3.3 KiB
TypeScript

import type {
RoleValueType,
RoleListType,
PermissionValueType,
PermissionListType,
RolePerMapType
} from './type';
import {
CommonPerList,
CommonRoleList,
CommonRolePerMap,
NullPermissionVal,
NullRoleVal,
OwnerPermissionVal,
OwnerRoleVal
} from './constant';
export type PerConstructPros = {
role?: RoleValueType;
isOwner?: boolean;
roleList?: RoleListType;
perList?: PermissionListType;
rolePerMap?: RolePerMapType;
};
/**
* the Permission helper class
*/
export class Permission {
role: PermissionValueType;
private permission: PermissionValueType = NullRoleVal; // default role
isOwner: boolean = false;
hasManagePer: boolean = false;
hasWritePer: boolean = false;
hasReadPer: boolean = false;
hasManageRole: boolean = false;
hasWriteRole: boolean = false;
hasReadRole: boolean = false;
readonly roleList: RoleListType;
readonly perList: PermissionListType;
readonly rolePerMap: RolePerMapType;
constructor({
role = NullRoleVal,
isOwner = false,
roleList = CommonRoleList,
perList = CommonPerList,
rolePerMap = CommonRolePerMap
}: PerConstructPros = {}) {
if (isOwner) {
this.role = OwnerRoleVal;
} else {
this.role = role;
}
this.roleList = roleList;
this.perList = perList;
this.rolePerMap = rolePerMap;
this.updatePermissions();
}
addRole(...roleList: RoleValueType[]) {
if (this.isOwner) {
return this;
}
for (const per of roleList) {
this.role = this.role | per;
}
this.updatePermissions();
return this;
}
removeRole(...roleList: RoleValueType[]) {
if (this.isOwner) {
return this.role;
}
for (const per of roleList) {
this.role = this.role & ~per;
}
this.updatePermissions();
return this;
}
checkPer(perm: PermissionValueType): boolean {
// if the permission is owner permission, only owner has this permission.
if (perm === OwnerPermissionVal) {
return this.permission === OwnerPermissionVal;
}
return (this.permission & perm) === perm;
}
checkRole(role: RoleValueType): boolean {
if (role === OwnerRoleVal) {
return this.role === OwnerRoleVal;
}
return (this.role & role) === role;
}
private updatePermissionCallback?: () => void;
setUpdatePermissionCallback(callback: () => void) {
callback();
this.updatePermissionCallback = callback;
}
private calculatePer() {
if (this.role === OwnerRoleVal) {
this.permission = OwnerPermissionVal;
return;
}
let role = this.role;
this.permission = 0;
while (role > 0) {
// Binary Magic
this.permission |= this.rolePerMap.get(role & -role) ?? 0;
role &= role - 1;
}
}
private updatePermissions() {
this.calculatePer();
this.isOwner = this.permission === OwnerRoleVal;
this.hasManagePer = this.checkPer(this.roleList['manage'].value);
this.hasWritePer = this.checkPer(this.roleList['write'].value);
this.hasReadPer = this.checkPer(this.roleList['read'].value);
this.hasManageRole = this.checkRole(this.roleList['manage'].value);
this.hasWriteRole = this.checkRole(this.roleList['write'].value);
this.hasReadRole = this.checkRole(this.roleList['read'].value);
this.updatePermissionCallback?.();
}
}