mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 20:37:48 +00:00
Team group (#2864)
* feat(member-group): Team (#2616) * feat: member-group schema define * feat(fe): create group * feat: add group edit modal * feat(fe): add avatar group component * feat: edit group fix: permission select menu style * feat: bio-mode support for select-member component * fix: avatar group key unique * feat: group manage * feat: divide member into group and clbs * feat: finish team permission * chore: adjust * fix: get clbs * perf: groups code * pref: member group for team (#2706) * chore: fe adjust fix: remove the member from groups when removing from team feat: change the groups avatar when updating the team's avatar * chore: DefaultGroupName as a constant string '' * fix: create default group when create team for root * feat: comment * feat: 4811 init * pref: member group for team (#2732) * chore: default group name * feat: get default group when get by tmbid * feat(fe): adjust * member ui * fix: delete group (#2736) * perf: init4811 * pref: member group (#2818) * fix: update clb per then refetch clb list * fix: calculate group permission * feat(fe): group tag * refactor(fe): team and group manage * feat: manage group member * feat: add group transfer owner modal * feat: group manage member * chore: adjust the file structure * pref: member group * chore: adjust fe style * fix: ts error * chore: fe adjust * chore: fe adjust * chore: adjust * chore: adjust the code * perf: i18n and schema name * pref: member-group (#2862) * feat: group list ordered by updateTime * fix: transfer ownership of group when deleting member * fix: i18n fix * feat: can not set member as admin/owner when user is not active * fix: GroupInfoModal hover input do not change color * fix(fe): searchinput do not scroll * perf: team group ui * doc * remove enum --------- Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,12 @@ export enum TeamErrEnum {
|
||||
appAmountNotEnough = 'appAmountNotEnough',
|
||||
pluginAmountNotEnough = 'pluginAmountNotEnough',
|
||||
websiteSyncNotEnough = 'websiteSyncNotEnough',
|
||||
reRankNotEnough = 'reRankNotEnough'
|
||||
reRankNotEnough = 'reRankNotEnough',
|
||||
groupNameEmpty = 'groupNameEmpty',
|
||||
groupNameDuplicate = 'groupNameDuplicate',
|
||||
groupNotExist = 'groupNotExist',
|
||||
cannotDeleteDefaultGroup = 'cannotDeleteDefaultGroup',
|
||||
userNotActive = 'userNotActive'
|
||||
}
|
||||
|
||||
const teamErr = [
|
||||
@@ -46,6 +51,26 @@ const teamErr = [
|
||||
{
|
||||
statusText: TeamErrEnum.reRankNotEnough,
|
||||
message: i18nT('common:code_error.team_error.re_rank_not_enough')
|
||||
},
|
||||
{
|
||||
statusText: TeamErrEnum.groupNameEmpty,
|
||||
message: i18nT('common:code_error.team_error.group_name_empty')
|
||||
},
|
||||
{
|
||||
statusText: TeamErrEnum.groupNotExist,
|
||||
message: i18nT('common:code_error.team_error.group_not_exist')
|
||||
},
|
||||
{
|
||||
statusText: TeamErrEnum.cannotDeleteDefaultGroup,
|
||||
message: i18nT('common:code_error.team_error.cannot_delete_default_group')
|
||||
},
|
||||
{
|
||||
statusText: TeamErrEnum.groupNameDuplicate,
|
||||
message: i18nT('common:code_error.team_error.group_name_duplicate')
|
||||
},
|
||||
{
|
||||
statusText: TeamErrEnum.userNotActive,
|
||||
message: i18nT('common:code_error.team_error.user_not_active')
|
||||
}
|
||||
];
|
||||
|
||||
|
@@ -7,6 +7,7 @@ export enum MongoImageTypeEnum {
|
||||
datasetAvatar = 'datasetAvatar',
|
||||
userAvatar = 'userAvatar',
|
||||
teamAvatar = 'teamAvatar',
|
||||
groupAvatar = 'groupAvatar',
|
||||
|
||||
chatImage = 'chatImage',
|
||||
collectionImage = 'collectionImage'
|
||||
@@ -36,6 +37,10 @@ export const mongoImageTypeMap = {
|
||||
label: 'teamAvatar',
|
||||
unique: true
|
||||
},
|
||||
[MongoImageTypeEnum.groupAvatar]: {
|
||||
label: 'groupAvatar',
|
||||
unique: true
|
||||
},
|
||||
|
||||
[MongoImageTypeEnum.chatImage]: {
|
||||
label: 'chatImage',
|
||||
|
@@ -1,3 +1,4 @@
|
||||
export const HUMAN_ICON = `/icon/human.svg`;
|
||||
export const LOGO_ICON = `/icon/logo.svg`;
|
||||
export const HUGGING_FACE_ICON = `/imgs/model/huggingface.svg`;
|
||||
export const DEFAULT_TEAM_AVATAR = `/imgs/avatar/defaultTeamAvatar.svg`;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { RequireAtLeastOne, RequireOnlyOne } from '../../common/type/utils';
|
||||
import { Permission } from './controller';
|
||||
import { PermissionValueType } from './type';
|
||||
|
||||
@@ -10,6 +11,19 @@ export type CollaboratorItemType = {
|
||||
};
|
||||
|
||||
export type UpdateClbPermissionProps = {
|
||||
tmbIds: string[];
|
||||
members?: string[];
|
||||
groups?: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
|
||||
export type DeleteClbPermissionProps = RequireOnlyOne<{
|
||||
tmbId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
||||
export type UpdatePermissionBody = {
|
||||
permission: PermissionValueType;
|
||||
} & RequireOnlyOne<{
|
||||
memberId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
@@ -61,7 +61,7 @@ export const PermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.write]: {
|
||||
name: i18nT('common:permission.write'),
|
||||
description: '',
|
||||
value: 0b110, // 如果某个资源有特殊要求,再重写这个值
|
||||
value: 0b110,
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { PermissionValueType } from './type';
|
||||
import { PermissionListType, PermissionValueType } from './type';
|
||||
import { PermissionList, NullPermission, OwnerPermissionVal } from './constant';
|
||||
|
||||
export type PerConstructPros = {
|
||||
per?: PermissionValueType;
|
||||
isOwner?: boolean;
|
||||
permissionList?: PermissionListType;
|
||||
};
|
||||
|
||||
// the Permission helper class
|
||||
@@ -13,9 +14,10 @@ export class Permission {
|
||||
hasManagePer: boolean;
|
||||
hasWritePer: boolean;
|
||||
hasReadPer: boolean;
|
||||
_permissionList: PermissionListType;
|
||||
|
||||
constructor(props?: PerConstructPros) {
|
||||
const { per = NullPermission, isOwner = false } = props || {};
|
||||
const { per = NullPermission, isOwner = false, permissionList = PermissionList } = props || {};
|
||||
if (isOwner) {
|
||||
this.value = OwnerPermissionVal;
|
||||
} else {
|
||||
@@ -23,9 +25,10 @@ export class Permission {
|
||||
}
|
||||
|
||||
this.isOwner = isOwner;
|
||||
this.hasManagePer = this.checkPer(PermissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(PermissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(PermissionList['read'].value);
|
||||
this._permissionList = permissionList;
|
||||
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
|
||||
}
|
||||
|
||||
// add permission(s)
|
||||
@@ -36,36 +39,39 @@ export class Permission {
|
||||
// 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;
|
||||
if (this.isOwner) {
|
||||
return this;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value | per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
return this;
|
||||
}
|
||||
|
||||
removePer(...perList: PermissionValueType[]) {
|
||||
for (let per of perList) {
|
||||
if (this.isOwner) {
|
||||
return this.value;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value & ~per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
return this;
|
||||
}
|
||||
|
||||
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);
|
||||
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
|
||||
}
|
||||
}
|
||||
|
23
packages/global/support/permission/memberGroup/constant.ts
Normal file
23
packages/global/support/permission/memberGroup/constant.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import { PermissionListType } from '../type';
|
||||
|
||||
export enum GroupMemberRole {
|
||||
owner = 'owner',
|
||||
admin = 'admin',
|
||||
member = 'member'
|
||||
}
|
||||
|
||||
export const memberGroupPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
value: 0b100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
value: 0b010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
value: 0b001
|
||||
}
|
||||
};
|
27
packages/global/support/permission/memberGroup/type.d.ts
vendored
Normal file
27
packages/global/support/permission/memberGroup/type.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { TeamMemberItemType } from 'support/user/team/type';
|
||||
import { TeamPermission } from '../user/controller';
|
||||
import { GroupMemberRole } from './constant';
|
||||
|
||||
type MemberGroupSchemaType = {
|
||||
_id: string;
|
||||
teamId: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
updateTime: Date;
|
||||
};
|
||||
|
||||
type GroupMemberSchemaType = {
|
||||
groupId: string;
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
};
|
||||
|
||||
type MemberGroupType = MemberGroupSchemaType & {
|
||||
members: {
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
}[]; // we can get tmb's info from other api. there is no need but only need to get tmb's id
|
||||
permission: TeamPermission;
|
||||
};
|
||||
|
||||
type MemberGroupListType = MemberGroupType[];
|
7
packages/global/support/permission/type.d.ts
vendored
7
packages/global/support/permission/type.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
import { RequireOnlyOne } from '../../common/type/utils';
|
||||
import { TeamMemberWithUserSchema } from '../user/team/type';
|
||||
import { AuthUserTypeEnum, PermissionKeyEnum, PerResourceTypeEnum } from './constant';
|
||||
|
||||
@@ -20,11 +21,13 @@ export type PermissionListType<T = {}> = Record<
|
||||
|
||||
export type ResourcePermissionType = {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
resourceType: ResourceType;
|
||||
permission: PermissionValueType;
|
||||
resourceId: string;
|
||||
};
|
||||
} & RequireOnlyOne<{
|
||||
tmbId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
||||
export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> & {
|
||||
tmbId: TeamMemberWithUserSchema;
|
||||
|
@@ -1,19 +1,22 @@
|
||||
import { PermissionKeyEnum, PermissionList, ReadPermissionVal } from '../constant';
|
||||
import { PermissionKeyEnum } from '../constant';
|
||||
import { PermissionListType } from '../type';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
import { PermissionList } from '../constant';
|
||||
export const TeamPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
description: i18nT('user:permission_des.read')
|
||||
value: 0b100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
description: i18nT('user:permission_des.write')
|
||||
value: 0b010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
description: i18nT('user:permission_des.manage')
|
||||
value: 0b001
|
||||
}
|
||||
};
|
||||
|
||||
export const TeamDefaultPermissionVal = ReadPermissionVal;
|
||||
export const TeamReadPermissionVal = TeamPermissionList['read'].value;
|
||||
export const TeamWritePermissionVal = TeamPermissionList['write'].value;
|
||||
export const TeamManagePermissionVal = TeamPermissionList['manage'].value;
|
||||
export const TeamDefaultPermissionVal = TeamReadPermissionVal;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { PerConstructPros, Permission } from '../controller';
|
||||
import { TeamDefaultPermissionVal } from './constant';
|
||||
import { TeamDefaultPermissionVal, TeamPermissionList } from './constant';
|
||||
|
||||
export class TeamPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
@@ -10,6 +10,7 @@ export class TeamPermission extends Permission {
|
||||
} else if (!props?.per) {
|
||||
props.per = TeamDefaultPermissionVal;
|
||||
}
|
||||
props.permissionList = TeamPermissionList;
|
||||
super(props);
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,6 @@ export type UpdateTeamMemberProps = {
|
||||
export type InviteMemberProps = {
|
||||
teamId: string;
|
||||
usernames: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
export type UpdateInviteProps = {
|
||||
tmbId: string;
|
||||
|
17
packages/global/support/user/team/group/api.d.ts
vendored
Normal file
17
packages/global/support/user/team/group/api.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { GroupMemberRole } from '../../../../support/permission/memberGroup/constant';
|
||||
|
||||
export type postCreateGroupData = {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
memberIdList?: string[];
|
||||
};
|
||||
|
||||
export type putUpdateGroupData = {
|
||||
groupId: string;
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
memberList?: {
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
}[];
|
||||
};
|
1
packages/global/support/user/team/group/constant.ts
Normal file
1
packages/global/support/user/team/group/constant.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const DefaultGroupName = 'DEFAULT_GROUP';
|
4
packages/global/support/user/team/type.d.ts
vendored
4
packages/global/support/user/team/type.d.ts
vendored
@@ -17,7 +17,6 @@ export type TeamSchema = {
|
||||
lastWebsiteSyncTime: Date;
|
||||
};
|
||||
lafAccount: LafAccountType;
|
||||
defaultPermission: PermissionValueType;
|
||||
notificationAccount?: string;
|
||||
};
|
||||
|
||||
@@ -25,6 +24,7 @@ export type tagsType = {
|
||||
label: string;
|
||||
key: string;
|
||||
};
|
||||
|
||||
export type TeamTagSchema = TeamTagItemType & {
|
||||
_id: string;
|
||||
teamId: string;
|
||||
@@ -45,9 +45,11 @@ export type TeamMemberSchema = {
|
||||
export type TeamMemberWithUserSchema = Omit<TeamMemberSchema, 'userId'> & {
|
||||
userId: UserModelSchema;
|
||||
};
|
||||
|
||||
export type TeamMemberWithTeamSchema = Omit<TeamMemberSchema, 'teamId'> & {
|
||||
teamId: TeamSchema;
|
||||
};
|
||||
|
||||
export type TeamMemberWithTeamAndUserSchema = Omit<TeamMemberWithTeamSchema, 'userId'> & {
|
||||
userId: UserModelSchema;
|
||||
};
|
||||
|
Reference in New Issue
Block a user