@drax/media-back 3.50.0 → 3.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/FileController.js +0 -10
- package/dist/controllers/MediaController.js +23 -0
- package/dist/permissions/MediaPermissions.js +1 -0
- package/dist/routes/MediaRoutes.js +13 -0
- package/dist/services/FileService.js +12 -0
- package/dist/services/MediaService.js +65 -0
- package/package.json +3 -3
- package/src/controllers/FileController.ts +0 -10
- package/src/controllers/MediaController.ts +26 -0
- package/src/index.ts +8 -0
- package/src/permissions/MediaPermissions.ts +1 -0
- package/src/routes/MediaRoutes.ts +14 -0
- package/src/services/FileService.ts +12 -1
- package/src/services/MediaService.ts +113 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/controllers/FileController.d.ts +0 -1
- package/types/controllers/FileController.d.ts.map +1 -1
- package/types/controllers/MediaController.d.ts +1 -0
- package/types/controllers/MediaController.d.ts.map +1 -1
- package/types/index.d.ts +2 -2
- package/types/index.d.ts.map +1 -1
- package/types/permissions/MediaPermissions.d.ts +2 -1
- package/types/permissions/MediaPermissions.d.ts.map +1 -1
- package/types/routes/MediaRoutes.d.ts.map +1 -1
- package/types/services/FileService.d.ts.map +1 -1
- package/types/services/MediaService.d.ts +31 -1
- package/types/services/MediaService.d.ts.map +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import FileServiceFactory from "../factory/services/FileServiceFactory.js";
|
|
2
2
|
import { AbstractFastifyController } from "@drax/crud-back";
|
|
3
3
|
import FilePermissions from "../permissions/FilePermissions.js";
|
|
4
|
-
import { StoreManager } from "@drax/common-back";
|
|
5
4
|
class FileController extends AbstractFastifyController {
|
|
6
5
|
constructor() {
|
|
7
6
|
super(FileServiceFactory.instance, FilePermissions);
|
|
@@ -24,15 +23,6 @@ class FileController extends AbstractFastifyController {
|
|
|
24
23
|
};
|
|
25
24
|
return payload;
|
|
26
25
|
}
|
|
27
|
-
async postDelete(request, item) {
|
|
28
|
-
try {
|
|
29
|
-
await StoreManager.deleteFilepath(item.relativePath);
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
console.error(error);
|
|
33
|
-
}
|
|
34
|
-
return item;
|
|
35
|
-
}
|
|
36
26
|
}
|
|
37
27
|
export default FileController;
|
|
38
28
|
export { FileController };
|
|
@@ -51,6 +51,29 @@ class MediaController extends CommonController {
|
|
|
51
51
|
this.handleError(e, reply);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
async deleteFile(request, reply) {
|
|
55
|
+
try {
|
|
56
|
+
request.rbac.assertPermission(MediaPermissions.DeleteFile);
|
|
57
|
+
const dir = request.params.dir;
|
|
58
|
+
const year = request.params.year;
|
|
59
|
+
const month = request.params.month;
|
|
60
|
+
const filename = request.params.filename;
|
|
61
|
+
const deleteMetadata = request.query?.deleteMetadata === undefined
|
|
62
|
+
? undefined
|
|
63
|
+
: !["false", "0", "no"].includes(String(request.query.deleteMetadata).toLowerCase());
|
|
64
|
+
const result = await this.mediaService.deleteFile({
|
|
65
|
+
dir,
|
|
66
|
+
year,
|
|
67
|
+
month,
|
|
68
|
+
filename,
|
|
69
|
+
deleteMetadata,
|
|
70
|
+
});
|
|
71
|
+
return reply.send(result);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
this.handleError(e, reply);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
54
77
|
}
|
|
55
78
|
export default MediaController;
|
|
56
79
|
export { MediaController };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var MediaPermissions;
|
|
2
2
|
(function (MediaPermissions) {
|
|
3
3
|
MediaPermissions["UploadFile"] = "file:upload";
|
|
4
|
+
MediaPermissions["DeleteFile"] = "file:delete";
|
|
4
5
|
})(MediaPermissions || (MediaPermissions = {}));
|
|
5
6
|
export default MediaPermissions;
|
|
6
7
|
export { MediaPermissions };
|
|
@@ -11,6 +11,19 @@ async function MediaRoutes(fastify, options) {
|
|
|
11
11
|
tags: ['Media'],
|
|
12
12
|
}
|
|
13
13
|
}, (req, rep) => controller.downloadFile(req, rep));
|
|
14
|
+
fastify.delete('/api/file/:dir/:year/:month/:filename', {
|
|
15
|
+
schema: {
|
|
16
|
+
tags: ['Media'],
|
|
17
|
+
querystring: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
deleteMetadata: {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
}, (req, rep) => controller.deleteFile(req, rep));
|
|
14
27
|
}
|
|
15
28
|
export default MediaRoutes;
|
|
16
29
|
export { MediaRoutes };
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { AbstractService } from "@drax/crud-back";
|
|
2
|
+
import { StoreManager } from "@drax/common-back";
|
|
2
3
|
class FileService extends AbstractService {
|
|
3
4
|
constructor(FileRepository, baseSchema, fullSchema) {
|
|
4
5
|
super(FileRepository, baseSchema, fullSchema);
|
|
5
6
|
this._validateOutput = true;
|
|
7
|
+
this.onDeleted = async (id, item) => {
|
|
8
|
+
if (!item?.relativePath) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
await StoreManager.deleteFilepath(item.relativePath);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
console.error(error);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
6
18
|
}
|
|
7
19
|
async registerUploadedFile(data) {
|
|
8
20
|
return await this.create(data);
|
|
@@ -118,6 +118,71 @@ class MediaService {
|
|
|
118
118
|
absolutePath,
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
+
async deleteFile(params) {
|
|
122
|
+
const { dir, year, month, filename, deleteMetadata = true } = params;
|
|
123
|
+
this.assertDir(dir);
|
|
124
|
+
this.assertYear(year);
|
|
125
|
+
this.assertMonth(month);
|
|
126
|
+
const fileDir = join(this.getBaseFileDir(), dir, year, month);
|
|
127
|
+
const relativePath = join(fileDir, filename);
|
|
128
|
+
const absolutePath = resolve(process.cwd(), relativePath);
|
|
129
|
+
let metadataDeleted = false;
|
|
130
|
+
if (deleteMetadata && this.isMetadataEnabled()) {
|
|
131
|
+
const file = await FileServiceFactory.instance.findOneBy("relativePath", relativePath);
|
|
132
|
+
if (file) {
|
|
133
|
+
await FileServiceFactory.instance.delete(file._id);
|
|
134
|
+
metadataDeleted = true;
|
|
135
|
+
return {
|
|
136
|
+
dir,
|
|
137
|
+
year,
|
|
138
|
+
month,
|
|
139
|
+
filename,
|
|
140
|
+
fileDir,
|
|
141
|
+
relativePath,
|
|
142
|
+
absolutePath,
|
|
143
|
+
deleted: true,
|
|
144
|
+
metadataDeleted,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
await StoreManager.deleteFilepath(relativePath);
|
|
149
|
+
return {
|
|
150
|
+
dir,
|
|
151
|
+
year,
|
|
152
|
+
month,
|
|
153
|
+
filename,
|
|
154
|
+
fileDir,
|
|
155
|
+
relativePath,
|
|
156
|
+
absolutePath,
|
|
157
|
+
deleted: true,
|
|
158
|
+
metadataDeleted,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async deleteFileByRelativePath(params) {
|
|
162
|
+
const { relativePath, deleteMetadata = true } = params;
|
|
163
|
+
const absolutePath = resolve(process.cwd(), relativePath);
|
|
164
|
+
let metadataDeleted = false;
|
|
165
|
+
if (deleteMetadata && this.isMetadataEnabled()) {
|
|
166
|
+
const file = await FileServiceFactory.instance.findOneBy("relativePath", relativePath);
|
|
167
|
+
if (file) {
|
|
168
|
+
await FileServiceFactory.instance.delete(file._id);
|
|
169
|
+
metadataDeleted = true;
|
|
170
|
+
return {
|
|
171
|
+
relativePath,
|
|
172
|
+
absolutePath,
|
|
173
|
+
deleted: true,
|
|
174
|
+
metadataDeleted,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await StoreManager.deleteFilepath(relativePath);
|
|
179
|
+
return {
|
|
180
|
+
relativePath,
|
|
181
|
+
absolutePath,
|
|
182
|
+
deleted: true,
|
|
183
|
+
metadataDeleted,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
121
186
|
}
|
|
122
187
|
export default MediaService;
|
|
123
188
|
export { MediaService, };
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.51.0",
|
|
7
7
|
"description": "Media files",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "types/index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"license": "ISC",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@drax/common-back": "^3.28.0",
|
|
24
|
-
"@drax/identity-back": "^3.
|
|
24
|
+
"@drax/identity-back": "^3.51.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@fastify/multipart": "^9.0.3",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"tsc-alias": "^1.8.10",
|
|
40
40
|
"typescript": "^5.4.5"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "62e011454676e3e1d5977be0fcfedba6bd568624"
|
|
43
43
|
}
|
|
@@ -2,7 +2,6 @@ import FileServiceFactory from "../factory/services/FileServiceFactory.js";
|
|
|
2
2
|
import {AbstractFastifyController, CustomRequest} from "@drax/crud-back";
|
|
3
3
|
import FilePermissions from "../permissions/FilePermissions.js";
|
|
4
4
|
import type {IFile, IFileBase} from "../interfaces/IFile";
|
|
5
|
-
import {StoreManager} from "@drax/common-back";
|
|
6
5
|
|
|
7
6
|
class FileController extends AbstractFastifyController<IFile, IFileBase, IFileBase> {
|
|
8
7
|
|
|
@@ -33,15 +32,6 @@ class FileController extends AbstractFastifyController<IFile, IFileBase, IFileBa
|
|
|
33
32
|
|
|
34
33
|
return payload
|
|
35
34
|
}
|
|
36
|
-
|
|
37
|
-
async postDelete(request: CustomRequest, item:IFile){
|
|
38
|
-
try {
|
|
39
|
-
await StoreManager.deleteFilepath(item.relativePath)
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.error(error)
|
|
42
|
-
}
|
|
43
|
-
return item
|
|
44
|
-
}
|
|
45
35
|
}
|
|
46
36
|
|
|
47
37
|
export default FileController;
|
|
@@ -64,6 +64,32 @@ class MediaController extends CommonController {
|
|
|
64
64
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
async deleteFile(request: any, reply: any) {
|
|
68
|
+
try {
|
|
69
|
+
request.rbac.assertPermission(MediaPermissions.DeleteFile)
|
|
70
|
+
|
|
71
|
+
const dir = request.params.dir
|
|
72
|
+
const year = request.params.year
|
|
73
|
+
const month = request.params.month
|
|
74
|
+
const filename = request.params.filename
|
|
75
|
+
const deleteMetadata = request.query?.deleteMetadata === undefined
|
|
76
|
+
? undefined
|
|
77
|
+
: !["false", "0", "no"].includes(String(request.query.deleteMetadata).toLowerCase())
|
|
78
|
+
|
|
79
|
+
const result = await this.mediaService.deleteFile({
|
|
80
|
+
dir,
|
|
81
|
+
year,
|
|
82
|
+
month,
|
|
83
|
+
filename,
|
|
84
|
+
deleteMetadata,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
return reply.send(result)
|
|
88
|
+
} catch (e) {
|
|
89
|
+
this.handleError(e, reply)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
67
93
|
|
|
68
94
|
}
|
|
69
95
|
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,10 @@ import type {
|
|
|
18
18
|
IMediaSaveFileResult,
|
|
19
19
|
IMediaGetFileParams,
|
|
20
20
|
IMediaGetFileResult,
|
|
21
|
+
IMediaDeleteFileParams,
|
|
22
|
+
IMediaDeleteFileResult,
|
|
23
|
+
IMediaDeleteFileByRelativePathParams,
|
|
24
|
+
IMediaDeleteFileByRelativePathResult,
|
|
21
25
|
} from "./services/MediaService.js";
|
|
22
26
|
|
|
23
27
|
export type {
|
|
@@ -29,6 +33,10 @@ export type {
|
|
|
29
33
|
IMediaSaveFileResult,
|
|
30
34
|
IMediaGetFileParams,
|
|
31
35
|
IMediaGetFileResult,
|
|
36
|
+
IMediaDeleteFileParams,
|
|
37
|
+
IMediaDeleteFileResult,
|
|
38
|
+
IMediaDeleteFileByRelativePathParams,
|
|
39
|
+
IMediaDeleteFileByRelativePathResult,
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
export {
|
|
@@ -17,6 +17,20 @@ async function MediaRoutes(fastify, options) {
|
|
|
17
17
|
}
|
|
18
18
|
}, (req,rep) => controller.downloadFile(req,rep) )
|
|
19
19
|
|
|
20
|
+
fastify.delete('/api/file/:dir/:year/:month/:filename', {
|
|
21
|
+
schema: {
|
|
22
|
+
tags: ['Media'],
|
|
23
|
+
querystring: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
deleteMetadata: {
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}, (req,rep) => controller.deleteFile(req,rep) )
|
|
33
|
+
|
|
20
34
|
|
|
21
35
|
}
|
|
22
36
|
|
|
@@ -3,14 +3,25 @@ import type{IFileRepository} from "../interfaces/IFileRepository.js";
|
|
|
3
3
|
import type {IFileBase, IFile} from "../interfaces/IFile.js";
|
|
4
4
|
import {AbstractService} from "@drax/crud-back";
|
|
5
5
|
import type {ZodObject, ZodRawShape} from "zod";
|
|
6
|
+
import {StoreManager} from "@drax/common-back";
|
|
6
7
|
|
|
7
8
|
class FileService extends AbstractService<IFile, IFileBase, IFileBase> {
|
|
8
9
|
|
|
9
|
-
|
|
10
10
|
constructor(FileRepository: IFileRepository, baseSchema?: ZodObject<ZodRawShape>, fullSchema?: ZodObject<ZodRawShape>) {
|
|
11
11
|
super(FileRepository, baseSchema, fullSchema);
|
|
12
12
|
|
|
13
13
|
this._validateOutput = true
|
|
14
|
+
this.onDeleted = async (id: string, item?: IFile | null): Promise<void> => {
|
|
15
|
+
if (!item?.relativePath) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await StoreManager.deleteFilepath(item.relativePath);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error(error);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
14
25
|
|
|
15
26
|
}
|
|
16
27
|
|
|
@@ -49,6 +49,38 @@ interface IMediaGetFileResult {
|
|
|
49
49
|
absolutePath: string;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
interface IMediaDeleteFileParams {
|
|
53
|
+
dir: string;
|
|
54
|
+
year: string;
|
|
55
|
+
month: string;
|
|
56
|
+
filename: string;
|
|
57
|
+
deleteMetadata?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface IMediaDeleteFileResult {
|
|
61
|
+
dir: string;
|
|
62
|
+
year: string;
|
|
63
|
+
month: string;
|
|
64
|
+
filename: string;
|
|
65
|
+
fileDir: string;
|
|
66
|
+
relativePath: string;
|
|
67
|
+
absolutePath: string;
|
|
68
|
+
deleted: boolean;
|
|
69
|
+
metadataDeleted: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface IMediaDeleteFileByRelativePathParams {
|
|
73
|
+
relativePath: string;
|
|
74
|
+
deleteMetadata?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface IMediaDeleteFileByRelativePathResult {
|
|
78
|
+
relativePath: string;
|
|
79
|
+
absolutePath: string;
|
|
80
|
+
deleted: boolean;
|
|
81
|
+
metadataDeleted: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
52
84
|
class MediaService {
|
|
53
85
|
protected getBaseFileDir(): string {
|
|
54
86
|
return DraxConfig.getOrLoad(CommonConfig.FileDir) || "files";
|
|
@@ -183,6 +215,83 @@ class MediaService {
|
|
|
183
215
|
absolutePath,
|
|
184
216
|
};
|
|
185
217
|
}
|
|
218
|
+
|
|
219
|
+
async deleteFile(params: IMediaDeleteFileParams): Promise<IMediaDeleteFileResult> {
|
|
220
|
+
const {dir, year, month, filename, deleteMetadata = true} = params;
|
|
221
|
+
|
|
222
|
+
this.assertDir(dir);
|
|
223
|
+
this.assertYear(year);
|
|
224
|
+
this.assertMonth(month);
|
|
225
|
+
|
|
226
|
+
const fileDir = join(this.getBaseFileDir(), dir, year, month);
|
|
227
|
+
const relativePath = join(fileDir, filename);
|
|
228
|
+
const absolutePath = resolve(process.cwd(), relativePath);
|
|
229
|
+
let metadataDeleted = false;
|
|
230
|
+
|
|
231
|
+
if (deleteMetadata && this.isMetadataEnabled()) {
|
|
232
|
+
const file = await FileServiceFactory.instance.findOneBy("relativePath", relativePath);
|
|
233
|
+
if (file) {
|
|
234
|
+
await FileServiceFactory.instance.delete(file._id);
|
|
235
|
+
metadataDeleted = true;
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
dir,
|
|
239
|
+
year,
|
|
240
|
+
month,
|
|
241
|
+
filename,
|
|
242
|
+
fileDir,
|
|
243
|
+
relativePath,
|
|
244
|
+
absolutePath,
|
|
245
|
+
deleted: true,
|
|
246
|
+
metadataDeleted,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
await StoreManager.deleteFilepath(relativePath);
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
dir,
|
|
255
|
+
year,
|
|
256
|
+
month,
|
|
257
|
+
filename,
|
|
258
|
+
fileDir,
|
|
259
|
+
relativePath,
|
|
260
|
+
absolutePath,
|
|
261
|
+
deleted: true,
|
|
262
|
+
metadataDeleted,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async deleteFileByRelativePath(params: IMediaDeleteFileByRelativePathParams): Promise<IMediaDeleteFileByRelativePathResult> {
|
|
267
|
+
const {relativePath, deleteMetadata = true} = params;
|
|
268
|
+
const absolutePath = resolve(process.cwd(), relativePath);
|
|
269
|
+
let metadataDeleted = false;
|
|
270
|
+
|
|
271
|
+
if (deleteMetadata && this.isMetadataEnabled()) {
|
|
272
|
+
const file = await FileServiceFactory.instance.findOneBy("relativePath", relativePath);
|
|
273
|
+
if (file) {
|
|
274
|
+
await FileServiceFactory.instance.delete(file._id);
|
|
275
|
+
metadataDeleted = true;
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
relativePath,
|
|
279
|
+
absolutePath,
|
|
280
|
+
deleted: true,
|
|
281
|
+
metadataDeleted,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
await StoreManager.deleteFilepath(relativePath);
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
relativePath,
|
|
290
|
+
absolutePath,
|
|
291
|
+
deleted: true,
|
|
292
|
+
metadataDeleted,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
186
295
|
}
|
|
187
296
|
|
|
188
297
|
export default MediaService;
|
|
@@ -195,4 +304,8 @@ export type {
|
|
|
195
304
|
IMediaSaveFileResult,
|
|
196
305
|
IMediaGetFileParams,
|
|
197
306
|
IMediaGetFileResult,
|
|
307
|
+
IMediaDeleteFileParams,
|
|
308
|
+
IMediaDeleteFileResult,
|
|
309
|
+
IMediaDeleteFileByRelativePathParams,
|
|
310
|
+
IMediaDeleteFileByRelativePathResult,
|
|
198
311
|
};
|