@flusys/nestjs-storage 0.1.0-beta.3 → 1.0.0-rc

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 (67) hide show
  1. package/README.md +131 -19
  2. package/cjs/config/storage-config.service.js +5 -0
  3. package/cjs/config/storage.constants.js +0 -8
  4. package/cjs/controllers/file-manager.controller.js +50 -5
  5. package/cjs/controllers/folder.controller.js +46 -4
  6. package/cjs/controllers/storage-config.controller.js +46 -4
  7. package/cjs/controllers/upload.controller.js +6 -12
  8. package/cjs/dtos/file-manager.dto.js +8 -5
  9. package/cjs/dtos/storage-config.dto.js +41 -1
  10. package/cjs/dtos/upload.dto.js +7 -0
  11. package/cjs/entities/storage-config-base.entity.js +31 -2
  12. package/cjs/interfaces/index.js +0 -1
  13. package/cjs/middlewares/file-serve.middleware.js +6 -0
  14. package/cjs/modules/storage.module.js +2 -4
  15. package/cjs/providers/local-provider.js +52 -2
  16. package/cjs/providers/storage-factory.service.js +2 -2
  17. package/cjs/services/file-manager.service.js +37 -24
  18. package/cjs/services/folder.service.js +18 -52
  19. package/cjs/services/storage-datasource.provider.js +10 -16
  20. package/cjs/services/storage-provider-config.service.js +28 -63
  21. package/cjs/services/upload.service.js +39 -27
  22. package/cjs/utils/file-validator.util.js +470 -0
  23. package/cjs/utils/image-compressor.util.js +1 -3
  24. package/config/storage-config.service.d.ts +5 -2
  25. package/config/storage.constants.d.ts +0 -2
  26. package/controllers/file-manager.controller.d.ts +1 -1
  27. package/controllers/upload.controller.d.ts +2 -6
  28. package/dtos/file-manager.dto.d.ts +2 -4
  29. package/dtos/folder.dto.d.ts +2 -4
  30. package/dtos/storage-config.dto.d.ts +9 -6
  31. package/entities/storage-config-base.entity.d.ts +2 -0
  32. package/fesm/config/storage-config.service.js +5 -0
  33. package/fesm/config/storage.constants.js +0 -2
  34. package/fesm/controllers/file-manager.controller.js +51 -6
  35. package/fesm/controllers/folder.controller.js +49 -7
  36. package/fesm/controllers/storage-config.controller.js +49 -7
  37. package/fesm/controllers/upload.controller.js +7 -13
  38. package/fesm/dtos/file-manager.dto.js +8 -5
  39. package/fesm/dtos/storage-config.dto.js +45 -11
  40. package/fesm/dtos/upload.dto.js +8 -1
  41. package/fesm/entities/index.js +1 -5
  42. package/fesm/entities/storage-config-base.entity.js +33 -7
  43. package/fesm/interfaces/index.js +0 -1
  44. package/fesm/interfaces/storage-config.interface.js +1 -3
  45. package/fesm/middlewares/file-serve.middleware.js +7 -1
  46. package/fesm/modules/storage.module.js +2 -4
  47. package/fesm/providers/local-provider.js +52 -2
  48. package/fesm/providers/storage-factory.service.js +2 -2
  49. package/fesm/services/file-manager.service.js +38 -25
  50. package/fesm/services/folder.service.js +19 -53
  51. package/fesm/services/storage-datasource.provider.js +10 -16
  52. package/fesm/services/storage-provider-config.service.js +28 -63
  53. package/fesm/services/upload.service.js +40 -28
  54. package/fesm/utils/file-validator.util.js +463 -0
  55. package/fesm/utils/image-compressor.util.js +1 -3
  56. package/interfaces/file-manager.interface.d.ts +7 -4
  57. package/interfaces/index.d.ts +0 -1
  58. package/interfaces/storage-config.interface.d.ts +2 -20
  59. package/package.json +6 -6
  60. package/providers/local-provider.d.ts +2 -0
  61. package/services/file-manager.service.d.ts +2 -2
  62. package/services/folder.service.d.ts +1 -2
  63. package/services/storage-provider-config.service.d.ts +1 -2
  64. package/utils/file-validator.util.d.ts +16 -0
  65. package/cjs/interfaces/file-upload-response.interface.js +0 -4
  66. package/fesm/interfaces/file-upload-response.interface.js +0 -1
  67. package/interfaces/file-upload-response.interface.d.ts +0 -6
@@ -0,0 +1,470 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "FileValidator", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return FileValidator;
9
+ }
10
+ });
11
+ const _common = require("@nestjs/common");
12
+ function _define_property(obj, key, value) {
13
+ if (key in obj) {
14
+ Object.defineProperty(obj, key, {
15
+ value: value,
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true
19
+ });
20
+ } else {
21
+ obj[key] = value;
22
+ }
23
+ return obj;
24
+ }
25
+ /**
26
+ * Magic byte signatures for common file types.
27
+ * Each entry maps a hex signature pattern to its MIME type.
28
+ */ const MAGIC_BYTES = [
29
+ // Images
30
+ {
31
+ signature: [
32
+ 0xff,
33
+ 0xd8,
34
+ 0xff
35
+ ],
36
+ offset: 0,
37
+ mimeType: 'image/jpeg'
38
+ },
39
+ {
40
+ signature: [
41
+ 0x89,
42
+ 0x50,
43
+ 0x4e,
44
+ 0x47,
45
+ 0x0d,
46
+ 0x0a,
47
+ 0x1a,
48
+ 0x0a
49
+ ],
50
+ offset: 0,
51
+ mimeType: 'image/png'
52
+ },
53
+ {
54
+ signature: [
55
+ 0x47,
56
+ 0x49,
57
+ 0x46,
58
+ 0x38,
59
+ 0x37,
60
+ 0x61
61
+ ],
62
+ offset: 0,
63
+ mimeType: 'image/gif'
64
+ },
65
+ {
66
+ signature: [
67
+ 0x47,
68
+ 0x49,
69
+ 0x46,
70
+ 0x38,
71
+ 0x39,
72
+ 0x61
73
+ ],
74
+ offset: 0,
75
+ mimeType: 'image/gif'
76
+ },
77
+ {
78
+ signature: [
79
+ 0x42,
80
+ 0x4d
81
+ ],
82
+ offset: 0,
83
+ mimeType: 'image/bmp'
84
+ },
85
+ {
86
+ signature: [
87
+ 0x52,
88
+ 0x49,
89
+ 0x46,
90
+ 0x46
91
+ ],
92
+ offset: 0,
93
+ mimeType: 'image/webp'
94
+ },
95
+ {
96
+ signature: [
97
+ 0x00,
98
+ 0x00,
99
+ 0x01,
100
+ 0x00
101
+ ],
102
+ offset: 0,
103
+ mimeType: 'image/x-icon'
104
+ },
105
+ {
106
+ signature: [
107
+ 0x00,
108
+ 0x00,
109
+ 0x02,
110
+ 0x00
111
+ ],
112
+ offset: 0,
113
+ mimeType: 'image/x-icon'
114
+ },
115
+ // Documents
116
+ {
117
+ signature: [
118
+ 0x25,
119
+ 0x50,
120
+ 0x44,
121
+ 0x46
122
+ ],
123
+ offset: 0,
124
+ mimeType: 'application/pdf'
125
+ },
126
+ {
127
+ signature: [
128
+ 0x50,
129
+ 0x4b,
130
+ 0x03,
131
+ 0x04
132
+ ],
133
+ offset: 0,
134
+ mimeType: 'application/zip'
135
+ },
136
+ // Audio
137
+ {
138
+ signature: [
139
+ 0x49,
140
+ 0x44,
141
+ 0x33
142
+ ],
143
+ offset: 0,
144
+ mimeType: 'audio/mpeg'
145
+ },
146
+ {
147
+ signature: [
148
+ 0xff,
149
+ 0xfb
150
+ ],
151
+ offset: 0,
152
+ mimeType: 'audio/mpeg'
153
+ },
154
+ {
155
+ signature: [
156
+ 0xff,
157
+ 0xfa
158
+ ],
159
+ offset: 0,
160
+ mimeType: 'audio/mpeg'
161
+ },
162
+ {
163
+ signature: [
164
+ 0x4f,
165
+ 0x67,
166
+ 0x67,
167
+ 0x53
168
+ ],
169
+ offset: 0,
170
+ mimeType: 'audio/ogg'
171
+ },
172
+ {
173
+ signature: [
174
+ 0x66,
175
+ 0x4c,
176
+ 0x61,
177
+ 0x43
178
+ ],
179
+ offset: 0,
180
+ mimeType: 'audio/flac'
181
+ },
182
+ // Video
183
+ {
184
+ signature: [
185
+ 0x00,
186
+ 0x00,
187
+ 0x00,
188
+ 0x1c,
189
+ 0x66,
190
+ 0x74,
191
+ 0x79,
192
+ 0x70
193
+ ],
194
+ offset: 0,
195
+ mimeType: 'video/mp4'
196
+ },
197
+ {
198
+ signature: [
199
+ 0x00,
200
+ 0x00,
201
+ 0x00,
202
+ 0x20,
203
+ 0x66,
204
+ 0x74,
205
+ 0x79,
206
+ 0x70
207
+ ],
208
+ offset: 0,
209
+ mimeType: 'video/mp4'
210
+ },
211
+ {
212
+ signature: [
213
+ 0x1a,
214
+ 0x45,
215
+ 0xdf,
216
+ 0xa3
217
+ ],
218
+ offset: 0,
219
+ mimeType: 'video/webm'
220
+ },
221
+ {
222
+ signature: [
223
+ 0x52,
224
+ 0x49,
225
+ 0x46,
226
+ 0x46
227
+ ],
228
+ offset: 0,
229
+ mimeType: 'video/avi'
230
+ },
231
+ // Archives
232
+ {
233
+ signature: [
234
+ 0x1f,
235
+ 0x8b
236
+ ],
237
+ offset: 0,
238
+ mimeType: 'application/gzip'
239
+ },
240
+ {
241
+ signature: [
242
+ 0x37,
243
+ 0x7a,
244
+ 0xbc,
245
+ 0xaf,
246
+ 0x27,
247
+ 0x1c
248
+ ],
249
+ offset: 0,
250
+ mimeType: 'application/x-7z-compressed'
251
+ },
252
+ {
253
+ signature: [
254
+ 0x52,
255
+ 0x61,
256
+ 0x72,
257
+ 0x21,
258
+ 0x1a,
259
+ 0x07
260
+ ],
261
+ offset: 0,
262
+ mimeType: 'application/x-rar-compressed'
263
+ }
264
+ ];
265
+ /**
266
+ * MIME type aliases - types that are equivalent.
267
+ */ const MIME_ALIASES = {
268
+ 'image/jpeg': [
269
+ 'image/jpg'
270
+ ],
271
+ 'image/jpg': [
272
+ 'image/jpeg'
273
+ ],
274
+ 'video/mp4': [
275
+ 'video/quicktime'
276
+ ],
277
+ 'application/zip': [
278
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
279
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
280
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
281
+ ]
282
+ };
283
+ /**
284
+ * File types that are text-based and don't have magic bytes.
285
+ * SECURITY NOTE: Dangerous types (HTML, JS, SVG) are excluded as they can contain scripts.
286
+ * These types require explicit allowlisting and additional content scanning.
287
+ */ const TEXT_BASED_TYPES = [
288
+ 'text/plain',
289
+ 'text/csv',
290
+ 'text/markdown',
291
+ 'application/json',
292
+ 'application/xml',
293
+ 'application/typescript',
294
+ 'text/css'
295
+ ];
296
+ /**
297
+ * Dangerous text-based types that can execute scripts.
298
+ * These bypass magic-bytes validation but require explicit allowlisting.
299
+ */ const DANGEROUS_TEXT_TYPES = [
300
+ 'text/html',
301
+ 'application/javascript',
302
+ 'text/javascript',
303
+ 'image/svg+xml',
304
+ 'application/xhtml+xml'
305
+ ];
306
+ let FileValidator = class FileValidator {
307
+ /**
308
+ * Detect file type from buffer using magic bytes.
309
+ * @param buffer - File buffer to analyze
310
+ * @returns Detected MIME type or null if unknown
311
+ */ static detectFileType(buffer) {
312
+ for (const { signature, offset, mimeType } of MAGIC_BYTES){
313
+ if (buffer.length < offset + signature.length) continue;
314
+ let matches = true;
315
+ for(let i = 0; i < signature.length; i++){
316
+ if (buffer[offset + i] !== signature[i]) {
317
+ matches = false;
318
+ break;
319
+ }
320
+ }
321
+ if (matches) {
322
+ return mimeType;
323
+ }
324
+ }
325
+ return null;
326
+ }
327
+ /**
328
+ * Check if a MIME type is text-based (doesn't have magic bytes).
329
+ */ static isTextBasedType(mimeType) {
330
+ return TEXT_BASED_TYPES.some((t)=>mimeType.startsWith(t) || mimeType === t);
331
+ }
332
+ /**
333
+ * Check if a MIME type is a dangerous text type that can execute scripts.
334
+ */ static isDangerousTextType(mimeType) {
335
+ return DANGEROUS_TEXT_TYPES.some((t)=>mimeType === t);
336
+ }
337
+ /**
338
+ * Check if two MIME types are compatible (exact match or aliases).
339
+ */ static mimeTypesMatch(detected, declared) {
340
+ // Exact match
341
+ if (detected === declared) return true;
342
+ // Check aliases
343
+ const aliases = MIME_ALIASES[detected];
344
+ if (aliases?.includes(declared)) return true;
345
+ // Check reverse aliases
346
+ const reverseAliases = MIME_ALIASES[declared];
347
+ if (reverseAliases?.includes(detected)) return true;
348
+ // Check if both are in same category (e.g., both images)
349
+ const detectedCategory = detected.split('/')[0];
350
+ const declaredCategory = declared.split('/')[0];
351
+ // For ZIP-based formats, allow any ZIP-detected file if declared is a ZIP variant
352
+ if (detected === 'application/zip') {
353
+ const zipVariants = [
354
+ 'application/vnd.openxmlformats-officedocument',
355
+ 'application/x-zip',
356
+ 'application/x-compressed'
357
+ ];
358
+ if (zipVariants.some((v)=>declared.startsWith(v))) {
359
+ return true;
360
+ }
361
+ }
362
+ return detectedCategory === declaredCategory;
363
+ }
364
+ /**
365
+ * Check if a MIME type is in the allowed list.
366
+ */ static isTypeAllowed(mimeType, allowedTypes) {
367
+ // Wildcard allows all
368
+ if (allowedTypes.includes('*/*')) return true;
369
+ return allowedTypes.some((allowed)=>{
370
+ // Category wildcard (e.g., "image/*")
371
+ if (allowed.endsWith('/*')) {
372
+ const category = allowed.slice(0, -2);
373
+ return mimeType.startsWith(category);
374
+ }
375
+ return allowed === mimeType;
376
+ });
377
+ }
378
+ /**
379
+ * Validate file content matches declared MIME type using magic bytes.
380
+ * @param buffer - File buffer
381
+ * @param declaredMimeType - MIME type declared by client
382
+ * @param allowedTypes - List of allowed MIME types/patterns
383
+ * @returns Validation result
384
+ */ static validateFileContent(buffer, declaredMimeType, allowedTypes = [
385
+ '*/*'
386
+ ]) {
387
+ try {
388
+ // Detect actual file type from magic bytes
389
+ const detectedType = this.detectFileType(buffer);
390
+ // If no type detected, check if it's a text-based type
391
+ if (!detectedType) {
392
+ // Check for dangerous text types first (HTML, JS, SVG)
393
+ if (this.isDangerousTextType(declaredMimeType)) {
394
+ // Only allow dangerous types if explicitly in allowedTypes (not via wildcard)
395
+ const explicitlyAllowed = allowedTypes.some((t)=>t === declaredMimeType && t !== '*/*' && !t.endsWith('/*'));
396
+ if (!explicitlyAllowed) {
397
+ this.logger.warn(`Blocked dangerous file type: ${declaredMimeType} - requires explicit allowlisting`);
398
+ return {
399
+ valid: false,
400
+ detectedType: declaredMimeType,
401
+ declaredType: declaredMimeType,
402
+ message: `File type "${declaredMimeType}" is potentially dangerous and not explicitly allowed`
403
+ };
404
+ }
405
+ this.logger.warn(`Allowing explicitly permitted dangerous file type: ${declaredMimeType}`);
406
+ }
407
+ if (this.isTextBasedType(declaredMimeType)) {
408
+ // Safe text-based files don't have magic bytes, trust the declared type
409
+ const isAllowed = this.isTypeAllowed(declaredMimeType, allowedTypes);
410
+ return {
411
+ valid: isAllowed,
412
+ detectedType: declaredMimeType,
413
+ declaredType: declaredMimeType,
414
+ message: isAllowed ? undefined : `File type "${declaredMimeType}" is not allowed`
415
+ };
416
+ }
417
+ // For binary files without recognized signatures, be cautious
418
+ this.logger.warn(`Unable to detect file type for declared type: ${declaredMimeType}`);
419
+ return {
420
+ valid: false,
421
+ declaredType: declaredMimeType,
422
+ message: 'Unable to verify file type. File may be corrupted or unsupported.'
423
+ };
424
+ }
425
+ // Check if detected type matches declared type
426
+ if (!this.mimeTypesMatch(detectedType, declaredMimeType)) {
427
+ this.logger.warn(`MIME type mismatch: declared=${declaredMimeType}, detected=${detectedType}`);
428
+ return {
429
+ valid: false,
430
+ detectedType,
431
+ declaredType: declaredMimeType,
432
+ message: `File content does not match declared type. Detected: ${detectedType}, Declared: ${declaredMimeType}`
433
+ };
434
+ }
435
+ // Check if detected type is allowed
436
+ if (!this.isTypeAllowed(detectedType, allowedTypes)) {
437
+ return {
438
+ valid: false,
439
+ detectedType,
440
+ declaredType: declaredMimeType,
441
+ message: `File type "${detectedType}" is not allowed`
442
+ };
443
+ }
444
+ return {
445
+ valid: true,
446
+ detectedType,
447
+ declaredType: declaredMimeType
448
+ };
449
+ } catch (error) {
450
+ this.logger.error('File validation error:', error);
451
+ return {
452
+ valid: false,
453
+ message: 'File validation failed'
454
+ };
455
+ }
456
+ }
457
+ /**
458
+ * Sanitize filename to prevent path traversal and special character issues.
459
+ * @param filename - Original filename
460
+ * @returns Sanitized filename
461
+ */ static sanitizeFilename(filename) {
462
+ return filename// Remove path components (prevent traversal)
463
+ .replace(/^.*[\\\/]/, '')// Remove null bytes
464
+ .replace(/\0/g, '')// Replace multiple dots with single
465
+ .replace(/\.{2,}/g, '.')// Remove special characters except allowed ones
466
+ .replace(/[^a-zA-Z0-9._-]/g, '_')// Limit length
467
+ .substring(0, 255);
468
+ }
469
+ };
470
+ _define_property(FileValidator, "logger", new _common.Logger(FileValidator.name));
@@ -155,9 +155,7 @@ let ImageCompressor = class ImageCompressor {
155
155
  buffer: data,
156
156
  format: `image/${targetFormat}`
157
157
  };
