mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -660,6 +660,83 @@ exports.restoreAssets = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// ─── PERMANENT DELETE (single) ─────────────────────────────────────────────────
|
||||
|
||||
exports.permanentlyDeleteAsset = async (req, res) => {
|
||||
try {
|
||||
const { assetId } = req.params;
|
||||
|
||||
const asset = await Asset.findOne({ where: { asset_id: assetId }, paranoid: false });
|
||||
if (!asset) return R.error(res, "Asset not found.", 404);
|
||||
if (!asset.deletedAt) return R.error(res, "Asset must be archived before it can be permanently deleted.", 400);
|
||||
|
||||
const { storage_provider, storage_key, thumbnail_storage_key } = asset;
|
||||
|
||||
await asset.destroy({ force: true });
|
||||
|
||||
const svc = getProvider(storage_provider);
|
||||
if (svc) {
|
||||
if (storage_key) {
|
||||
try { await svc.deleteFile(storage_key); }
|
||||
catch (err) { console.warn(`[ASSET][PERMANENT DELETE] File cleanup failed for "${storage_key}":`, err.message); }
|
||||
}
|
||||
if (thumbnail_storage_key) {
|
||||
try { await svc.deleteFile(thumbnail_storage_key); }
|
||||
catch (err) { console.warn(`[ASSET][PERMANENT DELETE] Thumbnail cleanup failed for "${thumbnail_storage_key}":`, err.message); }
|
||||
}
|
||||
}
|
||||
|
||||
invalidateListCache();
|
||||
logActivity(req.user?.user_id, 'permanently_delete_asset', { entityType: 'asset', entityId: Number(assetId) });
|
||||
return R.success(res, "Asset permanently deleted.");
|
||||
} catch (err) {
|
||||
console.error("[ASSET][PERMANENT DELETE]", err);
|
||||
return R.error(res, "Internal server error.", 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── PERMANENT DELETE (bulk) ───────────────────────────────────────────────────
|
||||
|
||||
exports.permanentlyDeleteAssets = async (req, res) => {
|
||||
try {
|
||||
const { ids } = req.body;
|
||||
if (!Array.isArray(ids) || !ids.length) return R.error(res, "ids must be a non-empty array.", 400);
|
||||
|
||||
const assets = await Asset.findAll({ where: { asset_id: { [Op.in]: ids } }, paranoid: false });
|
||||
if (!assets.length) return R.error(res, "No assets found.", 404);
|
||||
|
||||
const archivedAssets = assets.filter((a) => a.deletedAt);
|
||||
if (!archivedAssets.length) return R.error(res, "All selected assets must be archived before they can be permanently deleted.", 400);
|
||||
|
||||
const archivedIds = archivedAssets.map((a) => a.asset_id);
|
||||
|
||||
await Asset.destroy({ where: { asset_id: { [Op.in]: archivedIds } }, force: true });
|
||||
|
||||
for (const asset of archivedAssets) {
|
||||
const svc = getProvider(asset.storage_provider);
|
||||
if (!svc) continue;
|
||||
if (asset.storage_key) {
|
||||
try { await svc.deleteFile(asset.storage_key); }
|
||||
catch (err) { console.warn(`[ASSET][PERMANENT DELETE] File cleanup failed for "${asset.storage_key}":`, err.message); }
|
||||
}
|
||||
if (asset.thumbnail_storage_key) {
|
||||
try { await svc.deleteFile(asset.thumbnail_storage_key); }
|
||||
catch (err) { console.warn(`[ASSET][PERMANENT DELETE] Thumbnail cleanup failed for "${asset.thumbnail_storage_key}":`, err.message); }
|
||||
}
|
||||
}
|
||||
|
||||
invalidateListCache();
|
||||
logActivity(req.user?.user_id, 'bulk_permanently_delete_assets', { entityType: 'asset', details: { ids: archivedIds, count: archivedIds.length } });
|
||||
return R.success(res, `${archivedIds.length} asset(s) permanently deleted.`, {
|
||||
deleted_ids: archivedIds,
|
||||
skipped_ids: ids.filter((id) => !archivedIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[ASSET][BULK PERMANENT DELETE]", err);
|
||||
return R.error(res, "Internal server error.", 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── ARCHIVED LIST ────────────────────────────────────────────────────────────
|
||||
|
||||
exports.getArchivedAssets = async (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user