Commit e008b219 by Archer Committed by GitHub

feat: deleted user (#5289)

* add desc to coupon

* deleted user
parent 0fa08389
...@@ -11,6 +11,8 @@ weight: 782 ...@@ -11,6 +11,8 @@ weight: 782
## 🚀 新增内容 ## 🚀 新增内容
1. 账号注销
## ⚙️ 优化 ## ⚙️ 优化
1. 兑换码功能支持指定对公支付模式。 1. 兑换码功能支持指定对公支付模式。
......
...@@ -17,4 +17,5 @@ export type TeamCouponSchema = { ...@@ -17,4 +17,5 @@ export type TeamCouponSchema = {
redeemedTeamId?: string; redeemedTeamId?: string;
type: CouponTypeEnum; type: CouponTypeEnum;
price?: number; price?: number;
description?: string;
}; };
...@@ -5,6 +5,20 @@ import { MongoApp } from './schema'; ...@@ -5,6 +5,20 @@ import { MongoApp } from './schema';
import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import { encryptSecretValue, storeSecretValue } from '../../common/secret/utils'; import { encryptSecretValue, storeSecretValue } from '../../common/secret/utils';
import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants'; import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants';
import { type ClientSession } from '../../common/mongo';
import { MongoEvaluation } from './evaluation/evalSchema';
import { removeEvaluationJob } from './evaluation/mq';
import { deleteChatFiles } from '../chat/controller';
import { MongoChatItem } from '../chat/chatItemSchema';
import { MongoChat } from '../chat/chatSchema';
import { MongoOutLink } from '../../support/outLink/schema';
import { MongoOpenApi } from '../../support/openapi/schema';
import { MongoAppVersion } from './version/schema';
import { MongoChatInputGuide } from '../chat/inputGuide/schema';
import { MongoResourcePermission } from '../../support/permission/schema';
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
import { removeImageByPath } from '../../common/file/image/controller';
import { mongoSessionRun } from '../../common/mongo/sessionRun';
export const beforeUpdateAppFormat = ({ nodes }: { nodes?: StoreNodeItemType[] }) => { export const beforeUpdateAppFormat = ({ nodes }: { nodes?: StoreNodeItemType[] }) => {
if (!nodes) return; if (!nodes) return;
...@@ -110,3 +124,88 @@ export const getAppBasicInfoByIds = async ({ teamId, ids }: { teamId: string; id ...@@ -110,3 +124,88 @@ export const getAppBasicInfoByIds = async ({ teamId, ids }: { teamId: string; id
avatar: item.avatar avatar: item.avatar
})); }));
}; };
export const onDelOneApp = async ({
teamId,
appId,
session
}: {
teamId: string;
appId: string;
session?: ClientSession;
}) => {
const apps = await findAppAndAllChildren({
teamId,
appId,
fields: '_id avatar'
});
// Remove eval job
const evalJobs = await MongoEvaluation.find(
{
appId: { $in: apps.map((app) => app._id) }
},
'_id'
).lean();
await Promise.all(evalJobs.map((evalJob) => removeEvaluationJob(evalJob._id)));
const del = async (session: ClientSession) => {
for await (const app of apps) {
const appId = app._id;
// Chats
await deleteChatFiles({ appId });
await MongoChatItem.deleteMany(
{
appId
},
{ session }
);
await MongoChat.deleteMany(
{
appId
},
{ session }
);
// 删除分享链接
await MongoOutLink.deleteMany({
appId
}).session(session);
// Openapi
await MongoOpenApi.deleteMany({
appId
}).session(session);
// delete version
await MongoAppVersion.deleteMany({
appId
}).session(session);
await MongoChatInputGuide.deleteMany({
appId
}).session(session);
await MongoResourcePermission.deleteMany({
resourceType: PerResourceTypeEnum.app,
teamId,
resourceId: appId
}).session(session);
// delete app
await MongoApp.deleteOne(
{
_id: appId
},
{ session }
);
await removeImageByPath(app.avatar, session);
}
};
if (session) {
return del(session);
}
return mongoSessionRun(del);
};
...@@ -10,6 +10,10 @@ import { MongoDatasetDataText } from './data/dataTextSchema'; ...@@ -10,6 +10,10 @@ import { MongoDatasetDataText } from './data/dataTextSchema';
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset'; import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
import { retryFn } from '@fastgpt/global/common/system/utils'; import { retryFn } from '@fastgpt/global/common/system/utils';
import { clearDatasetImages } from './image/utils'; import { clearDatasetImages } from './image/utils';
import { MongoDatasetCollectionTags } from './tag/schema';
import { removeDatasetSyncJobScheduler } from './datasetSync';
import { mongoSessionRun } from '../../common/mongo/sessionRun';
import { removeImageByPath } from '../../common/file/image/controller';
/* ============= dataset ========== */ /* ============= dataset ========== */
/* find all datasetId by top datasetId */ /* find all datasetId by top datasetId */
...@@ -118,3 +122,44 @@ export async function delDatasetRelevantData({ ...@@ -118,3 +122,44 @@ export async function delDatasetRelevantData({
datasetId: { $in: datasetIds } datasetId: { $in: datasetIds }
}).session(session); }).session(session);
} }
export const deleteDatasets = async ({
teamId,
datasets
}: {
teamId: string;
datasets: DatasetSchemaType[];
}) => {
const datasetIds = datasets.map((d) => d._id);
// delete collection.tags
await MongoDatasetCollectionTags.deleteMany({
teamId,
datasetId: { $in: datasetIds }
});
// Remove cron job
await Promise.all(
datasets.map((dataset) => {
return removeDatasetSyncJobScheduler(dataset._id);
})
);
// delete all dataset.data and pg data
await mongoSessionRun(async (session) => {
// delete dataset data
await delDatasetRelevantData({ datasets, session });
// delete dataset
await MongoDataset.deleteMany(
{
_id: { $in: datasetIds }
},
{ session }
);
for await (const dataset of datasets) {
await removeImageByPath(dataset.avatar, session);
}
});
};
...@@ -14,7 +14,8 @@ export const ResourcePermissionCollectionName = 'resource_permissions'; ...@@ -14,7 +14,8 @@ export const ResourcePermissionCollectionName = 'resource_permissions';
export const ResourcePermissionSchema = new Schema({ export const ResourcePermissionSchema = new Schema({
teamId: { teamId: {
type: Schema.Types.ObjectId, type: Schema.Types.ObjectId,
ref: TeamCollectionName ref: TeamCollectionName,
required: true
}, },
tmbId: { tmbId: {
type: Schema.Types.ObjectId, type: Schema.Types.ObjectId,
......
...@@ -86,7 +86,7 @@ const getSession = async (key: string): Promise<SessionType> => { ...@@ -86,7 +86,7 @@ const getSession = async (key: string): Promise<SessionType> => {
export const delUserAllSession = async (userId: string, whiteList?: (string | undefined)[]) => { export const delUserAllSession = async (userId: string, whiteList?: (string | undefined)[]) => {
const formatWhiteList = whiteList?.map((item) => item && getSessionKey(item)); const formatWhiteList = whiteList?.map((item) => item && getSessionKey(item));
const redis = getGlobalRedisConnection(); const redis = getGlobalRedisConnection();
const keys = (await getAllKeysByPrefix(`${redisPrefix}${userId}`)).filter( const keys = (await getAllKeysByPrefix(`${redisPrefix}${String(userId)}`)).filter(
(item) => !formatWhiteList?.includes(item) (item) => !formatWhiteList?.includes(item)
); );
......
...@@ -17,6 +17,7 @@ const CouponSchema = new Schema({ ...@@ -17,6 +17,7 @@ const CouponSchema = new Schema({
enum: Object.values(CouponTypeEnum) enum: Object.values(CouponTypeEnum)
}, },
price: Number, price: Number,
description: String,
subscriptions: { subscriptions: {
type: [Object], type: [Object],
required: true required: true
......
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authApp } from '@fastgpt/service/support/permission/app/auth'; import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { MongoChatInputGuide } from '@fastgpt/service/core/chat/inputGuide/schema'; import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
import { import { onDelOneApp } from '@fastgpt/service/core/app/controller';
OwnerPermissionVal,
PerResourceTypeEnum
} from '@fastgpt/global/support/permission/constant';
import { findAppAndAllChildren } from '@fastgpt/service/core/app/controller';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { type ClientSession } from '@fastgpt/service/common/mongo';
import { deleteChatFiles } from '@fastgpt/service/core/chat/controller';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils'; import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { MongoOpenApi } from '@fastgpt/service/support/openapi/schema';
import { removeImageByPath } from '@fastgpt/service/common/file/image/controller';
import { addAuditLog } from '@fastgpt/service/support/user/audit/util'; import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants'; import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util'; import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
import { removeEvaluationJob } from '@fastgpt/service/core/app/evaluation/mq';
import { MongoEvaluation } from '@fastgpt/service/core/app/evaluation/evalSchema';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) { async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string }; const { appId } = req.query as { appId: string };
if (!appId) { if (!appId) {
throw new Error('参数错误'); return Promise.reject('参数错误');
} }
// Auth owner (folder owner, can delete all apps in the folder) // Auth owner (folder owner, can delete all apps in the folder)
...@@ -44,6 +27,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) { ...@@ -44,6 +27,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
teamId, teamId,
appId appId
}); });
(async () => { (async () => {
addAuditLog({ addAuditLog({
tmbId, tmbId,
...@@ -61,88 +45,3 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) { ...@@ -61,88 +45,3 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
} }
export default NextAPI(handler); export default NextAPI(handler);
export const onDelOneApp = async ({
teamId,
appId,
session
}: {
teamId: string;
appId: string;
session?: ClientSession;
}) => {
const apps = await findAppAndAllChildren({
teamId,
appId,
fields: '_id avatar'
});
// Remove eval job
const evalJobs = await MongoEvaluation.find(
{
appId: { $in: apps.map((app) => app._id) }
},
'_id'
).lean();
await Promise.all(evalJobs.map((evalJob) => removeEvaluationJob(evalJob._id)));
const del = async (session: ClientSession) => {
for await (const app of apps) {
const appId = app._id;
// Chats
await deleteChatFiles({ appId });
await MongoChatItem.deleteMany(
{
appId
},
{ session }
);
await MongoChat.deleteMany(
{
appId
},
{ session }
);
// 删除分享链接
await MongoOutLink.deleteMany({
appId
}).session(session);
// Openapi
await MongoOpenApi.deleteMany({
appId
}).session(session);
// delete version
await MongoAppVersion.deleteMany({
appId
}).session(session);
await MongoChatInputGuide.deleteMany({
appId
}).session(session);
await MongoResourcePermission.deleteMany({
resourceType: PerResourceTypeEnum.app,
teamId,
resourceId: appId
}).session(session);
// delete app
await MongoApp.deleteOne(
{
_id: appId
},
{ session }
);
await removeImageByPath(app.avatar, session);
}
};
if (session) {
return del(session);
}
return mongoSessionRun(del);
};
...@@ -10,7 +10,7 @@ import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant ...@@ -10,7 +10,7 @@ import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant
import { MongoApp } from '@fastgpt/service/core/app/schema'; import { MongoApp } from '@fastgpt/service/core/app/schema';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { onCreateApp } from '../create'; import { onCreateApp } from '../create';
import { onDelOneApp } from '../del'; import { onDelOneApp } from '@fastgpt/service/core/app/controller';
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller'; import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
export type UpdateHttpPluginBody = { export type UpdateHttpPluginBody = {
......
...@@ -8,7 +8,7 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; ...@@ -8,7 +8,7 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { type ClientSession } from 'mongoose'; import { type ClientSession } from 'mongoose';
import { MongoApp } from '@fastgpt/service/core/app/schema'; import { MongoApp } from '@fastgpt/service/core/app/schema';
import { onDelOneApp } from '../del'; import { onDelOneApp } from '@fastgpt/service/core/app/controller';
import { onCreateApp } from '../create'; import { onCreateApp } from '../create';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
......
import type { NextApiRequest } from 'next'; import type { NextApiRequest } from 'next';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth'; import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { delDatasetRelevantData } from '@fastgpt/service/core/dataset/controller'; import { deleteDatasets } from '@fastgpt/service/core/dataset/controller';
import { findDatasetAndAllChildren } from '@fastgpt/service/core/dataset/controller'; import { findDatasetAndAllChildren } from '@fastgpt/service/core/dataset/controller';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant'; import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { MongoDatasetCollectionTags } from '@fastgpt/service/core/dataset/tag/schema';
import { removeImageByPath } from '@fastgpt/service/common/file/image/controller';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { removeDatasetSyncJobScheduler } from '@fastgpt/service/core/dataset/datasetSync';
import { addAuditLog } from '@fastgpt/service/support/user/audit/util'; import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants'; import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/user/audit/util'; import { getI18nDatasetType } from '@fastgpt/service/support/user/audit/util';
...@@ -37,37 +31,10 @@ async function handler(req: NextApiRequest) { ...@@ -37,37 +31,10 @@ async function handler(req: NextApiRequest) {
teamId, teamId,
datasetId datasetId
}); });
const datasetIds = datasets.map((d) => d._id);
// delete collection.tags await deleteDatasets({
await MongoDatasetCollectionTags.deleteMany({
teamId, teamId,
datasetId: { $in: datasetIds } datasets
});
// Remove cron job
await Promise.all(
datasets.map((dataset) => {
return removeDatasetSyncJobScheduler(dataset._id);
})
);
// delete all dataset.data and pg data
await mongoSessionRun(async (session) => {
// delete dataset data
await delDatasetRelevantData({ datasets, session });
// delete dataset
await MongoDataset.deleteMany(
{
_id: { $in: datasetIds }
},
{ session }
);
for await (const dataset of datasets) {
await removeImageByPath(dataset.avatar, session);
}
}); });
(async () => { (async () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment