mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
Permission (#1687)
Co-authored-by: Archer <545436317@qq.com> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
TeamCollectionName,
|
||||
TeamMemberCollectionName
|
||||
} from '@fastgpt/global/support/user/team/constant';
|
||||
import { AppDefaultPermission } from '@fastgpt/global/support/permission/app/constant';
|
||||
|
||||
export const AppCollectionName = 'apps';
|
||||
|
||||
@@ -98,6 +99,12 @@ const AppSchema = new Schema({
|
||||
|
||||
inited: {
|
||||
type: Boolean
|
||||
},
|
||||
|
||||
// the default permission of a app
|
||||
defaultPermission: {
|
||||
type: Number,
|
||||
default: AppDefaultPermission
|
||||
}
|
||||
});
|
||||
|
||||
|
85
packages/service/support/permission/app/auth.ts
Normal file
85
packages/service/support/permission/app/auth.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Auth app permission */
|
||||
import { MongoApp } from '../../../core/app/schema';
|
||||
import { AppDetailType } from '@fastgpt/global/core/app/type.d';
|
||||
import { AuthPropsType } from '../type/auth.d';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { getResourcePermission } from '../controller';
|
||||
import { AppPermission } from '@fastgpt/global/support/permission/app/controller';
|
||||
import { AuthResponseType } from '../type/auth.d';
|
||||
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
|
||||
export const authAppByTmbId = async ({
|
||||
teamId,
|
||||
tmbId,
|
||||
appId,
|
||||
per
|
||||
}: {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
appId: string;
|
||||
per: PermissionValueType;
|
||||
}) => {
|
||||
const { permission: tmbPer } = await getTmbInfoByTmbId({ tmbId });
|
||||
|
||||
const app = await (async () => {
|
||||
// get app and per
|
||||
const [app, rp] = await Promise.all([
|
||||
MongoApp.findOne({ _id: appId, teamId }).lean(),
|
||||
getResourcePermission({
|
||||
teamId,
|
||||
tmbId,
|
||||
resourceId: appId,
|
||||
resourceType: PerResourceTypeEnum.app
|
||||
}) // this could be null
|
||||
]);
|
||||
|
||||
if (!app) {
|
||||
return Promise.reject(AppErrEnum.unExist);
|
||||
}
|
||||
|
||||
const isOwner = tmbPer.isOwner || String(app.tmbId) === tmbId;
|
||||
const Per = new AppPermission({ per: rp?.permission ?? app.defaultPermission, isOwner });
|
||||
|
||||
if (!Per.checkPer(per)) {
|
||||
return Promise.reject(AppErrEnum.unAuthApp);
|
||||
}
|
||||
|
||||
return {
|
||||
...app,
|
||||
permission: Per
|
||||
};
|
||||
})();
|
||||
|
||||
return { app };
|
||||
};
|
||||
|
||||
export const authApp = async ({
|
||||
appId,
|
||||
per,
|
||||
...props
|
||||
}: AuthPropsType & {
|
||||
appId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
app: AppDetailType;
|
||||
}
|
||||
> => {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { teamId, tmbId } = result;
|
||||
|
||||
const { app } = await authAppByTmbId({
|
||||
teamId,
|
||||
tmbId,
|
||||
appId,
|
||||
per
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
permission: app.permission,
|
||||
app
|
||||
};
|
||||
};
|
@@ -1,72 +0,0 @@
|
||||
import { MongoApp } from '../../../core/app/schema';
|
||||
import { AppDetailType } from '@fastgpt/global/core/app/type.d';
|
||||
import { AuthModeType } from '../type';
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
|
||||
// 模型使用权校验
|
||||
export async function authApp({
|
||||
appId,
|
||||
per = 'owner',
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
appId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
teamOwner: boolean;
|
||||
app: AppDetailType;
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { teamId, tmbId } = result;
|
||||
const { role } = await getTmbInfoByTmbId({ tmbId });
|
||||
|
||||
const { app, isOwner, canWrite } = await (async () => {
|
||||
// get app
|
||||
const app = await MongoApp.findOne({ _id: appId, teamId }).lean();
|
||||
if (!app) {
|
||||
return Promise.reject(AppErrEnum.unExist);
|
||||
}
|
||||
|
||||
const isOwner = String(app.tmbId) === tmbId || role === TeamMemberRoleEnum.owner;
|
||||
const canWrite =
|
||||
isOwner ||
|
||||
(app.permission === PermissionTypeEnum.public && role !== TeamMemberRoleEnum.visitor);
|
||||
|
||||
if (per === 'r') {
|
||||
if (!isOwner && app.permission !== PermissionTypeEnum.public) {
|
||||
return Promise.reject(AppErrEnum.unAuthApp);
|
||||
}
|
||||
}
|
||||
if (per === 'w' && !canWrite) {
|
||||
return Promise.reject(AppErrEnum.unAuthApp);
|
||||
}
|
||||
if (per === 'owner' && !isOwner) {
|
||||
return Promise.reject(AppErrEnum.unAuthApp);
|
||||
}
|
||||
|
||||
return {
|
||||
app: {
|
||||
...app,
|
||||
isOwner,
|
||||
canWrite
|
||||
},
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
...result,
|
||||
app,
|
||||
role,
|
||||
isOwner,
|
||||
canWrite,
|
||||
teamOwner: role === TeamMemberRoleEnum.owner
|
||||
};
|
||||
}
|
@@ -1,96 +0,0 @@
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { AuthModeType } from '../type';
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { AppDetailType } from '@fastgpt/global/core/app/type';
|
||||
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { MongoOutLink } from '../../outLink/schema';
|
||||
import { MongoApp } from '../../../core/app/schema';
|
||||
import { OutLinkErrEnum } from '@fastgpt/global/common/error/code/outLink';
|
||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
|
||||
/* crud outlink permission */
|
||||
export async function authOutLinkCrud({
|
||||
outLinkId,
|
||||
per = 'owner',
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
outLinkId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
app: AppDetailType;
|
||||
outLink: OutLinkSchema;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { tmbId, teamId } = result;
|
||||
|
||||
const { role } = await getTmbInfoByTmbId({ tmbId });
|
||||
|
||||
const { app, outLink, isOwner, canWrite } = await (async () => {
|
||||
const outLink = await MongoOutLink.findOne({ _id: outLinkId, teamId });
|
||||
|
||||
if (!outLink) {
|
||||
throw new Error(OutLinkErrEnum.unExist);
|
||||
}
|
||||
|
||||
const app = await MongoApp.findById(outLink.appId);
|
||||
|
||||
if (!app) {
|
||||
return Promise.reject(AppErrEnum.unExist);
|
||||
}
|
||||
|
||||
const isOwner = String(outLink.tmbId) === tmbId || role === TeamMemberRoleEnum.owner;
|
||||
const canWrite =
|
||||
isOwner ||
|
||||
(app.permission === PermissionTypeEnum.public && role !== TeamMemberRoleEnum.visitor);
|
||||
|
||||
if (per === 'r' && !isOwner && app.permission !== PermissionTypeEnum.public) {
|
||||
return Promise.reject(OutLinkErrEnum.unAuthLink);
|
||||
}
|
||||
if (per === 'w' && !canWrite) {
|
||||
return Promise.reject(OutLinkErrEnum.unAuthLink);
|
||||
}
|
||||
if (per === 'owner' && !isOwner) {
|
||||
return Promise.reject(OutLinkErrEnum.unAuthLink);
|
||||
}
|
||||
|
||||
return {
|
||||
app: {
|
||||
...app,
|
||||
isOwner: String(app.tmbId) === tmbId,
|
||||
canWrite
|
||||
},
|
||||
outLink,
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
...result,
|
||||
app,
|
||||
outLink,
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
}
|
||||
|
||||
/* outLink exist and it app exist */
|
||||
export async function authOutLinkValid({ shareId }: { shareId?: string }) {
|
||||
if (!shareId) {
|
||||
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
|
||||
}
|
||||
const shareChat = await MongoOutLink.findOne({ shareId });
|
||||
|
||||
if (!shareChat) {
|
||||
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
|
||||
}
|
||||
|
||||
return {
|
||||
appId: shareChat.appId,
|
||||
shareChat
|
||||
};
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { AuthModeType } from '../type';
|
||||
import { TeamItemType } from '@fastgpt/global/support/user/team/type';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { UserErrEnum } from '../../../../global/common/error/code/user';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
|
||||
export async function authUserNotVisitor(props: AuthModeType): Promise<
|
||||
AuthResponseType & {
|
||||
team: TeamItemType;
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
}
|
||||
> {
|
||||
const { teamId, tmbId } = await parseHeaderCert(props);
|
||||
const team = await getTmbInfoByTmbId({ tmbId });
|
||||
|
||||
if (team.role === TeamMemberRoleEnum.visitor) {
|
||||
return Promise.reject(UserErrEnum.binVisitor);
|
||||
}
|
||||
|
||||
return {
|
||||
teamId,
|
||||
tmbId,
|
||||
team,
|
||||
role: team.role,
|
||||
isOwner: team.role === TeamMemberRoleEnum.owner, // teamOwner
|
||||
canWrite: true
|
||||
};
|
||||
}
|
||||
|
||||
/* auth user role */
|
||||
export async function authUserRole(props: AuthModeType): Promise<
|
||||
AuthResponseType & {
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
teamOwner: boolean;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { role: userRole, canWrite } = await getTmbInfoByTmbId({ tmbId: result.tmbId });
|
||||
|
||||
return {
|
||||
...result,
|
||||
isOwner: true,
|
||||
role: userRole,
|
||||
teamOwner: userRole === TeamMemberRoleEnum.owner,
|
||||
canWrite
|
||||
};
|
||||
}
|
||||
|
||||
/* auth teamMember in team role */
|
||||
export async function authTeamOwner(props: AuthModeType): Promise<
|
||||
AuthResponseType & {
|
||||
role: `${TeamMemberRoleEnum}`;
|
||||
teamOwner: boolean;
|
||||
}
|
||||
> {
|
||||
const authRes = await authUserRole(props);
|
||||
|
||||
if (authRes.role !== TeamMemberRoleEnum.owner) {
|
||||
return Promise.reject(TeamErrEnum.unAuthTeam);
|
||||
}
|
||||
|
||||
return authRes;
|
||||
}
|
@@ -3,10 +3,76 @@ import { ERROR_ENUM } from '@fastgpt/global/common/error/errorCode';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { NextApiResponse } from 'next';
|
||||
import type { AuthModeType, ReqHeaderAuthType } from './type.d';
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { AuthUserTypeEnum, PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { authOpenApiKey } from '../openapi/auth';
|
||||
import { FileTokenQuery } from '@fastgpt/global/common/file/type';
|
||||
import { MongoResourcePermission } from './schema';
|
||||
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
import { mongoSessionRun } from '../../common/mongo/sessionRun';
|
||||
|
||||
export const getResourcePermission = async ({
|
||||
resourceType,
|
||||
teamId,
|
||||
tmbId,
|
||||
resourceId
|
||||
}: {
|
||||
resourceType: PerResourceTypeEnum;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
resourceId?: string;
|
||||
}) => {
|
||||
const per = await MongoResourcePermission.findOne({
|
||||
tmbId,
|
||||
teamId,
|
||||
resourceType,
|
||||
resourceId
|
||||
});
|
||||
|
||||
if (!per) {
|
||||
return null;
|
||||
}
|
||||
return per;
|
||||
};
|
||||
export const delResourcePermissionById = (id: string) => {
|
||||
return MongoResourcePermission.findByIdAndRemove(id);
|
||||
};
|
||||
export const updateResourcePermission = async ({
|
||||
resourceId,
|
||||
resourceType,
|
||||
teamId,
|
||||
tmbIdList,
|
||||
permission
|
||||
}: {
|
||||
resourceId?: string;
|
||||
resourceType: PerResourceTypeEnum;
|
||||
teamId: string;
|
||||
tmbIdList: string[];
|
||||
permission: PermissionValueType;
|
||||
}) => {
|
||||
await mongoSessionRun((session) => {
|
||||
return Promise.all(
|
||||
tmbIdList.map((tmbId) =>
|
||||
MongoResourcePermission.findOneAndUpdate(
|
||||
{
|
||||
resourceType,
|
||||
teamId,
|
||||
tmbId,
|
||||
resourceId
|
||||
},
|
||||
{
|
||||
permission
|
||||
},
|
||||
{
|
||||
session,
|
||||
upsert: true
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/* 下面代码等迁移 */
|
||||
/* create token */
|
||||
export function createJWT(user: { _id?: string; team?: { teamId?: string; tmbId: string } }) {
|
||||
const key = process.env.TOKEN_KEY as string;
|
||||
|
69
packages/service/support/permission/publish/authLink.ts
Normal file
69
packages/service/support/permission/publish/authLink.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { AppDetailType } from '@fastgpt/global/core/app/type';
|
||||
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { MongoOutLink } from '../../outLink/schema';
|
||||
import { OutLinkErrEnum } from '@fastgpt/global/common/error/code/outLink';
|
||||
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { AuthPropsType } from '../type/auth';
|
||||
import { AuthResponseType } from '../type/auth';
|
||||
import { authAppByTmbId } from '../app/auth';
|
||||
|
||||
/* crud outlink permission */
|
||||
export async function authOutLinkCrud({
|
||||
outLinkId,
|
||||
per,
|
||||
...props
|
||||
}: AuthPropsType & {
|
||||
outLinkId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
app: AppDetailType;
|
||||
outLink: OutLinkSchema;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { tmbId, teamId } = result;
|
||||
|
||||
const { app, outLink } = await (async () => {
|
||||
const outLink = await MongoOutLink.findOne({ _id: outLinkId, teamId });
|
||||
if (!outLink) {
|
||||
throw new Error(OutLinkErrEnum.unExist);
|
||||
}
|
||||
|
||||
const { app } = await authAppByTmbId({
|
||||
teamId,
|
||||
tmbId,
|
||||
appId: outLink.appId,
|
||||
per: ManagePermissionVal
|
||||
});
|
||||
|
||||
return {
|
||||
outLink,
|
||||
app
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
...result,
|
||||
permission: app.permission,
|
||||
app,
|
||||
outLink
|
||||
};
|
||||
}
|
||||
|
||||
/* outLink exist and it app exist */
|
||||
export async function authOutLinkValid({ shareId }: { shareId?: string }) {
|
||||
if (!shareId) {
|
||||
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
|
||||
}
|
||||
const shareChat = await MongoOutLink.findOne({ shareId });
|
||||
|
||||
if (!shareChat) {
|
||||
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
|
||||
}
|
||||
|
||||
return {
|
||||
appId: shareChat.appId,
|
||||
shareChat
|
||||
};
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
import { ResourcePermissionType } from '@fastgpt/global/support/permission/type';
|
||||
import { MongoResourcePermission } from './schema';
|
||||
import { ResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
export async function getResourcePermission({
|
||||
tmbId,
|
||||
resourceType
|
||||
}: {
|
||||
tmbId: string;
|
||||
resourceType: ResourceTypeEnum;
|
||||
}) {
|
||||
return (await MongoResourcePermission.findOne({
|
||||
tmbId,
|
||||
resourceType
|
||||
})) as ResourcePermissionType;
|
||||
}
|
@@ -1,127 +0,0 @@
|
||||
// PermissionValueType, the type of permission's value is a number, which is a bit field actually.
|
||||
// It is spired by the permission system in Linux.
|
||||
// The lowest 3 bits present the permission of reading, writing and managing.
|
||||
// The higher bits are advanced permissions or extended permissions, which could be customized.
|
||||
export type PermissionValueType = number;
|
||||
export type PermissionListType = { [key: string]: PermissionValueType };
|
||||
export const NullPermission: PermissionValueType = 0;
|
||||
|
||||
// the Permission helper class
|
||||
export class Permission {
|
||||
value: PermissionValueType;
|
||||
constructor(value: PermissionValueType) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// add permission(s)
|
||||
// it can be chaining called.
|
||||
// @example
|
||||
// const perm = new Permission(permission)
|
||||
// perm.add(PermissionList['read'])
|
||||
// perm.add(PermissionList['read'], PermissionList['write'])
|
||||
// perm.add(PermissionList['read']).add(PermissionList['write'])
|
||||
add(...perm: PermissionValueType[]): Permission {
|
||||
for (let p of perm) {
|
||||
this.value = addPermission(this.value, p);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
remove(...perm: PermissionValueType[]): Permission {
|
||||
for (let p of perm) {
|
||||
this.value = removePermission(this.value, p);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
check(perm: PermissionValueType): Permission | boolean {
|
||||
if (checkPermission(this.value, perm)) {
|
||||
return this;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function constructPermission(permList: PermissionValueType[]) {
|
||||
return new Permission(NullPermission).add(...permList);
|
||||
}
|
||||
|
||||
// The base Permissions List
|
||||
// It can be extended, for example:
|
||||
// export const UserPermissionList: PermissionListType = {
|
||||
// ...PermissionList,
|
||||
// 'Invite': 0b1000
|
||||
// }
|
||||
export const PermissionList: PermissionListType = {
|
||||
Read: 0b100,
|
||||
Write: 0b010,
|
||||
Manage: 0b001
|
||||
};
|
||||
|
||||
// list of permissions. could be customized.
|
||||
// ! removal of the basic permissions is not recommended.
|
||||
// const PermList: Array<PermissionType> = [ReadPerm, WritePerm, ManagePerm];
|
||||
|
||||
// return the list of permissions
|
||||
// @param Perm(optional): the list of permissions to be added
|
||||
// export function getPermList(Perm?: PermissionType[]): Array<PermissionType> {
|
||||
// if (Perm === undefined) {
|
||||
// return PermList;
|
||||
// } else {
|
||||
// return PermList.concat(Perm);
|
||||
// }
|
||||
// }
|
||||
|
||||
// check the permission
|
||||
// @param [val]: The permission value to be checked
|
||||
// @parma [perm]: Which Permission value will be checked
|
||||
// @returns [booean]: if the [val] has the [perm]
|
||||
// example:
|
||||
// const perm = user.permission // get this permisiion from db or somewhere else
|
||||
// const ok = checkPermission(perm, PermissionList['Read'])
|
||||
export function checkPermission(val: PermissionValueType, perm: PermissionValueType): boolean {
|
||||
return (val & perm) === perm;
|
||||
}
|
||||
|
||||
// add the permission
|
||||
// it can be chaining called.
|
||||
// return the new permission value based on [val] added with [perm]
|
||||
// @param val: PermissionValueType
|
||||
// @param perm: PermissionValueType
|
||||
// example:
|
||||
// const basePerm = 0b001; // Manage only
|
||||
export function addPermission(
|
||||
val: PermissionValueType,
|
||||
perm: PermissionValueType
|
||||
): PermissionValueType {
|
||||
return val | perm;
|
||||
}
|
||||
|
||||
// remove the permission
|
||||
export function removePermission(
|
||||
val: PermissionValueType,
|
||||
perm: PermissionValueType
|
||||
): PermissionValueType {
|
||||
return val & ~perm;
|
||||
}
|
||||
|
||||
// export function parsePermission(val: PermissionValueType, list: PermissionValueType[]) {
|
||||
// const result: [[string, boolean]] = [] as any;
|
||||
// list.forEach((perm) => {
|
||||
// result.push([perm[0], checkPermission(val, perm)]);
|
||||
// });
|
||||
// return result;
|
||||
// }
|
||||
|
||||
export function hasManage(val: PermissionValueType) {
|
||||
return checkPermission(val, PermissionList['Manage']);
|
||||
}
|
||||
|
||||
export function hasWrite(val: PermissionValueType) {
|
||||
return checkPermission(val, PermissionList['Write']);
|
||||
}
|
||||
|
||||
export function hasRead(val: PermissionValueType) {
|
||||
return checkPermission(val, PermissionList['Read']);
|
||||
}
|
@@ -2,11 +2,13 @@ import {
|
||||
TeamCollectionName,
|
||||
TeamMemberCollectionName
|
||||
} from '@fastgpt/global/support/user/team/constant';
|
||||
import { Model, connectionMongo } from '../../../common/mongo';
|
||||
import { Model, connectionMongo } from '../../common/mongo';
|
||||
import type { ResourcePermissionType } from '@fastgpt/global/support/permission/type';
|
||||
import { ResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
const { Schema, model, models } = connectionMongo;
|
||||
|
||||
export const ResourcePermissionCollectionName = 'resource_permission';
|
||||
|
||||
export const ResourcePermissionSchema = new Schema({
|
||||
teamId: {
|
||||
type: Schema.Types.ObjectId,
|
||||
@@ -17,30 +19,36 @@ export const ResourcePermissionSchema = new Schema({
|
||||
ref: TeamMemberCollectionName
|
||||
},
|
||||
resourceType: {
|
||||
type: Object.values(ResourceTypeEnum),
|
||||
type: Object.values(PerResourceTypeEnum),
|
||||
required: true
|
||||
},
|
||||
permission: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
// Resrouce ID: App or DataSet or any other resource type.
|
||||
// It is null if the resourceType is team.
|
||||
resourceId: {
|
||||
type: Schema.Types.ObjectId
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
ResourcePermissionSchema.index({
|
||||
teamId: 1,
|
||||
resourceType: 1
|
||||
});
|
||||
ResourcePermissionSchema.index({
|
||||
tmbId: 1,
|
||||
resourceType: 1
|
||||
});
|
||||
ResourcePermissionSchema.index(
|
||||
{
|
||||
resourceType: 1,
|
||||
teamId: 1,
|
||||
tmbId: 1,
|
||||
resourceId: 1
|
||||
},
|
||||
{
|
||||
unique: true
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
export const ResourcePermissionCollectionName = 'resource_permission';
|
||||
|
||||
export const MongoResourcePermission: Model<ResourcePermissionType> =
|
||||
models[ResourcePermissionCollectionName] ||
|
||||
model(ResourcePermissionCollectionName, ResourcePermissionSchema);
|
@@ -1,4 +1,3 @@
|
||||
import { getVectorCountByTeamId } from '../../common/vectorStore/controller';
|
||||
import { getTeamPlanStatus, getTeamStandPlan } from '../../support/wallet/sub/utils';
|
||||
import { MongoApp } from '../../core/app/schema';
|
||||
import { MongoPlugin } from '../../core/plugin/schema';
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { ApiRequestProps } from '../../type/next';
|
||||
import type { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
|
||||
export type ReqHeaderAuthType = {
|
||||
cookie?: string;
|
||||
@@ -8,10 +9,11 @@ export type ReqHeaderAuthType = {
|
||||
userid?: string;
|
||||
authorization?: string;
|
||||
};
|
||||
|
||||
export type AuthModeType = {
|
||||
req: ApiRequestProps;
|
||||
authToken?: boolean;
|
||||
authRoot?: boolean;
|
||||
authApiKey?: boolean;
|
||||
per?: 'r' | 'w' | 'owner';
|
||||
per?: PermissionValueType | 'r' | 'w' | 'owner'; // this is for compatibility
|
||||
};
|
||||
|
21
packages/service/support/permission/type/auth.d.ts
vendored
Normal file
21
packages/service/support/permission/type/auth.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { Permission } from '@fastgpt/global/support/permission/controller';
|
||||
import { ApiRequestProps } from '../../../type/next';
|
||||
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||
|
||||
export type AuthPropsType = {
|
||||
req: ApiRequestProps;
|
||||
authToken?: boolean;
|
||||
authRoot?: boolean;
|
||||
authApiKey?: boolean;
|
||||
per: PermissionValueType;
|
||||
};
|
||||
|
||||
export type AuthResponseType = {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
authType?: `${AuthUserTypeEnum}`;
|
||||
appId?: string;
|
||||
apikey?: string;
|
||||
permission: Permission;
|
||||
};
|
26
packages/service/support/permission/user/auth.ts
Normal file
26
packages/service/support/permission/user/auth.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { AuthResponseType } from '../type/auth.d';
|
||||
import { AuthPropsType } from '../type/auth.d';
|
||||
import { TeamTmbItemType } from '@fastgpt/global/support/user/team/type';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
|
||||
/* auth user role */
|
||||
export async function authUserPer(props: AuthPropsType): Promise<
|
||||
AuthResponseType & {
|
||||
tmb: TeamTmbItemType;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const tmb = await getTmbInfoByTmbId({ tmbId: result.tmbId });
|
||||
|
||||
if (!tmb.permission.checkPer(props.per)) {
|
||||
return Promise.reject(TeamErrEnum.unAuthTeam);
|
||||
}
|
||||
|
||||
return {
|
||||
...result,
|
||||
permission: tmb.permission,
|
||||
tmb
|
||||
};
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import { TeamItemType, TeamMemberWithTeamSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { TeamTmbItemType, TeamMemberWithTeamSchema } from '@fastgpt/global/support/user/team/type';
|
||||
import { ClientSession, Types } from '../../../common/mongo';
|
||||
import {
|
||||
TeamMemberRoleEnum,
|
||||
@@ -8,13 +8,25 @@ import {
|
||||
import { MongoTeamMember } from './teamMemberSchema';
|
||||
import { MongoTeam } from './teamSchema';
|
||||
import { UpdateTeamProps } from '@fastgpt/global/support/user/team/controller';
|
||||
import { getResourcePermission } from '../../permission/controller';
|
||||
import {
|
||||
PerResourceTypeEnum,
|
||||
ReadPermissionVal
|
||||
} from '@fastgpt/global/support/permission/constant';
|
||||
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||
|
||||
async function getTeamMember(match: Record<string, any>): Promise<TeamItemType> {
|
||||
async function getTeamMember(match: Record<string, any>): Promise<TeamTmbItemType> {
|
||||
const tmb = (await MongoTeamMember.findOne(match).populate('teamId')) as TeamMemberWithTeamSchema;
|
||||
if (!tmb) {
|
||||
return Promise.reject('member not exist');
|
||||
}
|
||||
|
||||
const tmbPer = await getResourcePermission({
|
||||
resourceType: PerResourceTypeEnum.team,
|
||||
teamId: tmb.teamId._id,
|
||||
tmbId: tmb._id
|
||||
});
|
||||
|
||||
return {
|
||||
userId: String(tmb.userId),
|
||||
teamId: String(tmb.teamId._id),
|
||||
@@ -27,9 +39,11 @@ async function getTeamMember(match: Record<string, any>): Promise<TeamItemType>
|
||||
role: tmb.role,
|
||||
status: tmb.status,
|
||||
defaultTeam: tmb.defaultTeam,
|
||||
canWrite: tmb.role !== TeamMemberRoleEnum.visitor,
|
||||
lafAccount: tmb.teamId.lafAccount,
|
||||
defaultPermission: tmb.teamId.defaultPermission
|
||||
permission: new TeamPermission({
|
||||
per: tmbPer?.permission ?? tmb.teamId.defaultPermission,
|
||||
isOwner: tmb.role === TeamMemberRoleEnum.owner
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ const { Schema, model, models } = connectionMongo;
|
||||
import { TeamSchema as TeamType } from '@fastgpt/global/support/user/team/type.d';
|
||||
import { userCollectionName } from '../../user/schema';
|
||||
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
|
||||
import { NullPermission } from '../../permission/resourcePermission/permisson';
|
||||
import { TeamDefaultPermissionVal } from '@fastgpt/global/support/permission/user/constant';
|
||||
|
||||
const TeamSchema = new Schema({
|
||||
name: {
|
||||
@@ -16,7 +16,7 @@ const TeamSchema = new Schema({
|
||||
},
|
||||
defaultPermission: {
|
||||
type: Number,
|
||||
default: NullPermission
|
||||
default: TeamDefaultPermissionVal
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
|
Reference in New Issue
Block a user