158
- } catch (error) {
159
- // Fallback to original if processing fails
160
- console.warn(`Image processing failed: ${error instanceof Error ? error.message : String(error)}`);
158
+ } catch {
161
159
  return {
162
160
  buffer,
163
161
  format: mimetype
@@ -1,9 +1,12 @@
1
+ import { DatabaseMode } from '@flusys/nestjs-core';
2
+ import { IModuleConfigService } from '@flusys/nestjs-shared/interfaces';
1
3
  import { StorageModuleOptions } from '../interfaces';
2
- export declare class StorageConfigService {
4
+ export declare class StorageConfigService implements IModuleConfigService {
3
5
  private readonly options;
4
6
  constructor(options: StorageModuleOptions);
5
7
  isCompanyFeatureEnabled(): boolean;
6
- getDatabaseMode(): 'single' | 'multi-tenant';
8
+ getDatabaseMode(): DatabaseMode;
9
+ isMultiTenant(): boolean;
7
10
  getMaxFileSize(): number;
8
11
  getAllowedFileTypes(): string[];
9
12
  isFileTypeAllowed(mimeType: string): boolean;
@@ -1,6 +1,4 @@
1
1
  export declare const STORAGE_MODULE_OPTIONS = "STORAGE_MODULE_OPTIONS";
2
- export declare const STORAGE_CONFIG_SERVICE = "STORAGE_CONFIG_SERVICE";
3
- export declare const STORAGE_DATA_SOURCE_PROVIDER = "STORAGE_DATA_SOURCE_PROVIDER";
4
2
  export declare const DEFAULT_MAX_FILE_SIZE: number;
5
3
  export declare const DEFAULT_ALLOWED_FILE_TYPES: string[];
6
4
  export declare const FILE_VALIDATION_MESSAGES: {
@@ -1,5 +1,5 @@
1
- import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
2
1
  import { SingleResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { CreateFileManagerDto, FileManagerResponseDto, FilesResponseDto, GetFilesRequestDto, UpdateFileManagerDto } from '../dtos';
4
4
  import { Request } from 'express';
5
5
  import { FileManagerService } from '../services/file-manager.service';
@@ -2,13 +2,9 @@ import { SingleResponseDto } from '@flusys/nestjs-shared/dtos';
2
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { DeleteMultipleFileDto, DeleteSingleFileDto, FileUploadResponsePayloadDto, UploadOptionsDto } from '../dtos';
4
4
  import { UploadService } from '../services/upload.service';
5
- import { StorageConfigService } from '../config';
6
- import { StorageFactoryService } from '../providers/storage-factory.service';
7
5
  export declare class UploadController {
8
- private uploadService;
9
- private storageConfigService;
10
- private storageFactoryService;
11
- constructor(uploadService: UploadService, storageConfigService: StorageConfigService, storageFactoryService: StorageFactoryService);
6
+ private readonly uploadService;
7
+ constructor(uploadService: UploadService);
12
8
  uploadSingleFile(file: Express.Multer.File, options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto>>;
13
9
  uploadMultipleFiles(files: Express.Multer.File[], options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto[]>>;
14
10
  deleteSingleFile(dto: DeleteSingleFileDto, user: ILoggedUserInfo): Promise<SingleResponseDto<boolean>>;
@@ -1,6 +1,5 @@
1
1
  import { FileLocationEnum } from '../enums';
2
- export declare class CreateFileManagerDto implements Record<string, unknown> {
3
- [key: string]: unknown;
2
+ export declare class CreateFileManagerDto {
4
3
  name: string;
5
4
  key: string;
6
5
  size: string;
@@ -11,8 +10,7 @@ export declare class CreateFileManagerDto implements Record<string, unknown> {
11
10
  location?: FileLocationEnum;
12
11
  }
13
12
  declare const UpdateFileManagerDto_base: import("@nestjs/common").Type<Partial<CreateFileManagerDto>>;
14
- export declare class UpdateFileManagerDto extends UpdateFileManagerDto_base implements Record<string, unknown> {
15
- [key: string]: unknown;
13
+ export declare class UpdateFileManagerDto extends UpdateFileManagerDto_base {
16
14
  id: string;
17
15
  }
18
16
  export declare class FileManagerResponseDto extends UpdateFileManagerDto {
@@ -1,10 +1,8 @@
1
- export declare class CreateFolderDto implements Record<string, unknown> {
2
- [key: string]: unknown;
1
+ export declare class CreateFolderDto {
3
2
  name: string;
4
3
  }
5
4
  declare const UpdateFolderDto_base: import("@nestjs/common").Type<Partial<CreateFolderDto>>;
6
- export declare class UpdateFolderDto extends UpdateFolderDto_base implements Record<string, unknown> {
7
- [key: string]: unknown;
5
+ export declare class UpdateFolderDto extends UpdateFolderDto_base {
8
6
  id: string;
9
7
  }
10
8
  export declare class FolderResponseDto extends UpdateFolderDto {
@@ -1,21 +1,24 @@
1
1
  import { IdentityResponseDto } from '@flusys/nestjs-shared/dtos';
2
2
  import { FileLocationEnum } from '../enums';
3
- export declare class CreateStorageConfigDto implements Record<string, unknown> {
4
- [key: string]: unknown;
3
+ export declare class CreateStorageConfigDto {
5
4
  name: string;
6
5
  storage: FileLocationEnum;
7
6
  config: Record<string, any>;
7
+ isActive?: boolean;
8
+ isDefault?: boolean;
8
9
  }
9
- export declare class UpdateStorageConfigDto implements Record<string, unknown> {
10
- [key: string]: unknown;
10
+ export declare class UpdateStorageConfigDto {
11
11
  id: string;
12
12
  name?: string;
13
13
  storage?: FileLocationEnum;
14
14
  config?: Record<string, any>;
15
+ isActive?: boolean;
16
+ isDefault?: boolean;
15
17
  }
16
- export declare class StorageConfigResponseDto extends IdentityResponseDto implements Record<string, unknown> {
17
- [key: string]: unknown;
18
+ export declare class StorageConfigResponseDto extends IdentityResponseDto {
18
19
  name: string;
19
20
  storage: FileLocationEnum;
20
21
  config: Record<string, any>;
22
+ isActive: boolean;
23
+ isDefault: boolean;
21
24
  }
@@ -4,4 +4,6 @@ export declare abstract class StorageConfigBase extends Identity {
4
4
  name: string;
5
5
  storage: FileLocationEnum;
6
6
  config: Record<string, any>;
7
+ isActive: boolean;
8
+ isDefault: boolean;
7
9
  }
@@ -40,6 +40,11 @@ export class StorageConfigService {
40
40
  return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
41
41
  }
42
42
  /**
43
+ * Check if running in multi-tenant mode
44
+ */ isMultiTenant() {
45
+ return this.getDatabaseMode() === 'multi-tenant';
46
+ }
47
+ /**
43
48
  * Get maximum file size in bytes
44
49
  */ getMaxFileSize() {
45
50
  return this.options.config?.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * Storage Module Constants
3
3
  */ export const STORAGE_MODULE_OPTIONS = 'STORAGE_MODULE_OPTIONS';
4
- export const STORAGE_CONFIG_SERVICE = 'STORAGE_CONFIG_SERVICE';
5
- export const STORAGE_DATA_SOURCE_PROVIDER = 'STORAGE_DATA_SOURCE_PROVIDER';
6
4
  export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
7
5
  export const DEFAULT_ALLOWED_FILE_TYPES = [
8
6
  '*/*'