Skip to content

Commit

Permalink
Permission (#1687)
Browse files Browse the repository at this point in the history
Co-authored-by: Archer <[email protected]>
Co-authored-by: Finley Ge <[email protected]>
  • Loading branch information
c121914yu and FinleyGe authored Jun 4, 2024
1 parent fcb915c commit 19c8a06
Show file tree
Hide file tree
Showing 109 changed files with 2,290 additions and 1,090 deletions.
1 change: 0 additions & 1 deletion packages/global/common/system/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions packages/global/core/app/collaborator.d.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 5 deletions packages/global/core/app/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,23 +29,22 @@ export type AppSchema = {
scheduledTriggerConfig?: AppScheduledTriggerConfigType | null;
scheduledTriggerNextTime?: Date;

permission: `${PermissionTypeEnum}`;
inited?: boolean;
teamTags: string[];
defaultPermission: PermissionValueType;
};

export type AppListItemType = {
_id: string;
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 = {
Expand Down
20 changes: 20 additions & 0 deletions packages/global/support/permission/app/constant.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions packages/global/support/permission/app/controller.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
Empty file.
9 changes: 9 additions & 0 deletions packages/global/support/permission/collaborator.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { PermissionValueType } from './type';

export type CollaboratorItemType = {
teamId: string;
tmbId: string;
permission: PermissionValueType;
name: string;
avatar: string;
};
38 changes: 37 additions & 1 deletion packages/global/support/permission/constant.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Permission } from './controller';
import { PermissionListType } from './type';

export enum AuthUserTypeEnum {
token = 'token',
root = 'root',
Expand All @@ -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 changes: 71 additions & 0 deletions packages/global/support/permission/controller.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 1 deletion packages/global/support/permission/type.d.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -17,4 +31,9 @@ export type ResourcePermissionType = {
tmbId: string;
resourceType: ResourceType;
permission: PermissionValueType;
resourceId: string;
};

export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> & {
tmbId: TeamMemberWithUserSchema;
};
16 changes: 16 additions & 0 deletions packages/global/support/permission/user/constant.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions packages/global/support/permission/user/controller.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
15 changes: 9 additions & 6 deletions packages/global/support/permission/utils.ts
Original file line number Diff line number Diff line change
@@ -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 }) {
Expand Down
4 changes: 1 addition & 3 deletions packages/global/support/user/team/controller.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PermissionValueType } from 'support/permission/type';
import { PermissionValueType } from '../../permission/type';
import { TeamMemberRoleEnum } from './constant';
import { LafAccountType, TeamMemberSchema } from './type';

Expand All @@ -22,7 +22,6 @@ export type UpdateTeamProps = {

/* ------------- member ----------- */
export type DelMemberProps = {
teamId: string;
memberId: string;
};
export type UpdateTeamMemberProps = {
Expand All @@ -46,7 +45,6 @@ export type InviteMemberResponse = Record<
>;

export type UpdateTeamMemberPermissionProps = {
teamId: string;
memberIds: string[];
permission: PermissionValueType;
};
8 changes: 4 additions & 4 deletions packages/global/support/user/team/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -49,7 +50,7 @@ export type TeamMemberWithTeamAndUserSchema = Omit<TeamMemberWithTeamSchema, 'us
userId: UserModelSchema;
};

export type TeamItemType = {
export type TeamTmbItemType = {
userId: string;
teamId: string;
teamName: string;
Expand All @@ -61,9 +62,8 @@ export type TeamItemType = {
defaultTeam: boolean;
role: `${TeamMemberRoleEnum}`;
status: `${TeamMemberStatusEnum}`;
canWrite: boolean;
lafAccount?: LafAccountType;
defaultPermission: PermissionValueType;
permission: TeamPermission;
};

export type TeamMemberItemType = {
Expand All @@ -75,7 +75,7 @@ export type TeamMemberItemType = {
// TODO: this should be deprecated.
role: `${TeamMemberRoleEnum}`;
status: `${TeamMemberStatusEnum}`;
permission: PermissionValueType;
permission: TeamPermission;
};

export type TeamTagItemType = {
Expand Down
4 changes: 2 additions & 2 deletions packages/global/support/user/type.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UserStatusEnum } from './constant';
import { TeamItemType } from './team/type';
import { TeamTmbItemType } from './team/type';

export type UserModelSchema = {
_id: string;
Expand Down Expand Up @@ -29,6 +29,6 @@ export type UserType = {
timezone: string;
promotionRate: UserModelSchema['promotionRate'];
openaiAccount: UserModelSchema['openaiAccount'];
team: TeamItemType;
team: TeamTmbItemType;
standardInfo?: standardInfoType;
};
Loading

0 comments on commit 19c8a06

Please sign in to comment.