@tomei/media 0.4.0 → 0.4.1

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.
Files changed (111) hide show
  1. package/.commitlintrc.json +22 -22
  2. package/.eslintrc.js +66 -66
  3. package/.husky/commit-msg +4 -4
  4. package/.husky/pre-commit +4 -4
  5. package/.prettierrc +4 -4
  6. package/.prettierrc copy +3 -3
  7. package/README.md +93 -93
  8. package/dist/base/base.medias.d.ts +38 -38
  9. package/dist/base/base.medias.js +169 -169
  10. package/dist/base/base.repository.abstract.d.ts +12 -12
  11. package/dist/base/base.repository.abstract.js +21 -21
  12. package/dist/base/base.repository.interface.d.ts +9 -9
  13. package/dist/base/base.repository.interface.js +2 -2
  14. package/dist/base/index.d.ts +2 -0
  15. package/dist/base/index.js +6 -0
  16. package/dist/base/index.js.map +1 -0
  17. package/dist/common/common.module.d.ts +2 -2
  18. package/dist/common/common.module.js +22 -22
  19. package/dist/common/common.service.d.ts +13 -13
  20. package/dist/common/common.service.js +107 -107
  21. package/dist/common/common.service.spec.d.ts +0 -0
  22. package/dist/common/common.service.spec.js +5 -0
  23. package/dist/common/common.service.spec.js.map +1 -0
  24. package/dist/common/dto/add-field-translation.dto.d.ts +7 -7
  25. package/dist/common/dto/add-field-translation.dto.js +41 -41
  26. package/dist/common/dto/get-media.dto.d.ts +5 -5
  27. package/dist/common/dto/get-media.dto.js +28 -28
  28. package/dist/common/dto/get-media.dto.js.map +1 -1
  29. package/dist/dto/external-media.dto.d.ts +10 -10
  30. package/dist/dto/external-media.dto.js +69 -69
  31. package/dist/dto/internal-medias.dto.d.ts +12 -12
  32. package/dist/dto/internal-medias.dto.js +86 -86
  33. package/dist/dto/medias.dto.d.ts +12 -0
  34. package/dist/dto/medias.dto.js +88 -0
  35. package/dist/dto/medias.dto.js.map +1 -0
  36. package/dist/entities/index.d.ts +2 -0
  37. package/dist/entities/index.js +6 -0
  38. package/dist/entities/index.js.map +1 -0
  39. package/dist/entities/media.entity.d.ts +21 -0
  40. package/dist/entities/media.entity.js +152 -0
  41. package/dist/entities/media.entity.js.map +1 -0
  42. package/dist/entities/medias.entity.d.ts +21 -21
  43. package/dist/entities/medias.entity.js +151 -151
  44. package/dist/enum/index.d.ts +2 -2
  45. package/dist/enum/index.js +5 -5
  46. package/dist/enum/medias.enum.d.ts +5 -5
  47. package/dist/enum/medias.enum.js +9 -9
  48. package/dist/helpers/error.d.ts +1 -1
  49. package/dist/helpers/error.js +13 -13
  50. package/dist/helpers/index.d.ts +2 -2
  51. package/dist/helpers/index.js +5 -5
  52. package/dist/index.d.ts +11 -11
  53. package/dist/index.js +19 -19
  54. package/dist/interfaces/base.medias-attr.interface.d.ts +20 -20
  55. package/dist/interfaces/base.medias-attr.interface.js +2 -2
  56. package/dist/interfaces/commonService.interface.d.ts +17 -0
  57. package/dist/interfaces/commonService.interface.js +3 -0
  58. package/dist/interfaces/commonService.interface.js.map +1 -0
  59. package/dist/interfaces/index.d.ts +3 -0
  60. package/dist/interfaces/index.js +3 -0
  61. package/dist/interfaces/index.js.map +1 -0
  62. package/dist/interfaces/media.repository.interface.d.ts +10 -0
  63. package/dist/interfaces/media.repository.interface.js +3 -0
  64. package/dist/interfaces/media.repository.interface.js.map +1 -0
  65. package/dist/interfaces/medias-attr.interface.d.ts +22 -0
  66. package/dist/interfaces/medias-attr.interface.js +3 -0
  67. package/dist/interfaces/medias-attr.interface.js.map +1 -0
  68. package/dist/interfaces/medias.repository.interface.d.ts +3 -3
  69. package/dist/interfaces/medias.repository.interface.js +2 -2
  70. package/dist/medias.controller copy.d.ts +25 -0
  71. package/dist/medias.controller copy.js +225 -0
  72. package/dist/medias.controller copy.js.map +1 -0
  73. package/dist/medias.controller.d.ts +29 -25
  74. package/dist/medias.controller.js +119 -224
  75. package/dist/medias.controller.js.map +1 -1
  76. package/dist/medias.controller.old.d.ts +25 -0
  77. package/dist/medias.controller.old.js +225 -0
  78. package/dist/medias.controller.old.js.map +1 -0
  79. package/dist/medias.d.ts +62 -62
  80. package/dist/medias.js +507 -507
  81. package/dist/medias.module.d.ts +2 -2
  82. package/dist/medias.module.js +31 -34
  83. package/dist/medias.module.js.map +1 -1
  84. package/dist/medias.repository.d.ts +16 -16
  85. package/dist/medias.repository.js +46 -46
  86. package/dist/pipe/append-id.pipe.d.ts +6 -6
  87. package/dist/pipe/append-id.pipe.js +27 -27
  88. package/dist/pipe/validate-enum.pipe.d.ts +6 -6
  89. package/dist/pipe/validate-enum.pipe.js +33 -33
  90. package/dist/pipe/validate-id.pipe.d.ts +6 -6
  91. package/dist/pipe/validate-id.pipe.js +30 -30
  92. package/dist/pipe/validate-search.pipe.d.ts +7 -7
  93. package/dist/pipe/validate-search.pipe.js +45 -45
  94. package/dist/responses/deleted.response.d.ts +3 -3
  95. package/dist/responses/deleted.response.js +20 -20
  96. package/dist/responses/pagination.response.d.ts +5 -5
  97. package/dist/responses/pagination.response.js +25 -25
  98. package/dist/tsconfig.tsbuildinfo +1 -1
  99. package/migration/media-migration.js +82 -82
  100. package/package.json +72 -72
  101. package/src/base/base.medias.ts +209 -209
  102. package/src/common/common.module.ts +10 -10
  103. package/src/common/common.service.ts +109 -109
  104. package/src/common/dto/add-field-translation.dto.ts +23 -23
  105. package/src/common/dto/get-media.dto.ts +12 -12
  106. package/src/index.ts +22 -22
  107. package/src/medias.repository.ts +41 -41
  108. package/src/medias.ts +688 -688
  109. package/src/pipe/validate-search.pipe.ts +44 -44
  110. package/tsconfig.build.json +4 -4
  111. package/tslint.json +18 -18
