mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 20:37:48 +00:00
Permission (#1687)
Co-authored-by: Archer <545436317@qq.com> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
@@ -31,7 +31,6 @@ export type FastGPTFeConfigsType = {
|
||||
show_openai_account?: boolean;
|
||||
show_promotion?: boolean;
|
||||
show_team_chat?: boolean;
|
||||
hide_app_flow?: boolean;
|
||||
concatMd?: string;
|
||||
docUrl?: string;
|
||||
chatbotUrl?: string;
|
||||
|
12
packages/global/core/app/collaborator.d.ts
vendored
Normal file
12
packages/global/core/app/collaborator.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { PermissionValueType } from '../../support/permission/type';
|
||||
|
||||
export type UpdateAppCollaboratorBody = {
|
||||
appId: string;
|
||||
tmbIds: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
|
||||
export type AppCollaboratorDeleteParams = {
|
||||
appId: string;
|
||||
tmbId: string;
|
||||
};
|
11
packages/global/core/app/type.d.ts
vendored
11
packages/global/core/app/type.d.ts
vendored
@@ -7,6 +7,8 @@ import { SelectedDatasetType } from '../workflow/api';
|
||||
import { DatasetSearchModeEnum } from '../dataset/constants';
|
||||
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
|
||||
import { StoreEdgeItemType } from '../workflow/type/edge';
|
||||
import { PermissionValueType } from '../../support/permission/type';
|
||||
import { AppPermission } from '../../support/permission/app/controller';
|
||||
|
||||
export type AppSchema = {
|
||||
_id: string;
|
||||
@@ -27,9 +29,9 @@ export type AppSchema = {
|
||||
scheduledTriggerConfig?: AppScheduledTriggerConfigType | null;
|
||||
scheduledTriggerNextTime?: Date;
|
||||
|
||||
permission: `${PermissionTypeEnum}`;
|
||||
inited?: boolean;
|
||||
teamTags: string[];
|
||||
defaultPermission: PermissionValueType;
|
||||
};
|
||||
|
||||
export type AppListItemType = {
|
||||
@@ -37,13 +39,12 @@ export type AppListItemType = {
|
||||
name: string;
|
||||
avatar: string;
|
||||
intro: string;
|
||||
isOwner: boolean;
|
||||
permission: `${PermissionTypeEnum}`;
|
||||
defaultPermission: PermissionValueType;
|
||||
permission: AppPermission;
|
||||
};
|
||||
|
||||
export type AppDetailType = AppSchema & {
|
||||
isOwner: boolean;
|
||||
canWrite: boolean;
|
||||
permission: AppPermission;
|
||||
};
|
||||
|
||||
export type AppSimpleEditFormType = {
|
||||
|
20
packages/global/support/permission/app/constant.ts
Normal file
20
packages/global/support/permission/app/constant.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { NullPermission, PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import { PermissionListType } from '../type';
|
||||
|
||||
export enum AppPermissionKeyEnum {}
|
||||
export const AppPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
description: '可使用该应用进行对话'
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
description: '可查看和编辑应用'
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
description: '写权限基础上,可配置发布渠道、查看对话日志、分配该应用权限'
|
||||
}
|
||||
};
|
||||
|
||||
export const AppDefaultPermission = NullPermission;
|
15
packages/global/support/permission/app/controller.ts
Normal file
15
packages/global/support/permission/app/controller.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { PerConstructPros, Permission } from '../controller';
|
||||
import { AppDefaultPermission } from './constant';
|
||||
|
||||
export class AppPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
if (!props) {
|
||||
props = {
|
||||
per: AppDefaultPermission
|
||||
};
|
||||
} else if (!props?.per) {
|
||||
props.per = AppDefaultPermission;
|
||||
}
|
||||
super(props);
|
||||
}
|
||||
}
|
0
packages/global/support/permission/app/type.d.ts
vendored
Normal file
0
packages/global/support/permission/app/type.d.ts
vendored
Normal file
9
packages/global/support/permission/collaborator.d.ts
vendored
Normal file
9
packages/global/support/permission/collaborator.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { PermissionValueType } from './type';
|
||||
|
||||
export type CollaboratorItemType = {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
permission: PermissionValueType;
|
||||
name: string;
|
||||
avatar: string;
|
||||
};
|
@@ -1,3 +1,6 @@
|
||||
import { Permission } from './controller';
|
||||
import { PermissionListType } from './type';
|
||||
|
||||
export enum AuthUserTypeEnum {
|
||||
token = 'token',
|
||||
root = 'root',
|
||||
@@ -21,8 +24,41 @@ export const PermissionTypeMap = {
|
||||
}
|
||||
};
|
||||
|
||||
export enum ResourceTypeEnum {
|
||||
export enum PerResourceTypeEnum {
|
||||
team = 'team',
|
||||
app = 'app',
|
||||
dataset = 'dataset'
|
||||
}
|
||||
|
||||
/* new permission */
|
||||
export enum PermissionKeyEnum {
|
||||
read = 'read',
|
||||
write = 'write',
|
||||
manage = 'manage'
|
||||
}
|
||||
export const PermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
name: '读权限',
|
||||
description: '',
|
||||
value: 0b100,
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
name: '写权限',
|
||||
description: '',
|
||||
value: 0b110, // 如果某个资源有特殊要求,再重写这个值
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
name: '管理员',
|
||||
description: '',
|
||||
value: 0b111,
|
||||
checkBoxType: 'single'
|
||||
}
|
||||
};
|
||||
|
||||
export const NullPermission = 0;
|
||||
export const OwnerPermissionVal = ~0 >>> 0;
|
||||
export const ReadPermissionVal = PermissionList['read'].value;
|
||||
export const WritePermissionVal = PermissionList['write'].value;
|
||||
export const ManagePermissionVal = PermissionList['manage'].value;
|
||||
|
71
packages/global/support/permission/controller.ts
Normal file
71
packages/global/support/permission/controller.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { PermissionValueType } from './type';
|
||||
import { PermissionList, NullPermission, OwnerPermissionVal } from './constant';
|
||||
|
||||
export type PerConstructPros = {
|
||||
per?: PermissionValueType;
|
||||
isOwner?: boolean;
|
||||
};
|
||||
|
||||
// the Permission helper class
|
||||
export class Permission {
|
||||
value: PermissionValueType;
|
||||
isOwner: boolean;
|
||||
hasManagePer: boolean;
|
||||
hasWritePer: boolean;
|
||||
hasReadPer: boolean;
|
||||
|
||||
constructor(props?: PerConstructPros) {
|
||||
const { per = NullPermission, isOwner = false } = props || {};
|
||||
if (isOwner) {
|
||||
this.value = OwnerPermissionVal;
|
||||
} else {
|
||||
this.value = per;
|
||||
}
|
||||
|
||||
this.isOwner = isOwner;
|
||||
this.hasManagePer = this.checkPer(PermissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(PermissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(PermissionList['read'].value);
|
||||
}
|
||||
|
||||
// add permission(s)
|
||||
// it can be chaining called.
|
||||
// @example
|
||||
// const perm = new Permission(permission)
|
||||
// perm.add(PermissionList['read'])
|
||||
// perm.add(PermissionList['read'], PermissionList['write'])
|
||||
// perm.add(PermissionList['read']).add(PermissionList['write'])
|
||||
addPer(...perList: PermissionValueType[]) {
|
||||
for (let oer of perList) {
|
||||
this.value = this.value | oer;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
}
|
||||
|
||||
removePer(...perList: PermissionValueType[]) {
|
||||
for (let per of perList) {
|
||||
this.value = this.value & ~per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
}
|
||||
|
||||
checkPer(perm: PermissionValueType): boolean {
|
||||
// if the permission is owner permission, only owner has this permission.
|
||||
if (perm === OwnerPermissionVal) {
|
||||
return this.value === OwnerPermissionVal;
|
||||
} else if (this.hasManagePer) {
|
||||
// The manager has all permissions except the owner permission
|
||||
return true;
|
||||
}
|
||||
return (this.value & perm) === perm;
|
||||
}
|
||||
|
||||
private updatePermissions() {
|
||||
this.isOwner = this.value === OwnerPermissionVal;
|
||||
this.hasManagePer = this.checkPer(PermissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(PermissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(PermissionList['read'].value);
|
||||
}
|
||||
}
|
21
packages/global/support/permission/type.d.ts
vendored
21
packages/global/support/permission/type.d.ts
vendored
@@ -1,6 +1,20 @@
|
||||
import { AuthUserTypeEnum } from './constant';
|
||||
import { TeamMemberWithUserSchema } from '../user/team/type';
|
||||
import { AuthUserTypeEnum, PermissionKeyEnum } from './constant';
|
||||
|
||||
// PermissionValueType, the type of permission's value is a number, which is a bit field actually.
|
||||
// It is spired by the permission system in Linux.
|
||||
// The lowest 3 bits present the permission of reading, writing and managing.
|
||||
// The higher bits are advanced permissions or extended permissions, which could be customized.
|
||||
export type PermissionValueType = number;
|
||||
export type PermissionListType<T = {}> = Record<
|
||||
T | PermissionKeyEnum,
|
||||
{
|
||||
name: string;
|
||||
description: string;
|
||||
value: PermissionValueType;
|
||||
checkBoxType: 'single' | 'multiple';
|
||||
}
|
||||
>;
|
||||
|
||||
export type AuthResponseType = {
|
||||
teamId: string;
|
||||
@@ -17,4 +31,9 @@ export type ResourcePermissionType = {
|
||||
tmbId: string;
|
||||
resourceType: ResourceType;
|
||||
permission: PermissionValueType;
|
||||
resourceId: string;
|
||||
};
|
||||
|
||||
export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> & {
|
||||
tmbId: TeamMemberWithUserSchema;
|
||||
};
|
||||
|
16
packages/global/support/permission/user/constant.ts
Normal file
16
packages/global/support/permission/user/constant.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { PermissionKeyEnum, PermissionList, ReadPermissionVal } from '../constant';
|
||||
|
||||
export const TeamPermissionList = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read]
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write]
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
description: '可邀请, 删除成员'
|
||||
}
|
||||
};
|
||||
|
||||
export const TeamDefaultPermissionVal = ReadPermissionVal;
|
15
packages/global/support/permission/user/controller.ts
Normal file
15
packages/global/support/permission/user/controller.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { PerConstructPros, Permission } from '../controller';
|
||||
import { TeamDefaultPermissionVal } from './constant';
|
||||
|
||||
export class TeamPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
if (!props) {
|
||||
props = {
|
||||
per: TeamDefaultPermissionVal
|
||||
};
|
||||
} else if (!props?.per) {
|
||||
props.per = TeamDefaultPermissionVal;
|
||||
}
|
||||
super(props);
|
||||
}
|
||||
}
|
@@ -1,22 +1,25 @@
|
||||
import { TeamMemberRoleEnum } from '../user/team/constant';
|
||||
import { PermissionTypeEnum } from './constant';
|
||||
import { Permission } from './controller';
|
||||
|
||||
/* team public source, or owner source in team */
|
||||
export function mongoRPermission({
|
||||
teamId,
|
||||
tmbId,
|
||||
role
|
||||
permission
|
||||
}: {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
permission: Permission;
|
||||
}) {
|
||||
if (permission.isOwner) {
|
||||
return {
|
||||
teamId
|
||||
};
|
||||
}
|
||||
return {
|
||||
teamId,
|
||||
...(role === TeamMemberRoleEnum.visitor && { permission: PermissionTypeEnum.public }),
|
||||
...(role === TeamMemberRoleEnum.admin && {
|
||||
$or: [{ permission: PermissionTypeEnum.public }, { tmbId }]
|
||||
})
|
||||
$or: [{ permission: PermissionTypeEnum.public }, { tmbId }]
|
||||
};
|
||||
}
|
||||
export function mongoOwnerPermission({ teamId, tmbId }: { teamId: string; tmbId: string }) {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { PermissionValueType } from 'support/permission/type';
|
||||
import { PermissionValueType } from '../../permission/type';
|
||||
import { TeamMemberRoleEnum } from './constant';
|
||||
import { LafAccountType, TeamMemberSchema } from './type';
|
||||
|
||||
@@ -22,7 +22,6 @@ export type UpdateTeamProps = {
|
||||
|
||||
/* ------------- member ----------- */
|
||||
export type DelMemberProps = {
|
||||
teamId: string;
|
||||
memberId: string;
|
||||
};
|
||||
export type UpdateTeamMemberProps = {
|
||||
@@ -46,7 +45,6 @@ export type InviteMemberResponse = Record<
|
||||
>;
|
||||
|
||||
export type UpdateTeamMemberPermissionProps = {
|
||||
teamId: string;
|
||||
memberIds: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
|
8
packages/global/support/user/team/type.d.ts
vendored
8
packages/global/support/user/team/type.d.ts
vendored
@@ -2,6 +2,7 @@ import type { UserModelSchema } from '../type';
|
||||
import type { TeamMemberRoleEnum, TeamMemberStatusEnum } from './constant';
|
||||
import { LafAccountType } from './type';
|
||||
import { PermissionValueType, ResourcePermissionType } from '../../permission/type';
|
||||
import { TeamPermission } from '../../permission/user/controller';
|
||||
|
||||
export type TeamSchema = {
|
||||
_id: string;
|
||||
@@ -49,7 +50,7 @@ export type TeamMemberWithTeamAndUserSchema = Omit<TeamMemberWithTeamSchema, 'us
|
||||
userId: UserModelSchema;
|
||||
};
|
||||
|
||||
export type TeamItemType = {
|
||||
export type TeamTmbItemType = {
|
||||
userId: string;
|
||||
teamId: string;
|
||||
teamName: string;
|
||||
@@ -61,9 +62,8 @@ export type TeamItemType = {
|
||||
defaultTeam: boolean;
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
status: `${TeamMemberStatusEnum}`;
|
||||
canWrite: boolean;
|
||||
lafAccount?: LafAccountType;
|
||||
defaultPermission: PermissionValueType;
|
||||
permission: TeamPermission;
|
||||
};
|
||||
|
||||
export type TeamMemberItemType = {
|
||||
@@ -75,7 +75,7 @@ export type TeamMemberItemType = {
|
||||
// TODO: this should be deprecated.
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
status: `${TeamMemberStatusEnum}`;
|
||||
permission: PermissionValueType;
|
||||
permission: TeamPermission;
|
||||
};
|
||||
|
||||
export type TeamTagItemType = {
|
||||
|
4
packages/global/support/user/type.d.ts
vendored
4
packages/global/support/user/type.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
import { UserStatusEnum } from './constant';
|
||||
import { TeamItemType } from './team/type';
|
||||
import { TeamTmbItemType } from './team/type';
|
||||
|
||||
export type UserModelSchema = {
|
||||
_id: string;
|
||||
@@ -29,6 +29,6 @@ export type UserType = {
|
||||
timezone: string;
|
||||
promotionRate: UserModelSchema['promotionRate'];
|
||||
openaiAccount: UserModelSchema['openaiAccount'];
|
||||
team: TeamItemType;
|
||||
team: TeamTmbItemType;
|
||||
standardInfo?: standardInfoType;
|
||||
};
|
||||
|
Reference in New Issue
Block a user