mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 14:39:25 +08:00
refactor(plugin-file-manager): move destroy to collection event (#6127)
This commit is contained in:
parent
19ffa45ee9
commit
55a7d9a828
@ -129,69 +129,3 @@ export async function createMiddleware(ctx: Context, next: Next) {
|
||||
|
||||
await multipart(ctx, next);
|
||||
}
|
||||
|
||||
export async function destroyMiddleware(ctx: Context, next: Next) {
|
||||
const { resourceName, actionName, sourceId } = ctx.action;
|
||||
const collection = ctx.db.getCollection(resourceName);
|
||||
|
||||
if (collection?.options?.template !== 'file' || actionName !== 'destroy') {
|
||||
return next();
|
||||
}
|
||||
|
||||
const repository = ctx.db.getRepository(resourceName, sourceId);
|
||||
|
||||
const { filterByTk, filter } = ctx.action.params;
|
||||
|
||||
const records = await repository.find({
|
||||
filterByTk,
|
||||
filter,
|
||||
context: ctx,
|
||||
});
|
||||
|
||||
const storageIds = new Set(records.map((record) => record.storageId));
|
||||
const storageGroupedRecords = records.reduce((result, record) => {
|
||||
const storageId = record.storageId;
|
||||
if (!result[storageId]) {
|
||||
result[storageId] = [];
|
||||
}
|
||||
result[storageId].push(record);
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
const storages = await ctx.db.getRepository('storages').find({
|
||||
filter: {
|
||||
id: [...storageIds] as any[],
|
||||
paranoid: {
|
||||
$ne: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
const undeleted = [];
|
||||
await storages.reduce(
|
||||
(promise, storage) =>
|
||||
promise.then(async () => {
|
||||
const storageConfig = ctx.app.pm.get(Plugin).storageTypes.get(storage.type);
|
||||
const result = await storageConfig.delete(storage, storageGroupedRecords[storage.id]);
|
||||
count += result[0];
|
||||
undeleted.push(...result[1]);
|
||||
}),
|
||||
Promise.resolve(),
|
||||
);
|
||||
|
||||
if (undeleted.length) {
|
||||
const ids = undeleted.map((record) => record.id);
|
||||
ctx.action.mergeParams({
|
||||
filter: {
|
||||
id: {
|
||||
$notIn: ids,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ctx.logger.error('[file-manager] some of attachment files are not successfully deleted: ', { ids });
|
||||
}
|
||||
|
||||
await next();
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import actions from '@nocobase/actions';
|
||||
import { createMiddleware, destroyMiddleware } from './attachments';
|
||||
import { createMiddleware } from './attachments';
|
||||
import * as storageActions from './storages';
|
||||
|
||||
export default function ({ app }) {
|
||||
@ -18,6 +18,4 @@ export default function ({ app }) {
|
||||
});
|
||||
app.resourcer.use(createMiddleware, { tag: 'createMiddleware', after: 'auth' });
|
||||
app.resourcer.registerActionHandler('upload', actions.create);
|
||||
|
||||
app.resourcer.use(destroyMiddleware);
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ import { Registry } from '@nocobase/utils';
|
||||
|
||||
import { basename, resolve } from 'path';
|
||||
|
||||
import { Transactionable } from '@nocobase/database';
|
||||
import { Model, Transactionable } from '@nocobase/database';
|
||||
import fs from 'fs';
|
||||
import { STORAGE_TYPE_ALI_OSS, STORAGE_TYPE_LOCAL, STORAGE_TYPE_S3, STORAGE_TYPE_TX_COS } from '../constants';
|
||||
import { FileModel } from './FileModel';
|
||||
import initActions from './actions';
|
||||
import { getFileData } from './actions/attachments';
|
||||
import { AttachmentInterface } from './interfaces/attachment-interface';
|
||||
import { IStorage, StorageModel } from './storages';
|
||||
import { AttachmentModel, IStorage, StorageModel } from './storages';
|
||||
import StorageTypeAliOss from './storages/ali-oss';
|
||||
import StorageTypeLocal from './storages/local';
|
||||
import StorageTypeS3 from './storages/s3';
|
||||
@ -29,6 +29,16 @@ export type * from './storages';
|
||||
|
||||
const DEFAULT_STORAGE_TYPE = STORAGE_TYPE_LOCAL;
|
||||
|
||||
class FileDeleteError extends Error {
|
||||
data: Model;
|
||||
|
||||
constructor(message: string, data: Model) {
|
||||
super(message);
|
||||
this.name = 'FileDeleteError';
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
export type FileRecordOptions = {
|
||||
collectionName: string;
|
||||
filePath: string;
|
||||
@ -46,6 +56,23 @@ export class PluginFileManagerServer extends Plugin {
|
||||
storageTypes = new Registry<IStorage>();
|
||||
storagesCache = new Map<number, StorageModel>();
|
||||
|
||||
afterDestroy = async (record: Model, options) => {
|
||||
const { collection } = record.constructor as typeof Model;
|
||||
if (collection?.options?.template !== 'file' && collection.name !== 'attachments') {
|
||||
return;
|
||||
}
|
||||
|
||||
const storage = this.storagesCache.get(record.get('storageId'));
|
||||
if (storage?.paranoid) {
|
||||
return;
|
||||
}
|
||||
const storageConfig = this.storageTypes.get(storage.type);
|
||||
const result = await storageConfig.delete(storage, [record as unknown as AttachmentModel]);
|
||||
if (!result[0]) {
|
||||
throw new FileDeleteError('Failed to delete file', record);
|
||||
}
|
||||
};
|
||||
|
||||
registerStorageType(type: string, options: IStorage) {
|
||||
this.storageTypes.register(type, options);
|
||||
}
|
||||
@ -184,6 +211,8 @@ export class PluginFileManagerServer extends Plugin {
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.db.on('afterDestroy', this.afterDestroy);
|
||||
|
||||
this.storageTypes.register(STORAGE_TYPE_LOCAL, new StorageTypeLocal());
|
||||
this.storageTypes.register(STORAGE_TYPE_ALI_OSS, new StorageTypeAliOss());
|
||||
this.storageTypes.register(STORAGE_TYPE_S3, new StorageTypeS3());
|
||||
@ -224,8 +253,7 @@ export class PluginFileManagerServer extends Plugin {
|
||||
|
||||
initActions(this);
|
||||
|
||||
this.app.acl.allow('attachments', 'upload', 'loggedIn');
|
||||
this.app.acl.allow('attachments', 'create', 'loggedIn');
|
||||
this.app.acl.allow('attachments', ['upload', 'create', 'destroy'], 'loggedIn');
|
||||
this.app.acl.allow('storages', 'getRules', 'loggedIn');
|
||||
|
||||
// this.app.resourcer.use(uploadMiddleware);
|
||||
|
Loading…
x
Reference in New Issue
Block a user