package/dist/medias.js CHANGED
@@ -1,508 +1,508 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.Medias = void 0;
15
- const storage_blob_1 = require("@azure/storage-blob");
16
- const common_1 = require("@nestjs/common");
17
- const crypto = require("crypto");
18
- const fs = require("fs");
19
- const util = require("util");
20
- const base_medias_1 = require("./base/base.medias");
21
- const medias_entity_1 = require("./entities/medias.entity");
22
- const stream_1 = require("stream");
23
- const cuid = require("cuid");
24
- const sequelize_1 = require("sequelize");
25
- class Medias extends base_medias_1.BaseMedias {
26
- constructor(mediasRepository, commonService, media) {
27
- super(mediasRepository, media);
28
- this.blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(process.env.AZURE_STORAGE_CONNECTION_STRING);
29
- this.algorithm = 'aes-256-cbc';
30
- this.entity = typeof medias_entity_1.MediasModel;
31
- this.commonService = commonService;
32
- try {
33
- this.container = process.env.MEDIA_AZUREBLOB_CONTAINER_NAME;
34
- if (!this.container && this.IsStorageTypeAzure()) {
35
- throw new common_1.BadRequestException('CONTAINER_NAME Environtment Variable name not found');
36
- }
37
- }
38
- catch (error) {
39
- throw error;
40
- }
41
- }
42
- async createMedias(isExternalMedias, stream) {
43
- try {
44
- const media = await super.create();
45
- let activityDescription = `Added a new external media Id: ${this.MediaId}.`;
46
- if (!isExternalMedias) {
47
- activityDescription = `Added a new media Id: ${this.MediaId}.`;
48
- await this.createInternalMedias(stream);
49
- }
50
- if (media) {
51
- await this.commonService.addActivityHistory({
52
- Action: 'Add',
53
- Activity: 'Add New Media',
54
- Description: activityDescription,
55
- EntityId: this.MediaId,
56
- EntityValueBefore: '',
57
- EntityValueAfter: JSON.stringify(Object.assign({}, media.get({ plain: true }))),
58
- PerformedById: this.CreatedById,
59
- PerformedAt: this.CreatedAt,
60
- }, this.entity, 'create');
61
- }
62
- return media;
63
- }
64
- catch (error) {
65
- throw error;
66
- }
67
- }
68
- async updateMedias(isExternalMedias, stream) {
69
- try {
70
- const oldMedia = await super.findOne({
71
- where: { MediaId: this.MediaId },
72
- });
73
- const media = await super.update();
74
- let activityDescription = `Updated external media Id: ${this.MediaId}.`;
75
- if (!isExternalMedias) {
76
- await this.updateInternalMedia(stream, oldMedia);
77
- activityDescription = `Updated media Id: ${this.MediaId}.`;
78
- }
79
- if (media) {
80
- await this.commonService.addActivityHistory({
81
- Action: 'Update',
82
- Activity: 'Update Media',
83
- Description: activityDescription,
84
- EntityId: this.MediaId,
85
- EntityValueBefore: JSON.stringify(Object.assign({}, oldMedia.get({ plain: true }))),
86
- EntityValueAfter: JSON.stringify(Object.assign({}, media.get({ plain: true }))),
87
- PerformedById: this.UpdatedById,
88
- PerformedAt: this.UpdatedAt,
89
- }, this.entity, 'update');
90
- }
91
- return media;
92
- }
93
- catch (error) {
94
- throw error;
95
- }
96
- }
97
- IsStorageTypeAzure() {
98
- const mediaStorageType = process.env.MEDIA_STORAGE_TYPE;
99
- if (mediaStorageType === 'azure') {
100
- return true;
101
- }
102
- else {
103
- return false;
104
- }
105
- }
106
- async updateInternalMedia(stream, oldMedia) {
107
- try {
108
- this.FileExtension = this.FileExtension.split('.')[0];
109
- this.FileName = this.FileName.replace(/\.[^/.]+$/, '');
110
- let file;
111
- if (this.IsEncryptedYN === 'Y') {
112
- file = await this.encrypt(stream.buffer);
113
- }
114
- else {
115
- file = {
116
- buffer: stream.buffer,
117
- isEncrypted: false,
118
- };
119
- }
120
- if (this.IsStorageTypeAzure()) {
121
- await this.deleteUploadedFileFromAzure(oldMedia.URL, oldMedia.FileName, oldMedia.FileExtension, oldMedia.IsEncryptedYN);
122
- await this.uploadFileToAzure(file);
123
- }
124
- else {
125
- const filePath = super.createSaveLocation();
126
- const isDirExist = util.promisify(fs.exists);
127
- const isDir = await isDirExist(filePath);
128
- if (isDir) {
129
- fs.unlinkSync(this.FilePath);
130
- if (this.IsEncryptedYN === 'Y') {
131
- fs.unlinkSync(this.getIvPath());
132
- }
133
- }
134
- await this.uploadFileToLocal(file);
135
- }
136
- }
137
- catch (error) {
138
- throw error;
139
- }
140
- }
141
- async createInternalMedias(stream) {
142
- try {
143
- this.FileExtension = this.FileExtension.split('.')[0];
144
- this.FileName = this.FileName.replace(/\.[^/.]+$/, '');
145
- let file;
146
- if (this.IsEncryptedYN === 'Y') {
147
- file = await this.encrypt(stream.buffer);
148
- }
149
- else {
150
- file = {
151
- buffer: stream.buffer,
152
- isEncrypted: false,
153
- };
154
- }
155
- if (this.IsStorageTypeAzure()) {
156
- this.uploadFileToAzure(file);
157
- }
158
- else {
159
- this.uploadFileToLocal(file);
160
- }
161
- }
162
- catch (error) {
163
- throw error;
164
- }
165
- }
166
- getIvPath() {
167
- return super.createSaveLocation() + `/${this.FileName}iv.iv`;
168
- }
169
- async uploadFileToLocal(file) {
170
- try {
171
- const savelocation = super.createSaveLocation();
172
- const isDirExist = util.promisify(fs.exists);
173
- const createDir = util.promisify(fs.mkdir);
174
- const isDir = await isDirExist(savelocation);
175
- if (!isDir) {
176
- await createDir(savelocation, { recursive: true });
177
- }
178
- const writeFileContent = util.promisify(fs.writeFile);
179
- await writeFileContent(this.FilePath, file.buffer);
180
- if (file.isEncrypted) {
181
- await writeFileContent(this.getIvPath(), file.iv);
182
- }
183
- const path = {
184
- filePath: super.createSaveLocation(),
185
- ivFilePath: this.getIvPath() ? this.getIvPath() : '',
186
- };
187
- return path;
188
- }
189
- catch (error) {
190
- throw error;
191
- }
192
- }
193
- async deleteUploadedFileFromLocal(path, isEncryptedYN) {
194
- try {
195
- const isDirExist = util.promisify(fs.exists);
196
- const isDir = await isDirExist(path);
197
- if (isDir) {
198
- const deleteFile = util.promisify(fs.unlink);
199
- await deleteFile(path);
200
- if (isEncryptedYN === 'Y') {
201
- await deleteFile(this.getIvPath());
202
- }
203
- }
204
- }
205
- catch (error) {
206
- throw error;
207
- }
208
- }
209
- async uploadFileToAzure(file) {
210
- const filePath = await this.uploadFileToAzureStorage(file.buffer, this.ObjectType, this.ObjectId, this.FileName, this.FileExtension);
211
- let ivPath;
212
- if (this.IsEncryptedYN === 'Y') {
213
- ivPath = await this.uploadFileToAzureStorage(file.iv, this.ObjectType, this.ObjectId, this.FileName + 'iv', 'iv');
214
- }
215
- const path = {
216
- filePath,
217
- ivFilePath: ivPath,
218
- };
219
- return path;
220
- }
221
- async deleteUploadedFileFromAzure(path, FileName, FileExtension, isEncryptedYN) {
222
- try {
223
- await this.deleteUploadedFileToAzureStorage(path, FileName, FileExtension);
224
- if (isEncryptedYN === 'Y') {
225
- await this.deleteUploadedFileToAzureStorage(path, FileName + 'iv', '.iv');
226
- }
227
- }
228
- catch (error) {
229
- throw error;
230
- }
231
- }
232
- async uploadFileToAzureStorage(bufferFile, ObjectType, ObjectId, FileName, FileExtension) {
233
- try {
234
- const fileName = FileName.replace(/\.[^/.]+$/, '');
235
- const path = `${this.container}/${ObjectType}/${ObjectId}`;
236
- const blobcontainer = this.blobServiceClient.getContainerClient(path);
237
- const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
238
- await blockBlobClient.uploadData(bufferFile);
239
- return path;
240
- }
241
- catch (error) {
242
- throw error;
243
- }
244
- }
245
- async deleteUploadedFileToAzureStorage(path, FileName, FileExtension) {
246
- const fileName = FileName.replace(/\.[^/.]+$/, '');
247
- const blobcontainer = this.blobServiceClient.getContainerClient(path);
248
- const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
249
- return await blockBlobClient.deleteIfExists();
250
- }
251
- setKey() {
252
- try {
253
- const key = process.env.MEDIA_ENCRYPT_KEY;
254
- if (!key) {
255
- throw new common_1.BadRequestException('MEDIA_ENCRYPT_KEY Environtment Variable name not found');
256
- }
257
- return key;
258
- }
259
- catch (error) {
260
- throw error;
261
- }
262
- }
263
- async findFile() {
264
- try {
265
- let fileBuffer;
266
- if (this.IsStorageTypeAzure()) {
267
- fileBuffer = await this.getFileFromAzure(this.URL, this.FileName, this.FileExtension);
268
- }
269
- else {
270
- fileBuffer = await this.getFileFromLocal(this.FilePath);
271
- }
272
- let file = {
273
- buffer: fileBuffer,
274
- isEncrypted: this.IsEncryptedYN === 'Y' ? true : false,
275
- };
276
- if (file.isEncrypted) {
277
- if (this.IsStorageTypeAzure()) {
278
- file.iv = await this.getFileFromAzure(this.URL, this.FileName + 'iv', 'iv');
279
- }
280
- else {
281
- file.iv = await this.getFileFromLocal(this.getIvPath());
282
- }
283
- file = await this.decrypt(file);
284
- }
285
- return file.buffer;
286
- }
287
- catch (error) {
288
- throw error;
289
- }
290
- }
291
- async stream2buffer(stream) {
292
- return new Promise((resolve, reject) => {
293
- const buffer = Array();
294
- stream.on('data', (chunk) => buffer.push(chunk));
295
- stream.on('end', () => resolve(Buffer.concat(buffer)));
296
- stream.on('error', (err) => reject(`error converting stream - ${err}`));
297
- });
298
- }
299
- async getFileFromAzure(path, FileName, FileExtension) {
300
- try {
301
- const fileName = FileName.replace(/\.[^/.]+$/, '');
302
- const blobcontainer = this.blobServiceClient.getContainerClient(path);
303
- const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
304
- const downloadResponse = await blockBlobClient.download();
305
- const ReadStream = new stream_1.Readable().wrap(downloadResponse.readableStreamBody);
306
- const file = await this.stream2buffer(ReadStream);
307
- return file;
308
- }
309
- catch (error) {
310
- throw error;
311
- }
312
- }
313
- async getFileFromLocal(pathfile) {
314
- try {
315
- const stream = fs.createReadStream(pathfile);
316
- const file = await this.stream2buffer(stream);
317
- return file;
318
- }
319
- catch (error) {
320
- throw error;
321
- }
322
- }
323
- async encrypt(fileBuffer) {
324
- try {
325
- const key = this.setKey();
326
- const iv = crypto.randomBytes(16);
327
- const cipher = crypto.createCipheriv(this.algorithm, key, iv);
328
- const resultBuffer = Buffer.concat([
329
- cipher.update(fileBuffer),
330
- cipher.final(),
331
- ]);
332
- const result = {
333
- buffer: resultBuffer,
334
- iv,
335
- isEncrypted: true,
336
- };
337
- return result;
338
- }
339
- catch (error) {
340
- throw error;
341
- }
342
- }
343
- async decrypt(file) {
344
- try {
345
- const key = this.setKey();
346
- const iv = file.iv;
347
- const decipher = crypto.createDecipheriv(this.algorithm, key, iv);
348
- const resultBuffer = Buffer.concat([
349
- decipher.update(file.buffer),
350
- decipher.final(),
351
- ]);
352
- const result = {
353
- buffer: resultBuffer,
354
- isEncrypted: false,
355
- };
356
- return result;
357
- }
358
- catch (error) {
359
- throw error;
360
- }
361
- }
362
- async delete() {
363
- try {
364
- const data = await super.delete();
365
- if (this.IsExternalYN === 'N') {
366
- if (this.IsStorageTypeAzure()) {
367
- await this.deleteUploadedFileFromAzure(this.URL, this.FileName, this.FileExtension, this.IsEncryptedYN);
368
- }
369
- else {
370
- await this.deleteUploadedFileFromLocal(this.URL, this.IsEncryptedYN);
371
- }
372
- }
373
- await this.commonService.addActivityHistory({
374
- Action: 'Delete',
375
- Activity: 'Delete Media',
376
- Description: `Deleted media (ID: ${this.MediaId})`,
377
- EntityId: this.MediaId,
378
- EntityValueBefore: JSON.stringify(data),
379
- EntityValueAfter: '',
380
- PerformedById: this.UpdatedById,
381
- PerformedAt: new Date(),
382
- }, this.entity, 'delete');
383
- return { message: 'Media has been deleted.' };
384
- }
385
- catch (error) {
386
- throw error;
387
- }
388
- }
389
- async postInternal(fileStream, createMediaDto, userId) {
390
- try {
391
- const mediaAttr = Object.assign(Object.assign({}, createMediaDto), { MediaId: cuid(), IsExternalYN: 'N', ExternalSource: '', URL: '', FilePath: '', CreatedAt: new Date(), UpdatedAt: new Date(), CreatedById: userId, UpdatedById: userId });
392
- this.init(mediaAttr);
393
- const createdData = await this.createMedias(false, fileStream);
394
- return createdData;
395
- }
396
- catch (error) {
397
- throw error;
398
- }
399
- }
400
- async postExternal(createMediaDto, userId) {
401
- const mediaAttr = Object.assign(Object.assign({}, createMediaDto), { MediaId: cuid(), IsExternalYN: 'Y', CreatedAt: new Date(), UpdatedAt: new Date(), IsEncryptedYN: 'N', FilePath: '', FileName: '', FileExtension: '', CreatedById: userId, UpdatedById: userId });
402
- this.init(mediaAttr);
403
- await this.createMedias(true);
404
- return mediaAttr;
405
- }
406
- async getAll(rows, page, search) {
407
- let searchObj;
408
- try {
409
- searchObj = search ? JSON.parse(search) : {};
410
- }
411
- catch (err) {
412
- throw new common_1.BadRequestException('Bad value for search.');
413
- }
414
- const mediaFilter = __rest(searchObj, []);
415
- const queryObj = {};
416
- Object.entries(mediaFilter).forEach(([key, value]) => {
417
- queryObj[key] = {
418
- [sequelize_1.Op.substring]: value,
419
- };
420
- });
421
- const offset = rows * (page - 1);
422
- const options = {
423
- order: [['CreatedAt', 'DESC']],
424
- limit: rows,
425
- offset,
426
- where: queryObj,
427
- distinct: true,
428
- };
429
- return this.findAllWithPagination(options);
430
- }
431
- async getOne(id) {
432
- try {
433
- const media = await this.findOne({ where: { MediaId: id } });
434
- if (!media) {
435
- throw new common_1.NotFoundException(`Media not found with id ${id}`);
436
- }
437
- return media;
438
- }
439
- catch (error) {
440
- throw error;
441
- }
442
- }
443
- async getFile(id) {
444
- try {
445
- const media = await this.findOne({ where: { MediaId: id } });
446
- if (!media) {
447
- throw new common_1.NotFoundException(`Media not found with id ${id}`);
448
- }
449
- this.init(Object.assign({}, media.get({ plain: true })));
450
- const fileBuffer = await this.findFile();
451
- return {
452
- fileBuffer: fileBuffer,
453
- resOption: {
454
- 'Content-Type': 'application/octet-stream',
455
- 'Content-Disposition': `attachment; filename=${media.FileName}.${media.FileExtension}`,
456
- 'Content-Length': fileBuffer.length,
457
- },
458
- };
459
- }
460
- catch (error) {
461
- throw error;
462
- }
463
- }
464
- async remove(id, userId) {
465
- try {
466
- const media = await this.findOne({ where: { MediaId: id } });
467
- if (!media) {
468
- throw new common_1.NotFoundException(`Media not found with id ${id}`);
469
- }
470
- const mediaAttr = Object.assign(Object.assign({}, media.get({ plain: true })), { UpdatedAt: new Date(), UpdatedById: userId });
471
- this.init(mediaAttr);
472
- return await this.delete();
473
- }
474
- catch (error) {
475
- throw error;
476
- }
477
- }
478
- async putExternal(id, updatedMediaDto, userId) {
479
- try {
480
- const media = await this.findOne({ where: { MediaId: id } });
481
- if (!media) {
482
- throw new common_1.NotFoundException(`Media not found with id ${id}`);
483
- }
484
- const mediaAttr = Object.assign(Object.assign(Object.assign({}, media.get({ plain: true })), updatedMediaDto), { UpdatedAt: new Date(), UpdatedById: userId });
485
- this.init(mediaAttr);
486
- return await this.updateMedias(true);
487
- }
488
- catch (error) {
489
- throw error;
490
- }
491
- }
492
- async putInternal(fileStream, id, updatedMediaDto, userId) {
493
- try {
494
- const media = await this.findOne({ where: { MediaId: id } });
495
- if (!media) {
496
- throw new common_1.NotFoundException(`Media not found with id ${id}`);
497
- }
498
- const mediaAttr = Object.assign(Object.assign(Object.assign({}, media.get({ plain: true })), updatedMediaDto), { UpdatedAt: new Date(), UpdatedById: userId });
499
- this.init(mediaAttr);
500
- return await this.updateMedias(false, fileStream);
501
- }
502
- catch (error) {
503
- throw error;
504
- }
505
- }
506
- }
507
- exports.Medias = Medias;
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.Medias = void 0;
15
+ const storage_blob_1 = require("@azure/storage-blob");
16
+ const common_1 = require("@nestjs/common");
17
+ const crypto = require("crypto");
18
+ const fs = require("fs");
19
+ const util = require("util");
20
+ const base_medias_1 = require("./base/base.medias");
21
+ const medias_entity_1 = require("./entities/medias.entity");
22
+ const stream_1 = require("stream");
23
+ const cuid = require("cuid");
24
+ const sequelize_1 = require("sequelize");
25
+ class Medias extends base_medias_1.BaseMedias {
26
+ constructor(mediasRepository, commonService, media) {
27
+ super(mediasRepository, media);
28
+ this.blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(process.env.AZURE_STORAGE_CONNECTION_STRING);
29
+ this.algorithm = 'aes-256-cbc';
30
+ this.entity = typeof medias_entity_1.MediasModel;
31
+ this.commonService = commonService;
32
+ try {
33
+ this.container = process.env.MEDIA_AZUREBLOB_CONTAINER_NAME;
34
+ if (!this.container && this.IsStorageTypeAzure()) {
35
+ throw new common_1.BadRequestException('CONTAINER_NAME Environtment Variable name not found');
36
+ }
37
+ }
38
+ catch (error) {
39
+ throw error;
40
+ }
41
+ }
42
+ async createMedias(isExternalMedias, stream) {
43
+ try {
44
+ const media = await super.create();
45
+ let activityDescription = `Added a new external media Id: ${this.MediaId}.`;
46
+ if (!isExternalMedias) {
47
+ activityDescription = `Added a new media Id: ${this.MediaId}.`;
48
+ await this.createInternalMedias(stream);
49
+ }
50
+ if (media) {
51
+ await this.commonService.addActivityHistory({
52
+ Action: 'Add',
53
+ Activity: 'Add New Media',
54
+ Description: activityDescription,
55
+ EntityId: this.MediaId,
56
+ EntityValueBefore: '',
57
+ EntityValueAfter: JSON.stringify(Object.assign({}, media.get({ plain: true }))),
58
+ PerformedById: this.CreatedById,
59
+ PerformedAt: this.CreatedAt,
60
+ }, this.entity, 'create');
61
+ }
62
+ return media;
63
+ }
64
+ catch (error) {
65
+ throw error;
66
+ }
67
+ }
68
+ async updateMedias(isExternalMedias, stream) {
69
+ try {
70
+ const oldMedia = await super.findOne({
71
+ where: { MediaId: this.MediaId },
72
+ });
73
+ const media = await super.update();
74
+ let activityDescription = `Updated external media Id: ${this.MediaId}.`;
75
+ if (!isExternalMedias) {
76
+ await this.updateInternalMedia(stream, oldMedia);
77
+ activityDescription = `Updated media Id: ${this.MediaId}.`;
78
+ }
79
+ if (media) {
80
+ await this.commonService.addActivityHistory({
81
+ Action: 'Update',
82
+ Activity: 'Update Media',
83
+ Description: activityDescription,
84
+ EntityId: this.MediaId,
85
+ EntityValueBefore: JSON.stringify(Object.assign({}, oldMedia.get({ plain: true }))),
86
+ EntityValueAfter: JSON.stringify(Object.assign({}, media.get({ plain: true }))),
87
+ PerformedById: this.UpdatedById,
88
+ PerformedAt: this.UpdatedAt,
89
+ }, this.entity, 'update');
90
+ }
91
+ return media;
92
+ }
93
+ catch (error) {
94
+ throw error;
95
+ }
96
+ }
97
+ IsStorageTypeAzure() {
98
+ const mediaStorageType = process.env.MEDIA_STORAGE_TYPE;
99
+ if (mediaStorageType === 'azure') {
100
+ return true;
101
+ }
102
+ else {
103
+ return false;
104
+ }
105
+ }
106
+ async updateInternalMedia(stream, oldMedia) {
107
+ try {
108
+ this.FileExtension = this.FileExtension.split('.')[0];
109
+ this.FileName = this.FileName.replace(/\.[^/.]+$/, '');
110
+ let file;
111
+ if (this.IsEncryptedYN === 'Y') {
112
+ file = await this.encrypt(stream.buffer);
113
+ }
114
+ else {
115
+ file = {
116
+ buffer: stream.buffer,
117
+ isEncrypted: false,
118
+ };
119
+ }
120
+ if (this.IsStorageTypeAzure()) {
121
+ await this.deleteUploadedFileFromAzure(oldMedia.URL, oldMedia.FileName, oldMedia.FileExtension, oldMedia.IsEncryptedYN);
122
+ await this.uploadFileToAzure(file);
123
+ }
124
+ else {
125
+ const filePath = super.createSaveLocation();
126
+ const isDirExist = util.promisify(fs.exists);
127
+ const isDir = await isDirExist(filePath);
128
+ if (isDir) {
129
+ fs.unlinkSync(this.FilePath);
130
+ if (this.IsEncryptedYN === 'Y') {
131
+ fs.unlinkSync(this.getIvPath());
132
+ }
133
+ }
134
+ await this.uploadFileToLocal(file);
135
+ }
136
+ }
137
+ catch (error) {
138
+ throw error;
139
+ }
140
+ }
141
+ async createInternalMedias(stream) {
142
+ try {
143
+ this.FileExtension = this.FileExtension.split('.')[0];
144
+ this.FileName = this.FileName.replace(/\.[^/.]+$/, '');
145
+ let file;
146
+ if (this.IsEncryptedYN === 'Y') {
147
+ file = await this.encrypt(stream.buffer);
148
+ }
149
+ else {
150
+ file = {
151
+ buffer: stream.buffer,
152
+ isEncrypted: false,
153
+ };
154
+ }
155
+ if (this.IsStorageTypeAzure()) {
156
+ this.uploadFileToAzure(file);
157
+ }
158
+ else {
159
+ this.uploadFileToLocal(file);
160
+ }
161
+ }
162
+ catch (error) {
163
+ throw error;
164
+ }
165
+ }
166
+ getIvPath() {
167
+ return super.createSaveLocation() + `/${this.FileName}iv.iv`;
168
+ }
169
+ async uploadFileToLocal(file) {
170
+ try {
171
+ const savelocation = super.createSaveLocation();
172
+ const isDirExist = util.promisify(fs.exists);
173
+ const createDir = util.promisify(fs.mkdir);
174
+ const isDir = await isDirExist(savelocation);
175
+ if (!isDir) {
176
+ await createDir(savelocation, { recursive: true });
177
+ }
178
+ const writeFileContent = util.promisify(fs.writeFile);
179
+ await writeFileContent(this.FilePath, file.buffer);
180
+ if (file.isEncrypted) {
181
+ await writeFileContent(this.getIvPath(), file.iv);
182
+ }
183
+ const path = {
184
+ filePath: super.createSaveLocation(),
185
+ ivFilePath: this.getIvPath() ? this.getIvPath() : '',
186
+ };
187
+ return path;
188
+ }
189
+ catch (error) {
190
+ throw error;
191
+ }
192
+ }
193
+ async deleteUploadedFileFromLocal(path, isEncryptedYN) {
194
+ try {
195
+ const isDirExist = util.promisify(fs.exists);
196
+ const isDir = await isDirExist(path);
197
+ if (isDir) {
198
+ const deleteFile = util.promisify(fs.unlink);
199
+ await deleteFile(path);
200
+ if (isEncryptedYN === 'Y') {
201
+ await deleteFile(this.getIvPath());
202
+ }
203
+ }
204
+ }
205
+ catch (error) {
206
+ throw error;
207
+ }
208
+ }
209
+ async uploadFileToAzure(file) {
210
+ const filePath = await this.uploadFileToAzureStorage(file.buffer, this.ObjectType, this.ObjectId, this.FileName, this.FileExtension);
211
+ let ivPath;
212
+ if (this.IsEncryptedYN === 'Y') {
213
+ ivPath = await this.uploadFileToAzureStorage(file.iv, this.ObjectType, this.ObjectId, this.FileName + 'iv', 'iv');
214
+ }
215
+ const path = {
216
+ filePath,
217
+ ivFilePath: ivPath,
218
+ };
219
+ return path;
220
+ }
221
+ async deleteUploadedFileFromAzure(path, FileName, FileExtension, isEncryptedYN) {
222
+ try {
223
+ await this.deleteUploadedFileToAzureStorage(path, FileName, FileExtension);
224
+ if (isEncryptedYN === 'Y') {
225
+ await this.deleteUploadedFileToAzureStorage(path, FileName + 'iv', '.iv');
226
+ }
227
+ }
228
+ catch (error) {
229
+ throw error;
230
+ }
231
+ }
232
+ async uploadFileToAzureStorage(bufferFile, ObjectType, ObjectId, FileName, FileExtension) {
233
+ try {
234
+ const fileName = FileName.replace(/\.[^/.]+$/, '');
235
+ const path = `${this.container}/${ObjectType}/${ObjectId}`;
236
+ const blobcontainer = this.blobServiceClient.getContainerClient(path);
237
+ const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
238
+ await blockBlobClient.uploadData(bufferFile);
239
+ return path;
240
+ }
241
+ catch (error) {
242
+ throw error;
243
+ }
244
+ }
245
+ async deleteUploadedFileToAzureStorage(path, FileName, FileExtension) {
246
+ const fileName = FileName.replace(/\.[^/.]+$/, '');
247
+ const blobcontainer = this.blobServiceClient.getContainerClient(path);
248
+ const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
249
+ return await blockBlobClient.deleteIfExists();
250
+ }
251
+ setKey() {
252
+ try {
253
+ const key = process.env.MEDIA_ENCRYPT_KEY;
254
+ if (!key) {
255
+ throw new common_1.BadRequestException('MEDIA_ENCRYPT_KEY Environtment Variable name not found');
256
+ }
257
+ return key;
258
+ }
259
+ catch (error) {
260
+ throw error;
261
+ }
262
+ }
263
+ async findFile() {
264
+ try {
265
+ let fileBuffer;
266
+ if (this.IsStorageTypeAzure()) {
267
+ fileBuffer = await this.getFileFromAzure(this.URL, this.FileName, this.FileExtension);
268
+ }
269
+ else {
270
+ fileBuffer = await this.getFileFromLocal(this.FilePath);
271
+ }
272
+ let file = {
273
+ buffer: fileBuffer,
274
+ isEncrypted: this.IsEncryptedYN === 'Y' ? true : false,
275
+ };
276
+ if (file.isEncrypted) {
277
+ if (this.IsStorageTypeAzure()) {
278
+ file.iv = await this.getFileFromAzure(this.URL, this.FileName + 'iv', 'iv');
279
+ }
280
+ else {
281
+ file.iv = await this.getFileFromLocal(this.getIvPath());
282
+ }
283
+ file = await this.decrypt(file);
284
+ }
285
+ return file.buffer;
286
+ }
287
+ catch (error) {
288
+ throw error;
289
+ }
290
+ }
291
+ async stream2buffer(stream) {
292
+ return new Promise((resolve, reject) => {
293
+ const buffer = Array();
294
+ stream.on('data', (chunk) => buffer.push(chunk));
295
+ stream.on('end', () => resolve(Buffer.concat(buffer)));
296
+ stream.on('error', (err) => reject(`error converting stream - ${err}`));
297
+ });
298
+ }
299
+ async getFileFromAzure(path, FileName, FileExtension) {
300
+ try {
301
+ const fileName = FileName.replace(/\.[^/.]+$/, '');
302
+ const blobcontainer = this.blobServiceClient.getContainerClient(path);
303
+ const blockBlobClient = await blobcontainer.getBlockBlobClient(`${fileName}.${FileExtension}`);
304
+ const downloadResponse = await blockBlobClient.download();
305
+ const ReadStream = new stream_1.Readable().wrap(downloadResponse.readableStreamBody);
306
+ const file = await this.stream2buffer(ReadStream);
307
+ return file;
308
+ }
309
+ catch (error) {
310
+ throw error;
311
+ }
312
+ }
313
+ async getFileFromLocal(pathfile) {
314
+ try {
315
+ const stream = fs.createReadStream(pathfile);
316
+ const file = await this.stream2buffer(stream);
317
+ return file;
318
+ }
319
+ catch (error) {
320
+ throw error;
321
+ }
322
+ }
323
+ async encrypt(fileBuffer) {
324
+ try {
325
+ const key = this.setKey();
326
+ const iv = crypto.randomBytes(16);
327
+ const cipher = crypto.createCipheriv(this.algorithm, key, iv);
328
+ const resultBuffer = Buffer.concat([
329
+ cipher.update(fileBuffer),
330
+ cipher.final(),
331
+ ]);
332
+ const result = {
333
+ buffer: resultBuffer,
334
+ iv,
335
+ isEncrypted: true,
336
+ };
337
+ return result;
338
+ }
339
+ catch (error) {
340
+ throw error;
341
+ }
342
+ }
343
+ async decrypt(file) {
344
+ try {
345
+ const key = this.setKey();
346
+ const iv = file.iv;
347
+ const decipher = crypto.createDecipheriv(this.algorithm, key, iv);
348
+ const resultBuffer = Buffer.concat([
349
+ decipher.update(file.buffer),
350
+ decipher.final(),
351
+ ]);
352
+ const result = {
353
+ buffer: resultBuffer,
354
+ isEncrypted: false,
355
+ };
356
+ return result;
357
+ }
358
+ catch (error) {
359
+ throw error;
360
+ }
361
+ }
362
+ async delete() {
363
+ try {
364
+ const data = await super.delete();
365
+ if (this.IsExternalYN === 'N') {
366
+ if (this.IsStorageTypeAzure()) {
367
+ await this.deleteUploadedFileFromAzure(this.URL, this.FileName, this.FileExtension, this.IsEncryptedYN);
368
+ }
369
+ else {
370
+ await this.deleteUploadedFileFromLocal(this.URL, this.IsEncryptedYN);
371
+ }
372
+ }
373
+ await this.commonService.addActivityHistory({
374
+ Action: 'Delete',
375
+ Activity: 'Delete Media',
376
+ Description: `Deleted media (ID: ${this.MediaId})`,
377
+ EntityId: this.MediaId,
378
+ EntityValueBefore: JSON.stringify(data),
379
+ EntityValueAfter: '',
380
+ PerformedById: this.UpdatedById,
381
+ PerformedAt: new Date(),
382
+ }, this.entity, 'delete');
383
+ return { message: 'Media has been deleted.' };
384
+ }
385
+ catch (error) {
386
+ throw error;
387
+ }
388
+ }
389
+ async postInternal(fileStream, createMediaDto, userId) {
390
+ try {
391
+ const mediaAttr = Object.assign(Object.assign({}, createMediaDto), { MediaId: cuid(), IsExternalYN: 'N', ExternalSource: '', URL: '', FilePath: '', CreatedAt: new Date(), UpdatedAt: new Date(), CreatedById: userId, UpdatedById: userId });
392
+ this.init(mediaAttr);
393
+ const createdData = await this.createMedias(false, fileStream);
394
+ return createdData;
395
+ }
396
+ catch (error) {
397
+ throw error;
398
+ }
399
+ }
400
+ async postExternal(createMediaDto, userId) {
401
+ const mediaAttr = Object.assign(Object.assign({}, createMediaDto), { MediaId: cuid(), IsExternalYN: 'Y', CreatedAt: new Date(), UpdatedAt: new Date(), IsEncryptedYN: 'N', FilePath: '', FileName: '', FileExtension: '', CreatedById: userId, UpdatedById: userId });
402
+ this.init(mediaAttr);
403
+ await this.createMedias(true);
404
+ return mediaAttr;
405
+ }
406
+ async getAll(rows, page, search) {
407
+ let searchObj;
408
+ try {
409
+ searchObj = search ? JSON.parse(search) : {};
410
+ }
411
+ catch (err) {
412
+ throw new common_1.BadRequestException('Bad value for search.');
413
+ }
414
+ const mediaFilter = __rest(searchObj, []);
415
+ const queryObj = {};
416
+ Object.entries(mediaFilter).forEach(([key, value]) => {
417
+ queryObj[key] = {
418
+ [sequelize_1.Op.substring]: value,
419
+ };
420
+ });
421
+ const offset = rows * (page - 1);
422
+ const options = {
423
+ order: [['CreatedAt', 'DESC']],
424
+ limit: rows,
425
+ offset,
426
+ where: queryObj,
427
+ distinct: true,
428
+ };
429
+ return this.findAllWithPagination(options);
430
+ }
431
+ async getOne(id) {
432
+ try {
433
+ const media = await this.findOne({ where: { MediaId: id } });
434
+ if (!media) {
435
+ throw new common_1.NotFoundException(`Media not found with id ${id}`);
436
+ }
437
+ return media;
438
+ }
439
+ catch (error) {
440
+ throw error;
441
+ }
442
+ }
443
+ async getFile(id) {
444
+ try {
445
+ const media = await this.findOne({ where: { MediaId: id } });
446
+ if (!media) {
447
+ throw new common_1.NotFoundException(`Media not found with id ${id}`);
448
+ }
449
+ this.init(Object.assign({}, media.get({ plain: true })));
450
+ const fileBuffer = await this.findFile();
451
+ return {
452
+ fileBuffer: fileBuffer,
453
+ resOption: {
454
+ 'Content-Type': 'application/octet-stream',
455
+ 'Content-Disposition': `attachment; filename=${media.FileName}.${media.FileExtension}`,
456
+ 'Content-Length': fileBuffer.length,
457
+ },
458
+ };
459
+ }
460
+ catch (error) {
461
+ throw error;
462
+ }
463
+ }
464
+ async remove(id, userId) {
465
+ try {
466
+ const media = await this.findOne({ where: { MediaId: id } });
467
+ if (!media) {
468
+ throw new common_1.NotFoundException(`Media not found with id ${id}`);
469
+ }
470
+ const mediaAttr = Object.assign(Object.assign({}, media.get({ plain: true })), { UpdatedAt: new Date(), UpdatedById: userId });
471
+ this.init(mediaAttr);
472
+ return await this.delete();
473
+ }
474
+ catch (error) {
475
+ throw error;
476
+ }
477
+ }
478
+ async putExternal(id, updatedMediaDto, userId) {
479
+ try {
480
+ const media = await this.findOne({ where: { MediaId: id } });
481
+ if (!media) {
482
+ throw new common_1.NotFoundException(`Media not found with id ${id}`);
483
+ }
484
+ const mediaAttr = Object.assign(Object.assign(Object.assign({}, media.get({ plain: true })), updatedMediaDto), { UpdatedAt: new Date(), UpdatedById: userId });
485
+ this.init(mediaAttr);
486
+ return await this.updateMedias(true);
487
+ }
488
+ catch (error) {
489
+ throw error;
490
+ }
491
+ }
492
+ async putInternal(fileStream, id, updatedMediaDto, userId) {
493
+ try {
494
+ const media = await this.findOne({ where: { MediaId: id } });
495
+ if (!media) {
496
+ throw new common_1.NotFoundException(`Media not found with id ${id}`);
497
+ }
498
+ const mediaAttr = Object.assign(Object.assign(Object.assign({}, media.get({ plain: true })), updatedMediaDto), { UpdatedAt: new Date(), UpdatedById: userId });
499
+ this.init(mediaAttr);
500
+ return await this.updateMedias(false, fileStream);
501
+ }
502
+ catch (error) {
503
+ throw error;
504
+ }
505
+ }
506
+ }
507
+ exports.Medias = Medias;
508
508
  //# sourceMappingURL=medias.js.map