mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-13 14:29:40 +00:00
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
This commit is contained in:
@@ -1,20 +1,56 @@
|
||||
import { NullPermission, PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import { type PermissionListType } from '../type';
|
||||
import {
|
||||
NullRoleVal,
|
||||
CommonPerKeyEnum,
|
||||
CommonRoleList,
|
||||
CommonPerList,
|
||||
CommonRolePerMap
|
||||
} from '../constant';
|
||||
import type { PermissionListType, PermissionValueType, RolePerMapType } from '../type';
|
||||
import { type RoleListType } from '../type';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
export enum AppPermissionKeyEnum {}
|
||||
export const AppPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
import { sumPer } from '../utils';
|
||||
|
||||
export enum AppPermissionKeyEnum {
|
||||
ReadChatLog = 'readChatLog'
|
||||
}
|
||||
|
||||
export const AppPerList: PermissionListType<AppPermissionKeyEnum> = {
|
||||
...CommonPerList,
|
||||
readChatLog: 0b1000
|
||||
};
|
||||
|
||||
export const AppRoleList: RoleListType<AppPermissionKeyEnum> = {
|
||||
[CommonPerKeyEnum.read]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.read],
|
||||
description: i18nT('app:permission.des.read')
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
[CommonPerKeyEnum.write]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.write],
|
||||
description: i18nT('app:permission.des.write')
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
[CommonPerKeyEnum.manage]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.manage],
|
||||
description: i18nT('app:permission.des.manage')
|
||||
},
|
||||
[AppPermissionKeyEnum.ReadChatLog]: {
|
||||
value: 0b1000,
|
||||
checkBoxType: 'multiple',
|
||||
name: i18nT('app:permission.name.readChatLog'),
|
||||
description: i18nT('app:permission.des.readChatLog')
|
||||
}
|
||||
};
|
||||
|
||||
export const AppDefaultPermissionVal = NullPermission;
|
||||
export const AppRolePerMap: RolePerMapType = new Map([
|
||||
...CommonRolePerMap,
|
||||
[
|
||||
AppRoleList[AppPermissionKeyEnum.ReadChatLog].value,
|
||||
sumPer(
|
||||
CommonPerList[CommonPerKeyEnum.read],
|
||||
AppPerList[AppPermissionKeyEnum.ReadChatLog]
|
||||
) as PermissionValueType
|
||||
]
|
||||
]);
|
||||
|
||||
export const AppDefaultRoleVal = NullRoleVal;
|
||||
export const AppReadChatLogPerVal = AppPerList[AppPermissionKeyEnum.ReadChatLog];
|
||||
export const AppReadChatLogRoleVal = AppRoleList[AppPermissionKeyEnum.ReadChatLog].value;
|
||||
|
@@ -1,15 +1,25 @@
|
||||
import { type PerConstructPros, Permission } from '../controller';
|
||||
import { AppDefaultPermissionVal } from './constant';
|
||||
import { AppDefaultRoleVal, AppPerList, AppRoleList, AppRolePerMap } from './constant';
|
||||
|
||||
export class AppPermission extends Permission {
|
||||
hasReadChatLogPer: boolean = false;
|
||||
hasReadChatLogRole: boolean = false;
|
||||
constructor(props?: PerConstructPros) {
|
||||
if (!props) {
|
||||
props = {
|
||||
per: AppDefaultPermissionVal
|
||||
role: AppDefaultRoleVal
|
||||
};
|
||||
} else if (!props?.per) {
|
||||
props.per = AppDefaultPermissionVal;
|
||||
} else if (!props?.role) {
|
||||
props.role = AppDefaultRoleVal;
|
||||
}
|
||||
props.roleList = AppRoleList;
|
||||
props.rolePerMap = AppRolePerMap;
|
||||
props.perList = AppPerList;
|
||||
super(props);
|
||||
|
||||
this.setUpdatePermissionCallback(() => {
|
||||
this.hasReadChatLogPer = this.checkPer(AppPerList.readChatLog);
|
||||
this.hasReadChatLogRole = this.checkRole(AppRoleList.readChatLog.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
import { type PermissionListType } from './type';
|
||||
import type { PermissionListType, PermissionValueType, RolePerMapType } from './type';
|
||||
import { type RoleListType } from './type';
|
||||
import { i18nT } from '../../../web/i18n/utils';
|
||||
import { sumPer } from './utils';
|
||||
export enum AuthUserTypeEnum {
|
||||
token = 'token',
|
||||
root = 'root',
|
||||
@@ -15,6 +17,12 @@ export enum PermissionTypeEnum {
|
||||
publicRead = 'publicRead',
|
||||
publicWrite = 'publicWrite'
|
||||
}
|
||||
|
||||
export const NullRoleVal = 0;
|
||||
export const NullPermissionVal = 0;
|
||||
export const OwnerRoleVal = ~0 >>> 0;
|
||||
export const OwnerPermissionVal = ~0 >>> 0;
|
||||
|
||||
export const PermissionTypeMap = {
|
||||
[PermissionTypeEnum.private]: {
|
||||
iconLight: 'support/permission/privateLight',
|
||||
@@ -45,34 +53,63 @@ export enum PerResourceTypeEnum {
|
||||
}
|
||||
|
||||
/* new permission */
|
||||
export enum PermissionKeyEnum {
|
||||
export enum CommonPerKeyEnum {
|
||||
owner = 'owner',
|
||||
read = 'read',
|
||||
write = 'write',
|
||||
manage = 'manage'
|
||||
}
|
||||
export const PermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
|
||||
export enum CommonRoleKeyEnum {
|
||||
read = 'read',
|
||||
write = 'write',
|
||||
manage = 'manage'
|
||||
}
|
||||
|
||||
export const CommonPerList: PermissionListType = {
|
||||
[CommonPerKeyEnum.owner]: OwnerRoleVal,
|
||||
[CommonPerKeyEnum.read]: 0b100,
|
||||
[CommonPerKeyEnum.write]: 0b010,
|
||||
[CommonPerKeyEnum.manage]: 0b001
|
||||
} as const;
|
||||
|
||||
export const CommonRoleList: RoleListType = {
|
||||
[CommonRoleKeyEnum.read]: {
|
||||
name: i18nT('common:permission.read'),
|
||||
description: '',
|
||||
value: 0b100,
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
[CommonRoleKeyEnum.write]: {
|
||||
name: i18nT('common:permission.write'),
|
||||
description: '',
|
||||
value: 0b110,
|
||||
value: 0b010,
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
[CommonRoleKeyEnum.manage]: {
|
||||
name: i18nT('common:permission.manager'),
|
||||
description: '',
|
||||
value: 0b111,
|
||||
value: 0b001,
|
||||
checkBoxType: 'single'
|
||||
}
|
||||
};
|
||||
} as const;
|
||||
|
||||
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;
|
||||
export const CommonRolePerMap: RolePerMapType = new Map([
|
||||
[CommonRoleList['read'].value, CommonPerList.read],
|
||||
[
|
||||
CommonRoleList['write'].value,
|
||||
sumPer(CommonPerList.write, CommonPerList.read) as PermissionValueType
|
||||
],
|
||||
[
|
||||
CommonRoleList['manage'].value,
|
||||
sumPer(CommonPerList.manage, CommonPerList.write, CommonPerList.read) as PermissionValueType
|
||||
]
|
||||
]);
|
||||
|
||||
export const ReadRoleVal = CommonRoleList['read'].value;
|
||||
export const WriteRoleVal = CommonRoleList['write'].value;
|
||||
export const ManageRoleVal = CommonRoleList['manage'].value;
|
||||
|
||||
export const ManagePermissionVal = CommonPerList.manage;
|
||||
export const ReadPermissionVal = CommonPerList.read;
|
||||
export const WritePermissionVal = CommonPerList.write;
|
||||
|
@@ -1,58 +1,86 @@
|
||||
import { type PermissionListType, type PermissionValueType } from './type';
|
||||
import { PermissionList, NullPermission, OwnerPermissionVal } from './constant';
|
||||
import type {
|
||||
RoleValueType,
|
||||
RoleListType,
|
||||
PermissionValueType,
|
||||
PermissionListType,
|
||||
RolePerMapType
|
||||
} from './type';
|
||||
import {
|
||||
CommonPerList,
|
||||
CommonRoleList,
|
||||
CommonRolePerMap,
|
||||
NullPermissionVal,
|
||||
NullRoleVal,
|
||||
OwnerPermissionVal,
|
||||
OwnerRoleVal
|
||||
} from './constant';
|
||||
|
||||
export type PerConstructPros = {
|
||||
per?: PermissionValueType;
|
||||
role?: RoleValueType;
|
||||
|
||||
isOwner?: boolean;
|
||||
permissionList?: PermissionListType;
|
||||
childUpdatePermissionCallback?: () => void;
|
||||
|
||||
roleList?: RoleListType;
|
||||
perList?: PermissionListType;
|
||||
rolePerMap?: RolePerMapType;
|
||||
};
|
||||
|
||||
// the Permission helper class
|
||||
/**
|
||||
* the Permission helper class
|
||||
*/
|
||||
export class Permission {
|
||||
value: PermissionValueType;
|
||||
role: PermissionValueType;
|
||||
private permission: PermissionValueType = NullRoleVal; // default role
|
||||
|
||||
isOwner: boolean = false;
|
||||
|
||||
hasManagePer: boolean = false;
|
||||
hasWritePer: boolean = false;
|
||||
hasReadPer: boolean = false;
|
||||
_permissionList: PermissionListType;
|
||||
hasManageRole: boolean = false;
|
||||
hasWriteRole: boolean = false;
|
||||
hasReadRole: boolean = false;
|
||||
|
||||
constructor(props?: PerConstructPros) {
|
||||
const { per = NullPermission, isOwner = false, permissionList = PermissionList } = props || {};
|
||||
readonly roleList: RoleListType;
|
||||
readonly perList: PermissionListType;
|
||||
readonly rolePerMap: RolePerMapType;
|
||||
|
||||
constructor({
|
||||
role = NullRoleVal,
|
||||
isOwner = false,
|
||||
roleList = CommonRoleList,
|
||||
perList = CommonPerList,
|
||||
rolePerMap = CommonRolePerMap
|
||||
}: PerConstructPros = {}) {
|
||||
if (isOwner) {
|
||||
this.value = OwnerPermissionVal;
|
||||
this.role = OwnerRoleVal;
|
||||
} else {
|
||||
this.value = per;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
this._permissionList = permissionList;
|
||||
this.roleList = roleList;
|
||||
this.perList = perList;
|
||||
this.rolePerMap = rolePerMap;
|
||||
this.updatePermissions();
|
||||
}
|
||||
|
||||
// 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[]) {
|
||||
addRole(...roleList: RoleValueType[]) {
|
||||
if (this.isOwner) {
|
||||
return this;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value | per;
|
||||
for (const per of roleList) {
|
||||
this.role = this.role | per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this;
|
||||
}
|
||||
|
||||
removePer(...perList: PermissionValueType[]) {
|
||||
removeRole(...roleList: RoleValueType[]) {
|
||||
if (this.isOwner) {
|
||||
return this.value;
|
||||
return this.role;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value & ~per;
|
||||
for (const per of roleList) {
|
||||
this.role = this.role & ~per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this;
|
||||
@@ -61,9 +89,16 @@ export class Permission {
|
||||
checkPer(perm: PermissionValueType): boolean {
|
||||
// if the permission is owner permission, only owner has this permission.
|
||||
if (perm === OwnerPermissionVal) {
|
||||
return this.value === OwnerPermissionVal;
|
||||
return this.permission === OwnerPermissionVal;
|
||||
}
|
||||
return (this.value & perm) === perm;
|
||||
return (this.permission & perm) === perm;
|
||||
}
|
||||
|
||||
checkRole(role: RoleValueType): boolean {
|
||||
if (role === OwnerRoleVal) {
|
||||
return this.role === OwnerRoleVal;
|
||||
}
|
||||
return (this.role & role) === role;
|
||||
}
|
||||
|
||||
private updatePermissionCallback?: () => void;
|
||||
@@ -72,15 +107,32 @@ export class Permission {
|
||||
this.updatePermissionCallback = callback;
|
||||
}
|
||||
|
||||
private updatePermissions() {
|
||||
this.isOwner = this.value === OwnerPermissionVal;
|
||||
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
|
||||
this.updatePermissionCallback?.();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
toBinary() {
|
||||
return this.value.toString(2);
|
||||
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?.();
|
||||
}
|
||||
}
|
||||
|
@@ -1,21 +1,30 @@
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
import { NullPermission, PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import {
|
||||
NullRoleVal,
|
||||
CommonPerKeyEnum,
|
||||
CommonRoleList,
|
||||
CommonRolePerMap,
|
||||
CommonPerList
|
||||
} from '../constant';
|
||||
import type { RolePerMapType } from '../type';
|
||||
|
||||
export enum DatasetPermissionKeyEnum {}
|
||||
|
||||
export const DatasetPermissionList = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
export const DatasetRoleList = {
|
||||
[CommonPerKeyEnum.read]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.read],
|
||||
description: i18nT('dataset:permission.des.read')
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
[CommonPerKeyEnum.write]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.write],
|
||||
description: i18nT('dataset:permission.des.write')
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
[CommonPerKeyEnum.manage]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.manage],
|
||||
description: i18nT('dataset:permission.des.manage')
|
||||
}
|
||||
};
|
||||
|
||||
export const DatasetDefaultPermissionVal = NullPermission;
|
||||
export const DatasetRolePerMap: RolePerMapType = CommonRolePerMap;
|
||||
|
||||
export const DatasetPerList = CommonPerList;
|
||||
|
||||
export const DataSetDefaultRoleVal = NullRoleVal;
|
||||
|
@@ -1,14 +1,22 @@
|
||||
import { NullPermission } from '../constant';
|
||||
import { type PerConstructPros, Permission } from '../controller';
|
||||
import {
|
||||
DataSetDefaultRoleVal,
|
||||
DatasetPerList,
|
||||
DatasetRoleList,
|
||||
DatasetRolePerMap
|
||||
} from './constant';
|
||||
export class DatasetPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
if (!props) {
|
||||
props = {
|
||||
per: NullPermission
|
||||
role: DataSetDefaultRoleVal
|
||||
};
|
||||
} else if (!props?.per) {
|
||||
props.per = NullPermission;
|
||||
} else if (!props?.role) {
|
||||
props.role = DataSetDefaultRoleVal;
|
||||
}
|
||||
props.roleList = DatasetRoleList;
|
||||
props.rolePerMap = DatasetRolePerMap;
|
||||
props.perList = DatasetPerList;
|
||||
super(props);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import { type PermissionListType } from '../type';
|
||||
import { CommonPerKeyEnum, CommonRoleList } from '../constant';
|
||||
import { type RoleListType } from '../type';
|
||||
|
||||
export enum GroupMemberRole {
|
||||
owner = 'owner',
|
||||
@@ -7,17 +7,17 @@ export enum GroupMemberRole {
|
||||
member = 'member'
|
||||
}
|
||||
|
||||
export const memberGroupPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
export const memberGroupPermissionList: RoleListType = {
|
||||
[CommonPerKeyEnum.read]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.read],
|
||||
value: 0b100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
[CommonPerKeyEnum.write]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.write],
|
||||
value: 0b010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
[CommonPerKeyEnum.manage]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.manage],
|
||||
value: 0b001
|
||||
}
|
||||
};
|
||||
|
56
packages/global/support/permission/type.d.ts
vendored
56
packages/global/support/permission/type.d.ts
vendored
@@ -3,25 +3,63 @@ import type { RequireOnlyOne } from '../../common/type/utils';
|
||||
import type { TeamMemberSchema } from '../user/team/type';
|
||||
import { MemberGroupSchemaType } from './memberGroup/type';
|
||||
import type { TeamMemberWithUserSchema } from '../user/team/type';
|
||||
import { AuthUserTypeEnum, type PermissionKeyEnum, type PerResourceTypeEnum } from './constant';
|
||||
import type { CommonPerKeyEnum, CommonRoleKeyEnum } from './constant';
|
||||
import { AuthUserTypeEnum, type CommonPerKeyEnum, type PerResourceTypeEnum } 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 RoleValueType = number;
|
||||
|
||||
export type ResourceType = `${PerResourceTypeEnum}`;
|
||||
|
||||
export type PermissionListType<T = {}> = Record<
|
||||
T | PermissionKeyEnum,
|
||||
{
|
||||
name: string;
|
||||
description: string;
|
||||
value: PermissionValueType;
|
||||
checkBoxType: 'single' | 'multiple';
|
||||
}
|
||||
/**
|
||||
* Define the roles. Each role is a binary number, only one bit is set to 1.
|
||||
*/
|
||||
export type RoleListType<T = {}> = Readonly<
|
||||
Record<
|
||||
T | CommonRoleKeyEnum,
|
||||
Readonly<{
|
||||
name: string;
|
||||
description: string;
|
||||
value: RoleValueType;
|
||||
checkBoxType: 'single' | 'multiple';
|
||||
}>
|
||||
>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Define the permissions. Each permission is a binary number, only one bit is set to 1.
|
||||
* @example
|
||||
* CommonPerList = {
|
||||
* read: 0b100,
|
||||
* write: 0b010,
|
||||
* manage: 0b001
|
||||
* }
|
||||
* @example_bad
|
||||
* CommonPerList = {
|
||||
* write: 0b110, // bad, should be 0b010
|
||||
* }
|
||||
*/
|
||||
export type PermissionListType<T = {}> = Readonly<
|
||||
Record<T | CommonPerKeyEnum, PermissionValueType>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Define the role-permission map. Each role has a permission.
|
||||
* @key: role (binary number), only one bit is set to 1.
|
||||
* @value: permission (binary number), multiple bits are set to 1.
|
||||
* @example
|
||||
* CommonRolePerMap = {
|
||||
* 0b100: 0b100,
|
||||
* 0b010: 0b110,
|
||||
* 0b001: 0b111
|
||||
* }
|
||||
*/
|
||||
export type RolePerMapType = Readonly<Map<RoleValueType, PermissionValueType>>;
|
||||
|
||||
export type ResourcePermissionType = {
|
||||
teamId: string;
|
||||
resourceType: ResourceType;
|
||||
|
@@ -1,39 +1,59 @@
|
||||
import { PermissionKeyEnum } from '../constant';
|
||||
import { type PermissionListType } from '../type';
|
||||
import { PermissionList } from '../constant';
|
||||
import { CommonPerKeyEnum, CommonRolePerMap } from '../constant';
|
||||
import type {
|
||||
PermissionListType,
|
||||
PermissionValueType,
|
||||
RoleListType,
|
||||
RolePerMapType
|
||||
} from '../type';
|
||||
import { CommonRoleList, CommonPerList } from '../constant';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
export enum TeamPermissionKeyEnum {
|
||||
import { sumPer } from '../utils';
|
||||
|
||||
export enum TeamPerKeyEnum {
|
||||
appCreate = 'appCreate',
|
||||
datasetCreate = 'datasetCreate',
|
||||
apikeyCreate = 'apikeyCreate'
|
||||
}
|
||||
|
||||
export const TeamPermissionList: PermissionListType<TeamPermissionKeyEnum> = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
export enum TeamRoleKeyEnum {
|
||||
appCreate = 'appCreate',
|
||||
datasetCreate = 'datasetCreate',
|
||||
apikeyCreate = 'apikeyCreate'
|
||||
}
|
||||
|
||||
export const TeamPerList: PermissionListType<TeamPerKeyEnum> = {
|
||||
...CommonPerList,
|
||||
apikeyCreate: 0b100000,
|
||||
appCreate: 0b001000,
|
||||
datasetCreate: 0b010000
|
||||
};
|
||||
|
||||
export const TeamRoleList: RoleListType<TeamRoleKeyEnum> = {
|
||||
[CommonPerKeyEnum.read]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.read],
|
||||
value: 0b000100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
[CommonPerKeyEnum.write]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.write],
|
||||
value: 0b000010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
[CommonPerKeyEnum.manage]: {
|
||||
...CommonRoleList[CommonPerKeyEnum.manage],
|
||||
value: 0b000001
|
||||
},
|
||||
[TeamPermissionKeyEnum.appCreate]: {
|
||||
[TeamRoleKeyEnum.appCreate]: {
|
||||
checkBoxType: 'multiple',
|
||||
description: '',
|
||||
name: i18nT('account_team:permission_appCreate'),
|
||||
value: 0b001000
|
||||
},
|
||||
[TeamPermissionKeyEnum.datasetCreate]: {
|
||||
[TeamRoleKeyEnum.datasetCreate]: {
|
||||
checkBoxType: 'multiple',
|
||||
description: '',
|
||||
name: i18nT('account_team:permission_datasetCreate'),
|
||||
value: 0b010000
|
||||
},
|
||||
[TeamPermissionKeyEnum.apikeyCreate]: {
|
||||
[TeamRoleKeyEnum.apikeyCreate]: {
|
||||
checkBoxType: 'multiple',
|
||||
description: '',
|
||||
name: i18nT('account_team:permission_apikeyCreate'),
|
||||
@@ -41,10 +61,38 @@ export const TeamPermissionList: PermissionListType<TeamPermissionKeyEnum> = {
|
||||
}
|
||||
};
|
||||
|
||||
export const TeamReadPermissionVal = TeamPermissionList['read'].value;
|
||||
export const TeamWritePermissionVal = TeamPermissionList['write'].value;
|
||||
export const TeamManagePermissionVal = TeamPermissionList['manage'].value;
|
||||
export const TeamAppCreatePermissionVal = TeamPermissionList['appCreate'].value;
|
||||
export const TeamDatasetCreatePermissionVal = TeamPermissionList['datasetCreate'].value;
|
||||
export const TeamApikeyCreatePermissionVal = TeamPermissionList['apikeyCreate'].value;
|
||||
export const TeamRolePerMap: RolePerMapType = new Map([
|
||||
...CommonRolePerMap,
|
||||
[
|
||||
TeamRoleList['appCreate'].value,
|
||||
sumPer(TeamPerList.appCreate, CommonPerList.read, CommonPerList.write) as PermissionValueType
|
||||
],
|
||||
[
|
||||
TeamRoleList['datasetCreate'].value,
|
||||
sumPer(
|
||||
TeamPerList.datasetCreate,
|
||||
CommonPerList.read,
|
||||
CommonPerList.write
|
||||
) as PermissionValueType
|
||||
],
|
||||
[
|
||||
TeamRoleList['apikeyCreate'].value,
|
||||
sumPer(TeamPerList.apikeyCreate, CommonPerList.read, CommonPerList.write) as PermissionValueType
|
||||
]
|
||||
]);
|
||||
|
||||
export const TeamReadRoleVal = TeamRoleList['read'].value;
|
||||
export const TeamWriteRoleVal = TeamRoleList['write'].value;
|
||||
export const TeamManageRoleVal = TeamRoleList['manage'].value;
|
||||
export const TeamAppCreateRoleVal = TeamRoleList['appCreate'].value;
|
||||
export const TeamDatasetCreateRoleVal = TeamRoleList['datasetCreate'].value;
|
||||
export const TeamApikeyCreateRoleVal = TeamRoleList['apikeyCreate'].value;
|
||||
export const TeamDefaultRoleVal = TeamReadRoleVal;
|
||||
|
||||
export const TeamReadPermissionVal = TeamPerList.read;
|
||||
export const TeamWritePermissionVal = TeamPerList.write;
|
||||
export const TeamManagePermissionVal = TeamPerList.manage;
|
||||
export const TeamAppCreatePermissionVal = TeamPerList.appCreate;
|
||||
export const TeamDatasetCreatePermissionVal = TeamPerList.datasetCreate;
|
||||
export const TeamApikeyCreatePermissionVal = TeamPerList.apikeyCreate;
|
||||
export const TeamDefaultPermissionVal = TeamReadPermissionVal;
|
||||
|
@@ -1,13 +1,18 @@
|
||||
import { type PerConstructPros, Permission } from '../controller';
|
||||
import {
|
||||
TeamApikeyCreatePermissionVal,
|
||||
TeamAppCreatePermissionVal,
|
||||
TeamDatasetCreatePermissionVal,
|
||||
TeamDefaultPermissionVal,
|
||||
TeamPermissionList
|
||||
TeamApikeyCreateRoleVal,
|
||||
TeamAppCreateRoleVal,
|
||||
TeamDatasetCreateRoleVal,
|
||||
TeamDefaultRoleVal,
|
||||
TeamPerList,
|
||||
TeamRoleList,
|
||||
TeamRolePerMap
|
||||
} from './constant';
|
||||
|
||||
export class TeamPermission extends Permission {
|
||||
hasAppCreateRole: boolean = false;
|
||||
hasDatasetCreateRole: boolean = false;
|
||||
hasApikeyCreateRole: boolean = false;
|
||||
hasAppCreatePer: boolean = false;
|
||||
hasDatasetCreatePer: boolean = false;
|
||||
hasApikeyCreatePer: boolean = false;
|
||||
@@ -15,18 +20,23 @@ export class TeamPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
if (!props) {
|
||||
props = {
|
||||
per: TeamDefaultPermissionVal
|
||||
role: TeamDefaultRoleVal
|
||||
};
|
||||
} else if (!props?.per) {
|
||||
props.per = TeamDefaultPermissionVal;
|
||||
} else if (!props?.role) {
|
||||
props.role = TeamDefaultRoleVal;
|
||||
}
|
||||
props.permissionList = TeamPermissionList;
|
||||
props.roleList = TeamRoleList;
|
||||
props.rolePerMap = TeamRolePerMap;
|
||||
props.perList = TeamPerList;
|
||||
super(props);
|
||||
|
||||
this.setUpdatePermissionCallback(() => {
|
||||
this.hasAppCreatePer = this.checkPer(TeamAppCreatePermissionVal);
|
||||
this.hasDatasetCreatePer = this.checkPer(TeamDatasetCreatePermissionVal);
|
||||
this.hasApikeyCreatePer = this.checkPer(TeamApikeyCreatePermissionVal);
|
||||
this.hasAppCreateRole = this.checkRole(TeamAppCreateRoleVal);
|
||||
this.hasDatasetCreateRole = this.checkRole(TeamDatasetCreateRoleVal);
|
||||
this.hasApikeyCreateRole = this.checkRole(TeamApikeyCreateRoleVal);
|
||||
this.hasAppCreatePer = this.checkPer(TeamAppCreateRoleVal);
|
||||
this.hasDatasetCreatePer = this.checkPer(TeamDatasetCreateRoleVal);
|
||||
this.hasApikeyCreatePer = this.checkPer(TeamApikeyCreateRoleVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { type PermissionValueType } from './type';
|
||||
import { NullPermission, PermissionTypeEnum } from './constant';
|
||||
import { NullRoleVal, PermissionTypeEnum } from './constant';
|
||||
import type { Permission } from './controller';
|
||||
|
||||
/* team public source, or owner source in team */
|
||||
@@ -30,7 +30,7 @@ export function mongoOwnerPermission({ teamId, tmbId }: { teamId: string; tmbId:
|
||||
}
|
||||
|
||||
// return permission-related schema to define the schema of resources
|
||||
export function getPermissionSchema(defaultPermission: PermissionValueType = NullPermission) {
|
||||
export function getPermissionSchema(defaultPermission: PermissionValueType = NullRoleVal) {
|
||||
return {
|
||||
defaultPermission: {
|
||||
type: Number,
|
||||
@@ -42,3 +42,11 @@ export function getPermissionSchema(defaultPermission: PermissionValueType = Nul
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const sumPer = (...per: PermissionValueType[]) => {
|
||||
if (per.length === 0) {
|
||||
// prevent sum 0 value, to fallback to default value
|
||||
return undefined;
|
||||
}
|
||||
return per.reduce((acc, cur) => acc | cur, 0);
|
||||
};
|
||||
|
@@ -16,17 +16,17 @@ export const filterDatasetsByTmbId = async ({
|
||||
// First get all permissions
|
||||
const permissions = await Promise.all(
|
||||
datasetIds.map(async (datasetId) => {
|
||||
const per = await getResourcePermission({
|
||||
const role = await getResourcePermission({
|
||||
teamId,
|
||||
tmbId,
|
||||
resourceId: datasetId,
|
||||
resourceType: PerResourceTypeEnum.dataset
|
||||
});
|
||||
|
||||
if (per === undefined) return false;
|
||||
if (role === undefined) return false;
|
||||
|
||||
const datasetPer = new DatasetPermission({
|
||||
per,
|
||||
role,
|
||||
isOwner: tmbPer.isOwner
|
||||
});
|
||||
|
||||
|
@@ -12,7 +12,6 @@ import { AppFolderTypeList } from '@fastgpt/global/core/app/constants';
|
||||
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
|
||||
import { type AuthModeType, type AuthResponseType } from '../type';
|
||||
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
|
||||
|
||||
export const authPluginByTmbId = async ({
|
||||
@@ -83,16 +82,16 @@ export const authAppByTmbId = async ({
|
||||
app.inheritPermission === false ||
|
||||
!app.parentId
|
||||
) {
|
||||
// 1. is a folder. (Folders have compeletely permission)
|
||||
// 1. is a folder. (Folders have completely permission)
|
||||
// 2. inheritPermission is false.
|
||||
// 3. is root folder/app.
|
||||
const rp = await getResourcePermission({
|
||||
const role = await getResourcePermission({
|
||||
teamId,
|
||||
tmbId,
|
||||
resourceId: appId,
|
||||
resourceType: PerResourceTypeEnum.app
|
||||
});
|
||||
const Per = new AppPermission({ per: rp ?? AppDefaultPermissionVal, isOwner });
|
||||
const Per = new AppPermission({ role, isOwner });
|
||||
return {
|
||||
Per
|
||||
};
|
||||
@@ -105,7 +104,7 @@ export const authAppByTmbId = async ({
|
||||
});
|
||||
|
||||
const Per = new AppPermission({
|
||||
per: parent.permission.value,
|
||||
role: parent.permission.role,
|
||||
isOwner
|
||||
});
|
||||
return {
|
||||
|
@@ -4,7 +4,7 @@ import { parseHeaderCert } from '../controller';
|
||||
import { getFileById } from '../../../common/file/gridfs/controller';
|
||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { OwnerPermissionVal, ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { OwnerPermissionVal, ReadRoleVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
|
||||
export const authCollectionFile = async ({
|
||||
@@ -32,7 +32,7 @@ export const authCollectionFile = async ({
|
||||
}
|
||||
|
||||
const permission = new Permission({
|
||||
per: ReadPermissionVal,
|
||||
role: ReadRoleVal,
|
||||
isOwner: file.metadata?.uid === tmbId || file.metadata?.tmbId === tmbId
|
||||
});
|
||||
|
||||
|
@@ -6,7 +6,6 @@ import { MongoOpenApi } from '../../openapi/schema';
|
||||
import { OpenApiErrEnum } from '@fastgpt/global/common/error/code/openapi';
|
||||
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { authAppByTmbId } from '../app/auth';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
|
||||
export async function authOpenApiKeyCrud({
|
||||
id,
|
||||
@@ -49,9 +48,7 @@ export async function authOpenApiKeyCrud({
|
||||
|
||||
return {
|
||||
openapi,
|
||||
permission: new Permission({
|
||||
per
|
||||
})
|
||||
permission: tmbPer
|
||||
};
|
||||
})();
|
||||
|
||||
|
@@ -21,6 +21,7 @@ import { type TeamMemberSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { type OrgSchemaType } from '@fastgpt/global/support/user/team/org/type';
|
||||
import { getOrgIdSetWithParentByTmbId } from './org/controllers';
|
||||
import { authUserSession } from '../user/session';
|
||||
import { sumPer } from '@fastgpt/global/support/permission/utils';
|
||||
|
||||
/** get resource permission for a team member
|
||||
* If there is no permission for the team member, it will return undefined
|
||||
@@ -102,7 +103,7 @@ export const getResourcePermission = async ({
|
||||
.then((perList) => perList.map((item) => item.permission))
|
||||
]);
|
||||
|
||||
return concatPer([...groupPers, ...orgPers]);
|
||||
return sumPer(...groupPers, ...orgPers);
|
||||
};
|
||||
|
||||
export async function getResourceClbsAndGroups({
|
||||
@@ -402,11 +403,3 @@ export const authFileToken = (token?: string) =>
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export const concatPer = (perList: PermissionValueType[] = []) => {
|
||||
if (perList.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new Permission().addPer(...perList).value;
|
||||
};
|
||||
|
@@ -7,7 +7,10 @@ import {
|
||||
} from '@fastgpt/global/core/dataset/type';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { MongoDataset } from '../../../core/dataset/schema';
|
||||
import { NullPermission, PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import {
|
||||
NullPermissionVal,
|
||||
PerResourceTypeEnum
|
||||
} from '@fastgpt/global/support/permission/constant';
|
||||
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||
import { DatasetPermission } from '@fastgpt/global/support/permission/dataset/controller';
|
||||
import { getCollectionWithDataset } from '../../../core/dataset/controller';
|
||||
@@ -15,7 +18,7 @@ import { MongoDatasetData } from '../../../core/dataset/data/schema';
|
||||
import { type AuthModeType, type AuthResponseType } from '../type';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DataSetDefaultRoleVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { getDatasetImagePreviewUrl } from '../../../core/dataset/image/utils';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
|
||||
@@ -71,7 +74,7 @@ export const authDatasetByTmbId = async ({
|
||||
dataset.inheritPermission === false ||
|
||||
!dataset.parentId
|
||||
) {
|
||||
// 1. is a folder. (Folders have compeletely permission)
|
||||
// 1. is a folder. (Folders have completely permission)
|
||||
// 2. inheritPermission is false.
|
||||
// 3. is root folder/dataset.
|
||||
const rp = await getResourcePermission({
|
||||
@@ -81,7 +84,7 @@ export const authDatasetByTmbId = async ({
|
||||
resourceType: PerResourceTypeEnum.dataset
|
||||
});
|
||||
const Per = new DatasetPermission({
|
||||
per: rp ?? DatasetDefaultPermissionVal,
|
||||
role: rp,
|
||||
isOwner
|
||||
});
|
||||
return {
|
||||
@@ -97,7 +100,7 @@ export const authDatasetByTmbId = async ({
|
||||
});
|
||||
|
||||
const Per = new DatasetPermission({
|
||||
per: parent.permission.value,
|
||||
role: parent.permission.role,
|
||||
isOwner
|
||||
});
|
||||
|
||||
@@ -158,7 +161,7 @@ export const authDataset = async ({
|
||||
// the temporary solution for authDatasetCollection is getting the
|
||||
export async function authDatasetCollection({
|
||||
collectionId,
|
||||
per = NullPermission,
|
||||
per = NullPermissionVal,
|
||||
isRoot = false,
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
@@ -242,7 +245,7 @@ export async function authDatasetCollection({
|
||||
// }
|
||||
// }
|
||||
|
||||
/*
|
||||
/*
|
||||
DatasetData permission is inherited from collection.
|
||||
*/
|
||||
export async function authDatasetData({
|
||||
|
@@ -3,7 +3,7 @@ import { parseHeaderCert } from '../controller';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { type AuthModeType, type AuthResponseType } from '../type';
|
||||
import { NullPermission } from '@fastgpt/global/support/permission/constant';
|
||||
import { NullPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||
import { authCert } from '../auth/common';
|
||||
import { MongoUser } from '../../user/schema';
|
||||
@@ -28,7 +28,7 @@ export async function authUserPer(props: AuthModeType): Promise<
|
||||
tmb
|
||||
};
|
||||
}
|
||||
if (!tmb.permission.checkPer(props.per ?? NullPermission)) {
|
||||
if (!tmb.permission.checkPer(props.per ?? NullPermissionVal)) {
|
||||
return Promise.reject(TeamErrEnum.unAuthTeam);
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ import { type UpdateTeamProps } from '@fastgpt/global/support/user/team/controll
|
||||
import { getResourcePermission } from '../../permission/controller';
|
||||
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||
import { TeamDefaultPermissionVal } from '@fastgpt/global/support/permission/user/constant';
|
||||
import { TeamDefaultRoleVal } from '@fastgpt/global/support/permission/user/constant';
|
||||
import { MongoMemberGroupModel } from '../../permission/memberGroup/memberGroupSchema';
|
||||
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
||||
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
|
||||
@@ -25,11 +25,12 @@ async function getTeamMember(match: Record<string, any>): Promise<TeamTmbItemTyp
|
||||
return Promise.reject('member not exist');
|
||||
}
|
||||
|
||||
const Per = await getResourcePermission({
|
||||
resourceType: PerResourceTypeEnum.team,
|
||||
teamId: tmb.teamId,
|
||||
tmbId: tmb._id
|
||||
});
|
||||
const role =
|
||||
(await getResourcePermission({
|
||||
resourceType: PerResourceTypeEnum.team,
|
||||
teamId: tmb.teamId,
|
||||
tmbId: tmb._id
|
||||
})) ?? TeamDefaultRoleVal;
|
||||
|
||||
return {
|
||||
userId: String(tmb.userId),
|
||||
@@ -44,7 +45,7 @@ async function getTeamMember(match: Record<string, any>): Promise<TeamTmbItemTyp
|
||||
role: tmb.role,
|
||||
status: tmb.status,
|
||||
permission: new TeamPermission({
|
||||
per: Per ?? TeamDefaultPermissionVal,
|
||||
role,
|
||||
isOwner: tmb.role === TeamMemberRoleEnum.owner
|
||||
}),
|
||||
notificationAccount: tmb.team.notificationAccount,
|
||||
|
@@ -143,6 +143,8 @@
|
||||
"permission.des.manage": "Based on write permissions, you can configure publishing channels, view conversation logs, and assign permissions to the application.",
|
||||
"permission.des.read": "Use the app to have conversations",
|
||||
"permission.des.write": "Can view and edit apps",
|
||||
"permission.des.readChatLog": "Can view chat logs",
|
||||
"permission.name.readChatLog": "View chat logs",
|
||||
"plugin.Instructions": "Instructions",
|
||||
"plugin_cost_by_token": "Charged based on token usage",
|
||||
"plugin_cost_per_times": "{{cost}} points/time",
|
||||
|
@@ -64,6 +64,7 @@
|
||||
"Parse": "Analysis",
|
||||
"Permission": "Permission",
|
||||
"Permission_tip": "Individual permissions are greater than group permissions",
|
||||
"permission_other": "Other permissions (multiple)",
|
||||
"Preview": "Preview",
|
||||
"Remove": "Remove",
|
||||
"Rename": "Rename",
|
||||
|
@@ -143,6 +143,8 @@
|
||||
"permission.des.manage": "写权限基础上,可配置发布渠道、查看对话日志、分配该应用权限",
|
||||
"permission.des.read": "可使用该应用进行对话",
|
||||
"permission.des.write": "可查看和编辑应用",
|
||||
"permission.des.readChatLog": "可查看对话日志",
|
||||
"permission.name.readChatLog": "查看对话日志",
|
||||
"plugin.Instructions": "使用说明",
|
||||
"plugin_cost_by_token": "依据 token 消耗计费",
|
||||
"plugin_cost_per_times": "{{cost}} 积分/次",
|
||||
|
@@ -64,6 +64,7 @@
|
||||
"Parse": "解析",
|
||||
"Permission": "权限",
|
||||
"Permission_tip": "个人权限大于群组权限",
|
||||
"permission_other": "其他权限(多选)",
|
||||
"Preview": "预览",
|
||||
"Remove": "移除",
|
||||
"Rename": "重命名",
|
||||
|
@@ -143,6 +143,8 @@
|
||||
"permission.des.manage": "在寫入權限基礎上,可以設定發布通道、檢視對話紀錄、分配這個應用程式的權限",
|
||||
"permission.des.read": "可以使用這個應用程式進行對話",
|
||||
"permission.des.write": "可以檢視和編輯應用程式",
|
||||
"permission.des.readChatLog": "可以檢視對話紀錄",
|
||||
"permission.name.readChatLog": "檢視對話紀錄",
|
||||
"plugin.Instructions": "使用說明",
|
||||
"plugin_cost_by_token": "根據 token 消耗計費",
|
||||
"plugin_cost_per_times": "{{cost}} 積分/次",
|
||||
|
@@ -64,6 +64,7 @@
|
||||
"Parse": "解析",
|
||||
"Permission": "權限",
|
||||
"Permission_tip": "個人權限大於群組權限",
|
||||
"permission_other": "其他權限(多選)",
|
||||
"Preview": "預覽",
|
||||
"Remove": "移除",
|
||||
"Rename": "重新命名",
|
||||
|
@@ -11,8 +11,8 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React from 'react';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import PermissionSelect from './PermissionSelect';
|
||||
import PermissionTags from './PermissionTags';
|
||||
import RoleSelect from './RoleSelect';
|
||||
import RoleTags from './RoleTags';
|
||||
import { CollaboratorContext } from './context';
|
||||
export type ManageModalProps = {
|
||||
onClose: () => void;
|
||||
@@ -70,17 +70,17 @@ function ManageModal({ onClose }: ManageModalProps) {
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td border="none">
|
||||
<PermissionTags permission={item.permission.value} />
|
||||
<RoleTags permission={item.permission.role} />
|
||||
</Td>
|
||||
<Td border="none">
|
||||
{/* Not self; Not owner and other manager */}
|
||||
{item.tmbId !== userInfo?.team?.tmbId &&
|
||||
(permission.isOwner || !item.permission.hasManagePer) && (
|
||||
<PermissionSelect
|
||||
<RoleSelect
|
||||
Button={
|
||||
<MyIcon name={'edit'} w={'16px'} _hover={{ color: 'primary.600' }} />
|
||||
}
|
||||
value={item.permission.value}
|
||||
value={item.permission.role}
|
||||
onChange={(permission) => {
|
||||
onUpdate({
|
||||
members: item.tmbId ? [item.tmbId] : undefined,
|
||||
|
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Box, Checkbox, HStack, VStack } from '@chakra-ui/react';
|
||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||
import PermissionTags from './PermissionTags';
|
||||
import { type PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
import RoleTags from './RoleTags';
|
||||
import type { RoleValueType } from '@fastgpt/global/support/permission/type';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import OrgTags from '../../user/team/OrgTags';
|
||||
import Tag from '@fastgpt/web/components/common/Tag';
|
||||
@@ -15,7 +15,7 @@ function MemberItemCard({
|
||||
isChecked,
|
||||
onDelete,
|
||||
name,
|
||||
permission,
|
||||
role: permission,
|
||||
orgs,
|
||||
addOnly,
|
||||
rightSlot
|
||||
@@ -26,7 +26,7 @@ function MemberItemCard({
|
||||
isChecked?: boolean;
|
||||
onDelete?: () => void;
|
||||
name: string;
|
||||
permission?: PermissionValueType;
|
||||
role?: RoleValueType;
|
||||
addOnly?: boolean;
|
||||
orgs?: string[];
|
||||
rightSlot?: React.ReactNode;
|
||||
@@ -61,7 +61,7 @@ function MemberItemCard({
|
||||
</Box>
|
||||
<Box lineHeight={1}>{orgs && orgs.length > 0 && <OrgTags orgs={orgs} />}</Box>
|
||||
</Box>
|
||||
{!isAdded && permission && <PermissionTags permission={permission} />}
|
||||
{!isAdded && permission && <RoleTags permission={permission} />}
|
||||
{isAdded && (
|
||||
<Tag
|
||||
mixBlendMode={'multiply'}
|
||||
|
@@ -27,7 +27,7 @@ import { useMemo, useRef, useState } from 'react';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { CollaboratorContext } from './context';
|
||||
import MemberItemCard from './MemberItemCard';
|
||||
import PermissionSelect from './PermissionSelect';
|
||||
import RoleSelect from './RoleSelect';
|
||||
|
||||
const HoverBoxStyle = {
|
||||
bgColor: 'myGray.50',
|
||||
@@ -98,15 +98,13 @@ function MemberModal({
|
||||
>([]);
|
||||
|
||||
const [selectedGroupList, setSelectedGroupList] = useState<MemberGroupListItemType<false>[]>([]);
|
||||
const permissionList = useContextSelector(CollaboratorContext, (v) => v.permissionList);
|
||||
const getPerLabelList = useContextSelector(CollaboratorContext, (v) => v.getPerLabelList);
|
||||
const [selectedPermission, setSelectedPermission] = useState<number | undefined>(
|
||||
permissionList?.read?.value
|
||||
);
|
||||
const perLabel = useMemo(() => {
|
||||
if (selectedPermission === undefined) return '';
|
||||
return getPerLabelList(selectedPermission!).join('、');
|
||||
}, [getPerLabelList, selectedPermission]);
|
||||
const roleList = useContextSelector(CollaboratorContext, (v) => v.roleList);
|
||||
const getRoleLabelList = useContextSelector(CollaboratorContext, (v) => v.getRoleLabelList);
|
||||
const [selectedRole, setSelectedRole] = useState<number | undefined>(roleList?.read?.value);
|
||||
const roleLabel = useMemo(() => {
|
||||
if (selectedRole === undefined) return '';
|
||||
return getRoleLabelList(selectedRole!).join('、');
|
||||
}, [getRoleLabelList, selectedRole]);
|
||||
|
||||
const onUpdateCollaborators = useContextSelector(
|
||||
CollaboratorContext,
|
||||
@@ -119,7 +117,7 @@ function MemberModal({
|
||||
members: selectedMemberList.map((item) => item.tmbId),
|
||||
groups: selectedGroupList.map((item) => item._id),
|
||||
orgs: selectedOrgList.map((item) => item._id),
|
||||
permission: addOnly ? undefined : selectedPermission!
|
||||
permission: addOnly ? undefined : selectedRole!
|
||||
} as UpdateClbPermissionProps<ValueOf<typeof addOnly>>),
|
||||
{
|
||||
successToast: t('common:add_success'),
|
||||
@@ -277,7 +275,7 @@ function MemberModal({
|
||||
avatar={member.avatar}
|
||||
key={member.tmbId}
|
||||
name={member.memberName}
|
||||
permission={collaborator?.permission.value}
|
||||
role={collaborator?.permission.role}
|
||||
onChange={onChange}
|
||||
isChecked={!!selectedMemberList.find((v) => v.tmbId === member.tmbId)}
|
||||
orgs={member.orgs}
|
||||
@@ -316,7 +314,7 @@ function MemberModal({
|
||||
name={org.name}
|
||||
onChange={onChange}
|
||||
addOnly={addOnly}
|
||||
permission={collaborator?.permission.value}
|
||||
role={collaborator?.permission.role}
|
||||
isChecked={!!selectedOrgList.find((v) => String(v._id) === String(org._id))}
|
||||
rightSlot={
|
||||
org.total && (
|
||||
@@ -365,8 +363,8 @@ function MemberModal({
|
||||
});
|
||||
}}
|
||||
isChecked={isChecked}
|
||||
permission={collaborator?.permission.value}
|
||||
addOnly={addOnly && !!member.permission.value}
|
||||
role={collaborator?.permission.role}
|
||||
addOnly={addOnly && !!member.permission.role}
|
||||
orgs={member.orgs}
|
||||
/>
|
||||
);
|
||||
@@ -392,7 +390,7 @@ function MemberModal({
|
||||
name={
|
||||
group.name === DefaultGroupName ? userInfo?.team.teamName ?? '' : group.name
|
||||
}
|
||||
permission={collaborator?.permission.value}
|
||||
role={collaborator?.permission.role}
|
||||
onChange={onChange}
|
||||
isChecked={!!selectedGroupList.find((v) => v._id === group._id)}
|
||||
addOnly={addOnly}
|
||||
@@ -425,9 +423,9 @@ function MemberModal({
|
||||
</Grid>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
{!addOnly && !!permissionList && (
|
||||
<PermissionSelect
|
||||
value={selectedPermission}
|
||||
{!addOnly && !!roleList && (
|
||||
<RoleSelect
|
||||
value={selectedRole}
|
||||
Button={
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
@@ -438,11 +436,11 @@ function MemberModal({
|
||||
borderRadius={'md'}
|
||||
h={'32px'}
|
||||
>
|
||||
{t(perLabel as any)}
|
||||
{roleLabel}
|
||||
<ChevronDownIcon fontSize={'md'} />
|
||||
</Flex>
|
||||
}
|
||||
onChange={(v) => setSelectedPermission(v)}
|
||||
onChange={(v) => setSelectedRole(v)}
|
||||
/>
|
||||
)}
|
||||
{addOnly && (
|
||||
|
@@ -7,11 +7,12 @@ import {
|
||||
Radio,
|
||||
useOutsideClick,
|
||||
HStack,
|
||||
MenuButton
|
||||
MenuButton,
|
||||
Checkbox
|
||||
} from '@chakra-ui/react';
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { type PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
import type { RoleValueType } from '@fastgpt/global/support/permission/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import { CollaboratorContext } from './context';
|
||||
@@ -19,8 +20,8 @@ import { useTranslation } from 'next-i18next';
|
||||
import MyDivider from '@fastgpt/web/components/common/MyDivider';
|
||||
|
||||
export type PermissionSelectProps = {
|
||||
value?: PermissionValueType;
|
||||
onChange: (value: PermissionValueType) => void;
|
||||
value?: RoleValueType;
|
||||
onChange: (value: RoleValueType) => void;
|
||||
trigger?: 'hover' | 'click';
|
||||
offset?: [number, number];
|
||||
Button: React.ReactNode;
|
||||
@@ -39,8 +40,8 @@ const MenuStyle = {
|
||||
fontSize: 'sm'
|
||||
};
|
||||
|
||||
function PermissionSelect({
|
||||
value,
|
||||
function RoleSelect({
|
||||
value: role,
|
||||
onChange,
|
||||
trigger = 'click',
|
||||
offset = [0, 5],
|
||||
@@ -49,15 +50,18 @@ function PermissionSelect({
|
||||
onDelete
|
||||
}: PermissionSelectProps) {
|
||||
const { t } = useTranslation();
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const closeTimer = useRef<NodeJS.Timeout>();
|
||||
|
||||
const { permission, permissionList } = useContextSelector(CollaboratorContext, (v) => v);
|
||||
const { permission, roleList: permissionList } = useContextSelector(
|
||||
CollaboratorContext,
|
||||
(v) => v
|
||||
);
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const permissionSelectList = useMemo(() => {
|
||||
if (!permissionList) return { singleCheckBoxList: [], multipleCheckBoxList: [] };
|
||||
const roleOptions = useMemo(() => {
|
||||
if (!permissionList) return { singleOptions: [], checkboxList: [] };
|
||||
|
||||
const list = Object.entries(permissionList).map(([_, value]) => {
|
||||
return {
|
||||
@@ -69,44 +73,42 @@ function PermissionSelect({
|
||||
});
|
||||
|
||||
return {
|
||||
singleCheckBoxList: list
|
||||
.filter((item) => item.checkBoxType === 'single')
|
||||
.filter((item) => {
|
||||
if (permission.isOwner) return true;
|
||||
if (item.value === permissionList['manage'].value) return false;
|
||||
return true;
|
||||
}),
|
||||
multipleCheckBoxList: list.filter((item) => item.checkBoxType === 'multiple')
|
||||
singleOptions: list.filter(
|
||||
(item) =>
|
||||
item.checkBoxType === 'single' &&
|
||||
(permission.isOwner || item.value !== permissionList['manage'].value)
|
||||
),
|
||||
checkboxList: list.filter((item) => item.checkBoxType === 'multiple')
|
||||
};
|
||||
}, [permission.isOwner, permissionList]);
|
||||
const selectedSingleValue = useMemo(() => {
|
||||
if (!permissionList) return undefined;
|
||||
|
||||
const per = new Permission({ per: value });
|
||||
const per = new Permission({ role });
|
||||
|
||||
if (per.hasManagePer) return permissionList['manage'].value;
|
||||
if (per.hasWritePer) return permissionList['write'].value;
|
||||
|
||||
return permissionList['read'].value;
|
||||
}, [permissionList, value]);
|
||||
// const selectedMultipleValues = useMemo(() => {
|
||||
// const per = new Permission({ per: value });
|
||||
//
|
||||
// return permissionSelectList.multipleCheckBoxList
|
||||
// .filter((item) => {
|
||||
// return per.checkPer(item.value);
|
||||
// })
|
||||
// .map((item) => item.value);
|
||||
// }, [permissionSelectList.multipleCheckBoxList, value]);
|
||||
}, [permissionList, role]);
|
||||
const selectedMultipleValues = useMemo(() => {
|
||||
const per = new Permission({ role });
|
||||
|
||||
const onSelectPer = (per: PermissionValueType) => {
|
||||
if (per === value) return;
|
||||
onChange(per);
|
||||
setIsOpen(false);
|
||||
return roleOptions.checkboxList
|
||||
.filter((item) => {
|
||||
return per.checkRole(item.value);
|
||||
})
|
||||
.map((item) => item.value);
|
||||
}, [role, roleOptions.checkboxList]);
|
||||
|
||||
const onSelectRole = (newRole: RoleValueType) => {
|
||||
if (newRole === role) return;
|
||||
onChange(newRole);
|
||||
// setIsOpen(false);
|
||||
};
|
||||
|
||||
useOutsideClick({
|
||||
ref: ref,
|
||||
ref,
|
||||
handler: () => {
|
||||
setIsOpen(false);
|
||||
}
|
||||
@@ -115,6 +117,7 @@ function PermissionSelect({
|
||||
return selectedSingleValue !== undefined ? (
|
||||
<Menu offset={offset} isOpen={isOpen} autoSelect={false} direction={'ltr'}>
|
||||
<Box
|
||||
ref={ref}
|
||||
w="fit-content"
|
||||
onMouseEnter={() => {
|
||||
if (trigger === 'hover') {
|
||||
@@ -131,7 +134,6 @@ function PermissionSelect({
|
||||
}}
|
||||
>
|
||||
<MenuButton
|
||||
ref={ref}
|
||||
position={'relative'}
|
||||
onClickCapture={() => {
|
||||
if (trigger === 'click') {
|
||||
@@ -153,12 +155,12 @@ function PermissionSelect({
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{/* The list of single select permissions */}
|
||||
{permissionSelectList.singleCheckBoxList.map((item) => {
|
||||
{roleOptions.singleOptions.map((item) => {
|
||||
const change = () => {
|
||||
const per = new Permission({ per: value });
|
||||
per.removePer(selectedSingleValue);
|
||||
per.addPer(item.value);
|
||||
onSelectPer(per.value);
|
||||
const per = new Permission({ role });
|
||||
per.removeRole(selectedSingleValue);
|
||||
per.addRole(item.value);
|
||||
onSelectRole(per.role);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -184,50 +186,45 @@ function PermissionSelect({
|
||||
);
|
||||
})}
|
||||
|
||||
{/* <MyDivider my={3} />
|
||||
<MyDivider />
|
||||
|
||||
{multipleValues.length > 0 && <Box m="4">其他权限(多选)</Box>} */}
|
||||
{roleOptions.checkboxList.length > 0 && (
|
||||
<Box pb="2" px="3" fontSize={'sm'} color={'myGray.900'}>
|
||||
{t('common:permission_other')}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* The list of multiple select permissions */}
|
||||
{/* {list
|
||||
.filter((item) => item.type === 'multiple')
|
||||
.map((item) => {
|
||||
const change = () => {
|
||||
if (checkPermission(valueState, item.value)) {
|
||||
setValueState(new Permission(valueState).remove(item.value).value);
|
||||
} else {
|
||||
setValueState(new Permission(valueState).add(item.value).value);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Flex
|
||||
key={item.value}
|
||||
{...(checkPermission(valueState, item.value)
|
||||
? {
|
||||
color: 'primary.500',
|
||||
bg: 'myWhite.300'
|
||||
}
|
||||
: {})}
|
||||
whiteSpace="pre-wrap"
|
||||
flexDirection="row"
|
||||
justifyContent="start"
|
||||
p="2"
|
||||
_hover={{
|
||||
bg: 'myGray.50'
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
size="lg"
|
||||
isChecked={checkPermission(valueState, item.value)}
|
||||
onChange={change}
|
||||
/>
|
||||
<Flex px="4" flexDirection="column" onClick={change}>
|
||||
<Box fontWeight="500">{item.name}</Box>
|
||||
<Box fontWeight="400">{item.description}</Box>
|
||||
</Flex>
|
||||
{roleOptions.checkboxList.map((item) => {
|
||||
const change = () => {
|
||||
const per = new Permission({ role });
|
||||
if (per.checkRole(item.value)) {
|
||||
per.removeRole(item.value);
|
||||
} else {
|
||||
per.addRole(item.value);
|
||||
}
|
||||
onSelectRole(per.role);
|
||||
};
|
||||
const isChecked = selectedMultipleValues.includes(item.value);
|
||||
return (
|
||||
<Flex
|
||||
key={item.value}
|
||||
{...(isChecked
|
||||
? {
|
||||
color: 'primary.600'
|
||||
}
|
||||
: {})}
|
||||
{...MenuStyle}
|
||||
>
|
||||
<Checkbox size="lg" isChecked={isChecked} onChange={change} />
|
||||
<Flex px="4" flexDirection="column" onClick={change}>
|
||||
<Box>{t(item.name as any)}</Box>
|
||||
<Box color={'myGray.500'} fontSize={'mini'}>
|
||||
{t(item.description as any)}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
})}*/}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
{onDelete && (
|
||||
<>
|
||||
<MyDivider my={2} h={'2px'} borderColor={'myGray.200'} />
|
||||
@@ -235,7 +232,7 @@ function PermissionSelect({
|
||||
{...MenuStyle}
|
||||
onClick={() => {
|
||||
onDelete();
|
||||
setIsOpen(false);
|
||||
// setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
<MyIcon name="delete" w="20px" color="red.600" />
|
||||
@@ -249,4 +246,4 @@ function PermissionSelect({
|
||||
) : null;
|
||||
}
|
||||
|
||||
export default React.memo(PermissionSelect);
|
||||
export default React.memo(RoleSelect);
|
@@ -10,17 +10,17 @@ export type PermissionTagsProp = {
|
||||
permission?: PermissionValueType;
|
||||
};
|
||||
|
||||
function PermissionTags({ permission }: PermissionTagsProp) {
|
||||
const { getPerLabelList } = useContextSelector(CollaboratorContext, (v) => v);
|
||||
function RoleTags({ permission }: PermissionTagsProp) {
|
||||
const { getRoleLabelList } = useContextSelector(CollaboratorContext, (v) => v);
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (permission === undefined) return null;
|
||||
|
||||
const perTagList = getPerLabelList(permission);
|
||||
const roleTagList = getRoleLabelList(permission);
|
||||
|
||||
return (
|
||||
<Flex gap="2" alignItems="center">
|
||||
{perTagList.map((item) => (
|
||||
{roleTagList.map((item) => (
|
||||
<Tag
|
||||
mixBlendMode={'multiply'}
|
||||
key={item}
|
||||
@@ -37,4 +37,4 @@ function PermissionTags({ permission }: PermissionTagsProp) {
|
||||
);
|
||||
}
|
||||
|
||||
export default PermissionTags;
|
||||
export default RoleTags;
|
@@ -3,11 +3,11 @@ import type {
|
||||
CollaboratorItemType,
|
||||
UpdateClbPermissionProps
|
||||
} from '@fastgpt/global/support/permission/collaborator';
|
||||
import { PermissionList } from '@fastgpt/global/support/permission/constant';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import type {
|
||||
PermissionListType,
|
||||
PermissionValueType
|
||||
PermissionValueType,
|
||||
RoleListType,
|
||||
RoleValueType
|
||||
} from '@fastgpt/global/support/permission/type';
|
||||
import { type ReactNode, useCallback } from 'react';
|
||||
import { createContext } from 'use-context-selector';
|
||||
@@ -19,6 +19,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import type { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { CommonRoleList } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
const MemberModal = dynamic(() => import('./MemberModal'));
|
||||
const ManageModal = dynamic(() => import('./ManageModal'));
|
||||
@@ -26,7 +27,7 @@ const ManageModal = dynamic(() => import('./ManageModal'));
|
||||
export type MemberManagerInputPropsType = {
|
||||
permission: Permission;
|
||||
onGetCollaboratorList: () => Promise<CollaboratorItemType[]>;
|
||||
permissionList?: PermissionListType;
|
||||
roleList?: RoleListType;
|
||||
onUpdateCollaborators: (props: UpdateClbPermissionProps) => Promise<any>;
|
||||
onDelOneCollaborator: (
|
||||
props: RequireOnlyOne<{ tmbId: string; groupId: string; orgId: string }>
|
||||
@@ -38,7 +39,7 @@ export type MemberManagerPropsType = MemberManagerInputPropsType & {
|
||||
collaboratorList: CollaboratorItemType[];
|
||||
refetchCollaboratorList: () => void;
|
||||
isFetchingCollaborator: boolean;
|
||||
getPerLabelList: (per: PermissionValueType) => string[];
|
||||
getRoleLabelList: (role: RoleValueType) => string[];
|
||||
};
|
||||
export type ChildrenProps = {
|
||||
onOpenAddMember: () => void;
|
||||
@@ -50,14 +51,14 @@ type CollaboratorContextType = MemberManagerPropsType & {};
|
||||
|
||||
export const CollaboratorContext = createContext<CollaboratorContextType>({
|
||||
collaboratorList: [],
|
||||
permissionList: PermissionList,
|
||||
roleList: CommonRoleList,
|
||||
onUpdateCollaborators: () => {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
onDelOneCollaborator: () => {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
getPerLabelList: (): string[] => {
|
||||
getRoleLabelList: (): string[] => {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
refetchCollaboratorList: (): void => {
|
||||
@@ -73,7 +74,7 @@ export const CollaboratorContext = createContext<CollaboratorContextType>({
|
||||
const CollaboratorContextProvider = ({
|
||||
permission,
|
||||
onGetCollaboratorList,
|
||||
permissionList,
|
||||
roleList,
|
||||
onUpdateCollaborators,
|
||||
onDelOneCollaborator,
|
||||
children,
|
||||
@@ -115,7 +116,7 @@ const CollaboratorContextProvider = ({
|
||||
return {
|
||||
...item,
|
||||
permission: new Permission({
|
||||
per: item.permission.value
|
||||
role: item.permission.role
|
||||
})
|
||||
};
|
||||
});
|
||||
@@ -128,32 +129,32 @@ const CollaboratorContextProvider = ({
|
||||
}
|
||||
);
|
||||
|
||||
const getPerLabelList = useCallback(
|
||||
(per: PermissionValueType) => {
|
||||
if (!permissionList) return [];
|
||||
const getRoleLabelList = useCallback(
|
||||
(role: PermissionValueType) => {
|
||||
if (!roleList) return [];
|
||||
|
||||
const Per = new Permission({ per });
|
||||
const Per = new Permission({ role });
|
||||
const labels: string[] = [];
|
||||
|
||||
if (Per.hasManagePer) {
|
||||
labels.push(permissionList['manage'].name);
|
||||
labels.push(t(roleList['manage'].name as any));
|
||||
} else if (Per.hasWritePer) {
|
||||
labels.push(permissionList['write'].name);
|
||||
labels.push(t(roleList['write'].name as any));
|
||||
} else if (Per.hasReadPer) {
|
||||
labels.push(permissionList['read'].name);
|
||||
labels.push(t(roleList['read'].name as any));
|
||||
}
|
||||
|
||||
Object.values(permissionList).forEach((item) => {
|
||||
Object.values(roleList).forEach((item) => {
|
||||
if (item.checkBoxType === 'multiple') {
|
||||
if (Per.checkPer(item.value)) {
|
||||
labels.push(item.name);
|
||||
if (Per.checkRole(item.value)) {
|
||||
labels.push(t(item.name as any));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return labels;
|
||||
},
|
||||
[permissionList]
|
||||
[roleList]
|
||||
);
|
||||
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
@@ -174,10 +175,10 @@ const CollaboratorContextProvider = ({
|
||||
collaboratorList,
|
||||
refetchCollaboratorList,
|
||||
isFetchingCollaborator,
|
||||
permissionList,
|
||||
roleList,
|
||||
onUpdateCollaborators: onUpdateCollaboratorsThen,
|
||||
onDelOneCollaborator: onDelOneCollaboratorThen,
|
||||
getPerLabelList
|
||||
getRoleLabelList
|
||||
};
|
||||
|
||||
const onOpenAddMemberModal = () => {
|
||||
|
@@ -1,34 +1,34 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import { type PermissionListType } from '@fastgpt/global/support/permission/type';
|
||||
import { PermissionList } from '@fastgpt/global/support/permission/constant';
|
||||
import type { RoleListType } from '@fastgpt/global/support/permission/type';
|
||||
import MyTag from '@fastgpt/web/components/common/Tag/index';
|
||||
import { HStack } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { CommonRoleList } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
const PermissionTag = ({
|
||||
permission,
|
||||
permissionList
|
||||
roleList: roleList
|
||||
}: {
|
||||
permission: Permission;
|
||||
permissionList: PermissionListType;
|
||||
roleList: RoleListType;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { commonLabel, otherLabels } = useMemo(() => {
|
||||
const Per = new Permission({ per: permission.value });
|
||||
const Per = new Permission({ role: permission.role });
|
||||
|
||||
const commonLabel = (() => {
|
||||
if (permission.isOwner) return t('common:permission.Owner');
|
||||
if (permission.hasManagePer) return t(PermissionList['manage'].name as any);
|
||||
if (permission.hasWritePer) return t(PermissionList['write'].name as any);
|
||||
if (permission.hasReadPer) return t(PermissionList['read'].name as any);
|
||||
if (permission.hasManagePer) return t(CommonRoleList['manage'].name as any);
|
||||
if (permission.hasWritePer) return t(CommonRoleList['write'].name as any);
|
||||
if (permission.hasReadPer) return t(CommonRoleList['read'].name as any);
|
||||
|
||||
return;
|
||||
})();
|
||||
|
||||
const otherLabels: string[] = [];
|
||||
Object.values(permissionList).forEach((item) => {
|
||||
Object.values(roleList).forEach((item) => {
|
||||
if (item.checkBoxType === 'multiple') {
|
||||
if (Per.checkPer(item.value)) {
|
||||
otherLabels.push(item.name);
|
||||
@@ -45,8 +45,8 @@ const PermissionTag = ({
|
||||
permission.hasReadPer,
|
||||
permission.hasWritePer,
|
||||
permission.isOwner,
|
||||
permission.value,
|
||||
permissionList,
|
||||
permission.role,
|
||||
roleList,
|
||||
t
|
||||
]);
|
||||
return (
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { AppPermission } from '@fastgpt/global/support/permission/app/controller';
|
||||
|
||||
export const processUpdateAppCollaboratorSpecific = (metadata: any) => {
|
||||
const permissionValue = parseInt(metadata.permission, 10);
|
||||
const permission = new AppPermission({ per: permissionValue });
|
||||
const role = parseInt(metadata.permission, 10);
|
||||
const permission = new AppPermission({ role });
|
||||
return {
|
||||
...metadata,
|
||||
readPermission: permission.hasReadPer ? '✔' : '✘',
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { DatasetPermission } from '@fastgpt/global/support/permission/dataset/controller';
|
||||
|
||||
export const processUpdateDatasetCollaboratorSpecific = (metadata: any) => {
|
||||
const permissionValue = parseInt(metadata.permission, 10);
|
||||
const permission = new DatasetPermission({ per: permissionValue });
|
||||
const role = parseInt(metadata.permission, 10);
|
||||
const permission = new DatasetPermission({ role });
|
||||
return {
|
||||
...metadata,
|
||||
readPermission: permission.hasReadPer ? '✔' : '✘',
|
||||
|
@@ -1,8 +1,10 @@
|
||||
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||
|
||||
// TODO: replace any
|
||||
export const processAssignPermissionSpecific = (metadata: any) => {
|
||||
const permissionValue = parseInt(metadata.permission, 10);
|
||||
const permission = new TeamPermission({ per: permissionValue });
|
||||
// metadata.permission is a string, parseInt will convert it to number in decimal
|
||||
const role = parseInt(metadata.permission, 10);
|
||||
const permission = new TeamPermission({ role });
|
||||
|
||||
return {
|
||||
...metadata,
|
||||
|
@@ -124,7 +124,7 @@ function GroupEditModal({
|
||||
const handleToggleSelect = (memberId: string) => {
|
||||
if (
|
||||
myRole === 'owner' &&
|
||||
memberId === groupMembers.find((item) => item.role === 'owner')?.tmbId
|
||||
memberId === groupMembers.find((item) => item.groupRole === 'owner')?.tmbId
|
||||
) {
|
||||
toast({
|
||||
title: t('user:team.group.toast.can_not_delete_owner'),
|
||||
|
@@ -28,11 +28,14 @@ import MemberTag from '../../../../components/support/user/team/Info/MemberTag';
|
||||
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
|
||||
import {
|
||||
TeamApikeyCreatePermissionVal,
|
||||
TeamApikeyCreateRoleVal,
|
||||
TeamAppCreatePermissionVal,
|
||||
TeamAppCreateRoleVal,
|
||||
TeamDatasetCreatePermissionVal,
|
||||
TeamDatasetCreateRoleVal,
|
||||
TeamManagePermissionVal,
|
||||
TeamPermissionList,
|
||||
TeamWritePermissionVal
|
||||
TeamManageRoleVal,
|
||||
TeamRoleList
|
||||
} from '@fastgpt/global/support/permission/user/constant';
|
||||
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||
import { useToggle } from 'ahooks';
|
||||
@@ -117,18 +120,18 @@ function PermissionManage({
|
||||
|
||||
if (!clb) return;
|
||||
|
||||
const permission = new TeamPermission({ per: clb.permission.value });
|
||||
const permission = new TeamPermission({ role: clb.permission.role });
|
||||
if (type === 'add') {
|
||||
permission.addPer(per);
|
||||
permission.addRole(per);
|
||||
} else {
|
||||
permission.removePer(per);
|
||||
permission.removeRole(per);
|
||||
}
|
||||
|
||||
return onUpdateCollaborators({
|
||||
...(clb.tmbId && { members: [clb.tmbId] }),
|
||||
...(clb.groupId && { groups: [clb.groupId] }),
|
||||
...(clb.orgId && { orgs: [clb.orgId] }),
|
||||
permission: permission.value
|
||||
permission: permission.role
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -145,12 +148,12 @@ function PermissionManage({
|
||||
|
||||
function PermissionCheckBox({
|
||||
isDisabled,
|
||||
per,
|
||||
role,
|
||||
clbPer,
|
||||
id
|
||||
}: {
|
||||
isDisabled: boolean;
|
||||
per: PermissionValueType;
|
||||
role: PermissionValueType;
|
||||
clbPer: Permission;
|
||||
id: string;
|
||||
}) {
|
||||
@@ -159,18 +162,18 @@ function PermissionManage({
|
||||
<Box mx="auto" w="fit-content">
|
||||
<Checkbox
|
||||
isDisabled={isDisabled}
|
||||
isChecked={clbPer.checkPer(per)}
|
||||
isChecked={clbPer.checkRole(role)}
|
||||
onChange={(e) =>
|
||||
e.target.checked
|
||||
? onUpdatePermission({
|
||||
id,
|
||||
type: 'add',
|
||||
per
|
||||
per: role
|
||||
})
|
||||
: onUpdatePermission({
|
||||
id,
|
||||
type: 'remove',
|
||||
per
|
||||
per: role
|
||||
})
|
||||
}
|
||||
/>
|
||||
@@ -266,25 +269,25 @@ function PermissionManage({
|
||||
</Td>
|
||||
<PermissionCheckBox
|
||||
isDisabled={member.permission.isOwner || !userManage}
|
||||
per={TeamAppCreatePermissionVal}
|
||||
role={TeamAppCreateRoleVal}
|
||||
clbPer={member.permission}
|
||||
id={member.tmbId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={member.permission.isOwner || !userManage}
|
||||
per={TeamDatasetCreatePermissionVal}
|
||||
role={TeamDatasetCreateRoleVal}
|
||||
clbPer={member.permission}
|
||||
id={member.tmbId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={member.permission.isOwner || !userManage}
|
||||
per={TeamApikeyCreatePermissionVal}
|
||||
role={TeamApikeyCreateRoleVal}
|
||||
clbPer={member.permission}
|
||||
id={member.tmbId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={member.permission.isOwner || !userInfo?.permission.isOwner}
|
||||
per={TeamManagePermissionVal}
|
||||
role={TeamManageRoleVal}
|
||||
clbPer={member.permission}
|
||||
id={member.tmbId!}
|
||||
/>
|
||||
@@ -323,25 +326,25 @@ function PermissionManage({
|
||||
</Td>
|
||||
<PermissionCheckBox
|
||||
isDisabled={org.permission.isOwner || !userManage}
|
||||
per={TeamAppCreatePermissionVal}
|
||||
role={TeamAppCreatePermissionVal}
|
||||
clbPer={org.permission}
|
||||
id={org.orgId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={org.permission.isOwner || !userManage}
|
||||
per={TeamDatasetCreatePermissionVal}
|
||||
role={TeamDatasetCreatePermissionVal}
|
||||
clbPer={org.permission}
|
||||
id={org.orgId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={org.permission.isOwner || !userManage}
|
||||
per={TeamApikeyCreatePermissionVal}
|
||||
role={TeamApikeyCreatePermissionVal}
|
||||
clbPer={org.permission}
|
||||
id={org.orgId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={org.permission.isOwner || !userInfo?.permission.isOwner}
|
||||
per={TeamManagePermissionVal}
|
||||
role={TeamManagePermissionVal}
|
||||
clbPer={org.permission}
|
||||
id={org.orgId!}
|
||||
/>
|
||||
@@ -385,25 +388,25 @@ function PermissionManage({
|
||||
</Td>
|
||||
<PermissionCheckBox
|
||||
isDisabled={group.permission.isOwner || !userManage}
|
||||
per={TeamAppCreatePermissionVal}
|
||||
role={TeamAppCreatePermissionVal}
|
||||
clbPer={group.permission}
|
||||
id={group.groupId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={group.permission.isOwner || !userManage}
|
||||
per={TeamDatasetCreatePermissionVal}
|
||||
role={TeamDatasetCreatePermissionVal}
|
||||
clbPer={group.permission}
|
||||
id={group.groupId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={group.permission.isOwner || !userManage}
|
||||
per={TeamApikeyCreatePermissionVal}
|
||||
role={TeamApikeyCreatePermissionVal}
|
||||
clbPer={group.permission}
|
||||
id={group.groupId!}
|
||||
/>
|
||||
<PermissionCheckBox
|
||||
isDisabled={group.permission.isOwner || !userInfo?.permission.isOwner}
|
||||
per={TeamManagePermissionVal}
|
||||
role={TeamManagePermissionVal}
|
||||
clbPer={group.permission}
|
||||
id={group.groupId!}
|
||||
/>
|
||||
@@ -434,7 +437,7 @@ export const Render = ({ Tabs }: { Tabs: React.ReactNode }) => {
|
||||
return userInfo?.team ? (
|
||||
<CollaboratorContextProvider
|
||||
permission={userInfo?.team.permission}
|
||||
permissionList={TeamPermissionList}
|
||||
roleList={TeamRoleList}
|
||||
onGetCollaboratorList={getTeamClbs}
|
||||
onUpdateCollaborators={updateMemberPermission}
|
||||
onDelOneCollaborator={deleteMemberPermission}
|
||||
|
@@ -20,7 +20,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import type { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
|
||||
import type { AppSchema } from '@fastgpt/global/core/app/type.d';
|
||||
import { AppPermissionList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { AppRoleList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import type { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
@@ -187,7 +187,7 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<CollaboratorContextProvider
|
||||
permission={appDetail.permission}
|
||||
onGetCollaboratorList={() => getCollaboratorList(appDetail._id)}
|
||||
permissionList={AppPermissionList}
|
||||
roleList={AppRoleList}
|
||||
onUpdateCollaborators={async (props) =>
|
||||
onUpdateCollaborators({
|
||||
permission: props.permission,
|
||||
|
@@ -36,7 +36,9 @@ const RouteTab = () => {
|
||||
label: t('app:publish_channel'),
|
||||
id: TabEnum.publish
|
||||
},
|
||||
{ label: t('app:chat_logs'), id: TabEnum.logs }
|
||||
...(appDetail.permission.hasReadChatLogPer
|
||||
? [{ label: t('app:chat_logs'), id: TabEnum.logs }]
|
||||
: [])
|
||||
]
|
||||
: [])
|
||||
],
|
||||
|
@@ -17,7 +17,7 @@ import { useFolderDrag } from '@/components/common/folder/useFolderDrag';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { EditResourceInfoFormType } from '@/components/common/Modal/EditResourceModal';
|
||||
import MyMenu, { type MenuItemType } from '@fastgpt/web/components/common/MyMenu';
|
||||
import { AppPermissionList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { AppRoleList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import {
|
||||
deleteAppCollaborators,
|
||||
getCollaboratorList,
|
||||
@@ -427,7 +427,7 @@ const ListItem = () => {
|
||||
managePer={{
|
||||
permission: editPerApp.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(editPerApp._id),
|
||||
permissionList: AppPermissionList,
|
||||
roleList: AppRoleList,
|
||||
onUpdateCollaborators: (props: {
|
||||
members?: string[];
|
||||
groups?: string[];
|
||||
|
@@ -17,7 +17,7 @@ import { DatasetTypeEnum, DatasetTypeMap } from '@fastgpt/global/core/dataset/co
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DatasetRoleList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import MemberManager from '../../MemberManager';
|
||||
import {
|
||||
getCollaboratorList,
|
||||
@@ -382,7 +382,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
managePer={{
|
||||
permission: datasetDetail.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(datasetId),
|
||||
permissionList: DatasetPermissionList,
|
||||
roleList: DatasetRoleList,
|
||||
onUpdateCollaborators: (body) =>
|
||||
postUpdateDatasetCollaborators({
|
||||
...body,
|
||||
|
@@ -17,7 +17,7 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { DatasetsContext } from '../../../pages/dataset/list/context';
|
||||
import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DatasetRoleList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import ConfigPerModal from '@/components/support/permission/ConfigPerModal';
|
||||
import {
|
||||
deleteDatasetCollaborators,
|
||||
@@ -436,7 +436,7 @@ function List() {
|
||||
managePer={{
|
||||
permission: editPerDataset.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(editPerDataset._id),
|
||||
permissionList: DatasetPermissionList,
|
||||
roleList: DatasetRoleList,
|
||||
onUpdateCollaborators: (props) =>
|
||||
postUpdateDatasetCollaborators({
|
||||
...props,
|
||||
|
39
projects/app/src/pages/api/admin/initv4112.ts
Normal file
39
projects/app/src/pages/api/admin/initv4112.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { AppReadChatLogRoleVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { AppPermission } from '@fastgpt/global/support/permission/app/controller';
|
||||
import type { AnyBulkWriteOperation } from '@fastgpt/service/common/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
|
||||
import { type NextApiRequest, type NextApiResponse } from 'next';
|
||||
async function handler(req: NextApiRequest, _res: NextApiResponse) {
|
||||
await authCert({ req, authRoot: true });
|
||||
|
||||
// 初始化 app 权限:所有有 write 的都加上 readChatLog role
|
||||
const rps = await MongoResourcePermission.find({
|
||||
resourceType: 'app'
|
||||
}).lean();
|
||||
|
||||
const ops: AnyBulkWriteOperation<typeof MongoResourcePermission>[] = [];
|
||||
|
||||
for (const rp of rps) {
|
||||
const per = new AppPermission({ role: rp.permission });
|
||||
if (per.hasWritePer) {
|
||||
per.addRole(AppReadChatLogRoleVal);
|
||||
ops.push({
|
||||
updateOne: {
|
||||
filter: { _id: rp._id },
|
||||
update: { $set: { permission: per.role } }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result = await MongoResourcePermission.bulkWrite(ops);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DataSetDefaultRoleVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
|
||||
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
defaultPermission: DatasetDefaultPermissionVal
|
||||
defaultPermission: DataSetDefaultRoleVal
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -22,15 +22,15 @@ async function handler(req: NextApiRequest, _res: NextApiResponse) {
|
||||
});
|
||||
|
||||
for await (const rp of rps) {
|
||||
const per = new TeamPermission({ per: rp.permission });
|
||||
console.log(per.hasWritePer, per.value);
|
||||
if (per.hasWritePer) {
|
||||
const newPer = per.addPer(
|
||||
TeamAppCreatePermissionVal,
|
||||
TeamDatasetCreatePermissionVal,
|
||||
TeamApikeyCreatePermissionVal
|
||||
);
|
||||
rp.permission = newPer.value;
|
||||
const per = rp.permission;
|
||||
console.log(per);
|
||||
if (per & 0b010) {
|
||||
// has 0b010
|
||||
rp.permission =
|
||||
per |
|
||||
TeamAppCreatePermissionVal |
|
||||
TeamDatasetCreatePermissionVal |
|
||||
TeamApikeyCreatePermissionVal;
|
||||
|
||||
try {
|
||||
await retryFn(async () => {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import type { NextApiResponse } from 'next';
|
||||
import { responseWriteController } from '@fastgpt/service/common/response';
|
||||
import { addDays } from 'date-fns';
|
||||
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
|
||||
import { addLog } from '@fastgpt/service/common/system/log';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -19,6 +18,7 @@ import type { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { type AIChatItemValueItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { sanitizeCsvField } from '@fastgpt/service/common/file/csv';
|
||||
import { AppReadChatLogPerVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
|
||||
const formatJsonString = (data: any) => {
|
||||
if (data == null) return '';
|
||||
@@ -47,7 +47,7 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
const { teamId } = await authApp({ req, authToken: true, appId, per: WritePermissionVal });
|
||||
const { teamId } = await authApp({ req, authToken: true, appId, per: AppReadChatLogPerVal });
|
||||
|
||||
const teamMemberWithContact = await MongoTeamMember.aggregate([
|
||||
{ $match: { teamId: new Types.ObjectId(teamId) } },
|
||||
|
@@ -7,7 +7,6 @@ import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { ChatItemCollectionName } from '@fastgpt/service/core/chat/chatItemSchema';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
|
||||
import { parsePaginationRequest } from '@fastgpt/service/common/api/pagination';
|
||||
import { type PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
@@ -16,6 +15,7 @@ import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
|
||||
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
|
||||
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
import { AppReadChatLogPerVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
@@ -41,7 +41,7 @@ async function handler(
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
per: WritePermissionVal
|
||||
per: AppReadChatLogPerVal
|
||||
});
|
||||
|
||||
const where = {
|
||||
|
@@ -11,15 +11,15 @@ import { type ApiRequestProps } from '@fastgpt/service/type/next';
|
||||
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
|
||||
import { AppFolderTypeList, AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { AppDefaultRoleVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
import { concatPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { getGroupsByTmbId } from '@fastgpt/service/support/permission/memberGroup/controllers';
|
||||
import { getOrgIdSetWithParentByTmbId } from '@fastgpt/service/support/permission/org/controllers';
|
||||
import { addSourceMember } from '@fastgpt/service/support/user/utils';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { sumPer } from '@fastgpt/global/support/permission/utils';
|
||||
|
||||
export type ListAppBody = {
|
||||
parentId?: ParentIdType;
|
||||
@@ -63,7 +63,7 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
]);
|
||||
|
||||
// Get team all app permissions
|
||||
const [perList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
const [roleList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
MongoResourcePermission.find({
|
||||
resourceType: PerResourceTypeEnum.app,
|
||||
teamId,
|
||||
@@ -87,7 +87,7 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
})
|
||||
]);
|
||||
// Get my permissions
|
||||
const myPerList = perList.filter(
|
||||
const myPerList = roleList.filter(
|
||||
(item) =>
|
||||
String(item.tmbId) === String(tmbId) ||
|
||||
myGroupMap.has(String(item.groupId)) ||
|
||||
@@ -160,11 +160,11 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
.map((app) => {
|
||||
const { Per, privateApp } = (() => {
|
||||
const getPer = (appId: string) => {
|
||||
const tmbPer = myPerList.find(
|
||||
const tmbRole = myPerList.find(
|
||||
(item) => String(item.resourceId) === appId && !!item.tmbId
|
||||
)?.permission;
|
||||
const groupPer = concatPer(
|
||||
myPerList
|
||||
const groupRole = sumPer(
|
||||
...myPerList
|
||||
.filter(
|
||||
(item) => String(item.resourceId) === appId && (!!item.groupId || !!item.orgId)
|
||||
)
|
||||
@@ -172,13 +172,13 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
);
|
||||
|
||||
return new AppPermission({
|
||||
per: tmbPer ?? groupPer ?? AppDefaultPermissionVal,
|
||||
role: tmbRole ?? groupRole,
|
||||
isOwner: String(app.tmbId) === String(tmbId) || teamPer.isOwner
|
||||
});
|
||||
};
|
||||
|
||||
const getClbCount = (appId: string) => {
|
||||
return perList.filter((item) => String(item.resourceId) === String(appId)).length;
|
||||
return roleList.filter((item) => String(item.resourceId) === String(appId)).length;
|
||||
};
|
||||
|
||||
// Inherit app, check parent folder clb
|
||||
|
@@ -8,17 +8,17 @@ import {
|
||||
ReadPermissionVal
|
||||
} from '@fastgpt/global/support/permission/constant';
|
||||
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
|
||||
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DataSetDefaultRoleVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
|
||||
import { type ApiRequestProps } from '@fastgpt/service/type/next';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
import { getGroupsByTmbId } from '@fastgpt/service/support/permission/memberGroup/controllers';
|
||||
import { concatPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { getOrgIdSetWithParentByTmbId } from '@fastgpt/service/support/permission/org/controllers';
|
||||
import { addSourceMember } from '@fastgpt/service/support/user/utils';
|
||||
import { getEmbeddingModel } from '@fastgpt/service/core/ai/model';
|
||||
import { sumPer } from '@fastgpt/global/support/permission/utils';
|
||||
|
||||
export type GetDatasetListBody = {
|
||||
parentId: ParentIdType;
|
||||
@@ -51,7 +51,7 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
]);
|
||||
|
||||
// Get team all app permissions
|
||||
const [perList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
const [roleList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
MongoResourcePermission.find({
|
||||
resourceType: PerResourceTypeEnum.dataset,
|
||||
teamId,
|
||||
@@ -74,7 +74,7 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
tmbId
|
||||
})
|
||||
]);
|
||||
const myPerList = perList.filter(
|
||||
const myRoles = roleList.filter(
|
||||
(item) =>
|
||||
String(item.tmbId) === String(tmbId) ||
|
||||
myGroupMap.has(String(item.groupId)) ||
|
||||
@@ -83,7 +83,7 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
|
||||
const findDatasetQuery = (() => {
|
||||
// Filter apps by permission, if not owner, only get apps that I have permission to access
|
||||
const idList = { _id: { $in: myPerList.map((item) => item.resourceId) } };
|
||||
const idList = { _id: { $in: myRoles.map((item) => item.resourceId) } };
|
||||
const datasetPerQuery = teamPer.isOwner
|
||||
? {}
|
||||
: parentId
|
||||
@@ -127,23 +127,23 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
.map((dataset) => {
|
||||
const { Per, privateDataset } = (() => {
|
||||
const getPer = (datasetId: string) => {
|
||||
const tmbPer = myPerList.find(
|
||||
const tmbRole = myRoles.find(
|
||||
(item) => String(item.resourceId) === datasetId && !!item.tmbId
|
||||
)?.permission;
|
||||
const groupPer = concatPer(
|
||||
myPerList
|
||||
const groupRole = sumPer(
|
||||
...myRoles
|
||||
.filter(
|
||||
(item) => String(item.resourceId) === datasetId && (!!item.groupId || !!item.orgId)
|
||||
)
|
||||
.map((item) => item.permission)
|
||||
);
|
||||
return new DatasetPermission({
|
||||
per: tmbPer ?? groupPer ?? DatasetDefaultPermissionVal,
|
||||
role: tmbRole ?? groupRole,
|
||||
isOwner: String(dataset.tmbId) === String(tmbId) || teamPer.isOwner
|
||||
});
|
||||
};
|
||||
const getClbCount = (datasetId: string) => {
|
||||
return perList.filter((item) => String(item.resourceId) === String(datasetId)).length;
|
||||
return roleList.filter((item) => String(item.resourceId) === String(datasetId)).length;
|
||||
};
|
||||
|
||||
// inherit
|
||||
|
@@ -17,7 +17,7 @@ import FolderPath from '@/components/common/folder/Path';
|
||||
import { useRouter } from 'next/router';
|
||||
import FolderSlideCard from '@/components/common/folder/SlideCard';
|
||||
import { delAppById, resumeInheritPer } from '@/web/core/app/api';
|
||||
import { AppPermissionList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { AppRoleList } from '@fastgpt/global/support/permission/app/constant';
|
||||
import {
|
||||
deleteAppCollaborators,
|
||||
getCollaboratorList,
|
||||
@@ -282,7 +282,7 @@ const MyApps = ({ MenuIcon }: { MenuIcon: JSX.Element }) => {
|
||||
managePer={{
|
||||
permission: folderDetail.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(folderDetail._id),
|
||||
permissionList: AppPermissionList,
|
||||
roleList: AppRoleList,
|
||||
onUpdateCollaborators: (props) =>
|
||||
postUpdateAppCollaborators({
|
||||
...props,
|
||||
|
@@ -18,7 +18,7 @@ import { type EditFolderFormType } from '@fastgpt/web/components/common/MyModal/
|
||||
import dynamic from 'next/dynamic';
|
||||
import { postCreateDatasetFolder, resumeInheritPer } from '@/web/core/dataset/api';
|
||||
import FolderSlideCard from '@/components/common/folder/SlideCard';
|
||||
import { DatasetPermissionList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import { DatasetRoleList } from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import {
|
||||
postUpdateDatasetCollaborators,
|
||||
deleteDatasetCollaborators,
|
||||
@@ -256,7 +256,7 @@ const Dataset = () => {
|
||||
managePer={{
|
||||
permission: folderDetail.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(folderDetail._id),
|
||||
permissionList: DatasetPermissionList,
|
||||
roleList: DatasetRoleList,
|
||||
onUpdateCollaborators: (params) =>
|
||||
postUpdateDatasetCollaborators({
|
||||
...params,
|
||||
|
28
test/cases/global/support/permission/common.test.ts
Normal file
28
test/cases/global/support/permission/common.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { CommonPerList, CommonRoleList } from '@fastgpt/global/support/permission/constant';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import { sumPer } from '@fastgpt/global/support/permission/utils';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
describe('Permission Helper Class Test', () => {
|
||||
it('Permission Helper Class Test', () => {
|
||||
const permission = new Permission();
|
||||
expect(permission.role).toBe(0);
|
||||
|
||||
permission.addRole(CommonRoleList.manage.value);
|
||||
expect(permission.role).toBe(CommonRoleList.manage.value);
|
||||
expect(permission.checkPer(CommonPerList.manage)).toBe(true);
|
||||
|
||||
permission.removeRole(CommonRoleList.read.value);
|
||||
expect(permission.checkPer(CommonPerList.manage)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tool Functions', () => {
|
||||
it('sumPer', () => {
|
||||
expect(sumPer(0b001, 0b010)).toBe(0b011);
|
||||
expect(sumPer(0b000, 0b000)).toBe(0b000);
|
||||
expect(sumPer(0b100, 0b001)).toBe(0b101);
|
||||
expect(sumPer(0b111, 0b010)).toBe(0b111);
|
||||
expect(sumPer(sumPer(0b001, 0b010), 0b100)).toBe(0b111);
|
||||
expect(sumPer(0b10000000, 0b01000000)).toBe(0b11000000);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user