@flusys/nestjs-storage 9.1.2 → 9.2.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.
Files changed (38) hide show
  1. package/README.md +13 -0
  2. package/controllers/file-manager.controller.d.ts +1 -0
  3. package/controllers/folder.controller.d.ts +1 -0
  4. package/controllers/storage-config.controller.d.ts +1 -0
  5. package/fesm/493.js +416 -251
  6. package/fesm/537.js +25 -21
  7. package/fesm/562.js +184 -172
  8. package/fesm/chunks/190.js +6 -6
  9. package/fesm/chunks/252.js +1 -1
  10. package/fesm/chunks/327.js +1 -1
  11. package/fesm/chunks/385.js +1 -1
  12. package/fesm/chunks/591.js +11 -11
  13. package/fesm/chunks/746.js +1 -1
  14. package/fesm/chunks/798.js +1 -1
  15. package/fesm/chunks/918.js +19 -7
  16. package/fesm/config/index.js +8 -8
  17. package/fesm/controllers/index.js +1 -1
  18. package/fesm/docs/index.js +11 -15
  19. package/fesm/dtos/index.js +24 -20
  20. package/fesm/entities/index.js +6 -6
  21. package/fesm/enums/index.js +4 -4
  22. package/fesm/index.js +30 -34
  23. package/fesm/interfaces/index.js +2 -2
  24. package/fesm/modules/index.js +1 -1
  25. package/fesm/providers/index.js +123 -129
  26. package/fesm/services/index.js +1 -1
  27. package/fesm/utils/index.js +88 -84
  28. package/middlewares/file-serve.middleware.d.ts +3 -1
  29. package/package.json +3 -3
  30. package/providers/local-provider.d.ts +2 -0
  31. package/providers/sftp-provider.optional.d.ts +1 -0
  32. package/providers/storage-factory.service.d.ts +4 -2
  33. package/services/file-manager.service.d.ts +5 -6
  34. package/services/folder.service.d.ts +5 -5
  35. package/services/storage-provider-config.service.d.ts +5 -2
  36. package/services/upload.service.d.ts +3 -1
  37. package/utils/company-ownership.util.d.ts +3 -0
  38. package/utils/file-validator.util.d.ts +1 -0
@@ -1,13 +1,12 @@
1
1
  import * as __rspack_external_sharp from "sharp";
2
- import * as __rspack_external_path from "path";
3
2
  import * as __rspack_external_uuid from "uuid";
4
3
  import * as __rspack_external_fs_promises_e1851c9c from "fs/promises";
5
4
  export const __rspack_esm_id = 467;
6
5
  export const __rspack_esm_ids = [467];
7
6
  export const __webpack_modules__ = {
8
- 922(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
9
- /* import */ var _storage_factory_service_js__rspack_import_0 = __webpack_require__(192);
10
- /* import */ var _storage_provider_registry_js__rspack_import_1 = __webpack_require__(264);
7
+ 1922(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
8
+ /* import */ var _storage_factory_service_js__rspack_import_0 = __webpack_require__(2192);
9
+ /* import */ var _storage_provider_registry_js__rspack_import_1 = __webpack_require__(9264);
11
10
  /* import */ var _local_provider_js__rspack_import_2 = __webpack_require__(632);
12
11
  // Core exports
13
12
 
@@ -35,15 +34,15 @@ __webpack_require__.d(__webpack_exports__, {
35
34
  });
36
35
 
37
36
  // EXTERNAL MODULE: external "@nestjs/common"
38
- var common_ = __webpack_require__(157);
37
+ var common_ = __webpack_require__(6157);
39
38
  // EXTERNAL MODULE: external "@flusys/nestjs-shared/constants"
40
- var constants_ = __webpack_require__(140);
39
+ var constants_ = __webpack_require__(9140);
41
40
  // EXTERNAL MODULE: ./projects/nestjs-storage/src/utils/image-compressor.util.ts + 1 modules
42
- var image_compressor_util = __webpack_require__(872);
41
+ var image_compressor_util = __webpack_require__(1872);
43
42
  ;// CONCATENATED MODULE: external "fs/promises"
44
43
 
45
44
  // EXTERNAL MODULE: external "path"
46
- var external_path_ = __webpack_require__(521);
45
+ var external_path_ = __webpack_require__(2521);
47
46
  // EXTERNAL MODULE: external "uuid"
48
47
  var external_uuid_ = __webpack_require__(37);
49
48
  ;// CONCATENATED MODULE: ./projects/nestjs-storage/src/providers/local-provider.ts
@@ -71,20 +70,26 @@ var external_uuid_ = __webpack_require__(37);
71
70
  basePath = '';
72
71
  baseUrl = '';
73
72
  relativeBasePath = '';
73
+ isWithinBase(targetPath) {
74
+ const normalizedBasePath = external_path_.resolve(this.basePath);
75
+ const normalizedTargetPath = external_path_.resolve(targetPath);
76
+ return normalizedTargetPath.startsWith(normalizedBasePath + external_path_.sep) || normalizedTargetPath === normalizedBasePath;
77
+ }
74
78
  /**
75
79
  * SECURITY: Validates that a target path does not escape the base directory
76
80
  * Prevents path traversal attacks using ../ sequences
77
81
  * @throws Error if path traversal is detected
78
82
  */ validatePathWithinBase(targetPath) {
79
- const normalizedBasePath = external_path_.resolve(this.basePath);
80
- const normalizedTargetPath = external_path_.resolve(targetPath);
81
- if (!normalizedTargetPath.startsWith(normalizedBasePath + external_path_.sep) && normalizedTargetPath !== normalizedBasePath) {
82
- throw new common_.BadRequestException({
83
- message: 'Invalid path: Path traversal attempt detected',
84
- messageKey: constants_.SYSTEM_MESSAGES.PATH_TRAVERSAL_DETECTED
85
- });
83
+ if (!this.isWithinBase(targetPath)) {
84
+ this.throwTraversal();
86
85
  }
87
86
  }
87
+ throwTraversal() {
88
+ throw new common_.BadRequestException({
89
+ message: 'Invalid path: Path traversal attempt detected',
90
+ messageKey: constants_.SYSTEM_MESSAGES.PATH_TRAVERSAL_DETECTED
91
+ });
92
+ }
88
93
  /**
89
94
  * SECURITY: Validates file key format to prevent malicious input
90
95
  * @throws Error if key contains suspicious patterns
@@ -159,36 +164,27 @@ var external_uuid_ = __webpack_require__(37);
159
164
  return Promise.all(files.map((file)=>this.uploadFile(file, options)));
160
165
  }
161
166
  async deleteFile(key) {
162
- try {
163
- // SECURITY: Validate key format first
164
- this.validateKeyFormat(key);
165
- // Key now includes the basePath, resolve from cwd
166
- let filePath = external_path_.resolve(key);
167
- // SECURITY: Validate resolved path is within base directory
168
- this.validatePathWithinBase(filePath);
169
- // Check if file exists at the resolved path
167
+ // SECURITY: Validate key format first
168
+ this.validateKeyFormat(key);
169
+ // New keys include the basePath and resolve from cwd; old keys are relative to basePath.
170
+ // Only candidates inside the base directory are ever touched.
171
+ const candidates = [
172
+ external_path_.resolve(key),
173
+ external_path_.join(this.basePath, key)
174
+ ].filter((candidate)=>this.isWithinBase(candidate) && external_path_.resolve(candidate) !== this.basePath);
175
+ if (!candidates.length) this.throwTraversal();
176
+ for (const candidate of candidates){
170
177
  try {
171
- await __rspack_external_fs_promises_e1851c9c.access(filePath);
178
+ await __rspack_external_fs_promises_e1851c9c.access(candidate);
172
179
  } catch {
173
- // Fallback: try with basePath prefix (for old keys without basePath)
174
- const fallbackPath = external_path_.join(this.basePath, key);
175
- // SECURITY: Validate fallback path as well
176
- this.validatePathWithinBase(fallbackPath);
177
- try {
178
- await __rspack_external_fs_promises_e1851c9c.access(fallbackPath);
179
- filePath = fallbackPath;
180
- } catch {
181
- // File doesn't exist at either location - silent return
182
- return;
183
- }
180
+ continue;
184
181
  }
185
- await __rspack_external_fs_promises_e1851c9c.unlink(filePath);
186
- } catch (error) {
187
- // Re-throw security errors
188
- if (error instanceof Error && error.message.includes('Invalid')) {
189
- throw error;
182
+ try {
183
+ await __rspack_external_fs_promises_e1851c9c.unlink(candidate);
184
+ } catch {
185
+ // Silent failure - the file may have been removed concurrently
190
186
  }
191
- // Silent failure for other errors
187
+ return;
192
188
  }
193
189
  }
194
190
  async deleteMultipleFiles(keys) {
@@ -217,7 +213,7 @@ var external_uuid_ = __webpack_require__(37);
217
213
 
218
214
 
219
215
  },
220
- 872(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
216
+ 1872(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
221
217
 
222
218
  // EXPORTS
223
219
  __webpack_require__.d(__webpack_exports__, {
@@ -230,6 +226,10 @@ __webpack_require__.d(__webpack_exports__, {
230
226
 
231
227
  // Handle ESM/CJS interop - sharp exports differently in each module system
232
228
  const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
229
+ const MULTI_FRAME_FORMATS = [
230
+ 'gif',
231
+ 'webp'
232
+ ];
233
233
  /**
234
234
  * Image Compression Utility
235
235
  * Handles image compression and format conversion using sharp
@@ -247,87 +247,87 @@ const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
247
247
  format: mimetype
248
248
  };
249
249
  }
250
- // Initialize sharp with improved error handling
251
- const image = sharp(buffer, {
252
- failOnError: false,
253
- density: 300
254
- });
255
- // Apply initial resize
256
- image.resize({
257
- width: maxWidth,
258
- height: maxHeight,
259
- fit: 'inside',
260
- withoutEnlargement: true
261
- });
262
- // Determine target format
263
- let targetFormat = format !== 'original' ? format : mimetype.split('/')[1];
264
- // Format-specific optimizations
265
- switch(targetFormat.toLowerCase()){
266
- case 'jpeg':
267
- case 'jpg':
268
- image.jpeg({
269
- quality,
270
- mozjpeg: true,
271
- chromaSubsampling: '4:4:4'
272
- });
273
- break;
274
- case 'png':
275
- image.png({
276
- compressionLevel: 9,
277
- adaptiveFiltering: true,
278
- palette: true,
279
- quality,
280
- colors: 256,
281
- dither: 1.0
282
- });
283
- break;
284
- case 'webp':
285
- image.webp({
286
- quality,
287
- smartSubsample: true,
288
- effort: 6,
289
- lossless: quality === 100
290
- });
291
- break;
292
- case 'avif':
293
- image.avif({
294
- quality,
295
- effort: 6,
296
- chromaSubsampling: '4:4:4'
297
- });
298
- break;
299
- case 'tiff':
300
- image.tiff({
301
- quality,
302
- compression: 'lzw',
303
- predictor: 'horizontal',
304
- pyramid: true
305
- });
306
- break;
307
- case 'gif':
308
- image.gif({
309
- colours: 256,
310
- effort: 10,
311
- dither: 1
312
- });
313
- break;
314
- case 'jp2':
315
- image.jp2({
316
- quality,
317
- lossless: quality === 100
318
- });
319
- break;
320
- default:
321
- // Fallback to WebP for best compression/quality ratio
322
- targetFormat = 'webp';
323
- image.webp({
324
- quality,
325
- smartSubsample: true,
326
- effort: 6
327
- });
328
- break;
329
- }
250
+ let targetFormat = (format !== 'original' ? format : mimetype.split('/')[1]).toLowerCase();
330
251
  try {
252
+ // Read every frame only when the output can hold them - a multi-page JPEG/PNG would be one tall strip
253
+ const image = sharp(buffer, {
254
+ failOnError: false,
255
+ density: 300,
256
+ animated: MULTI_FRAME_FORMATS.includes(targetFormat)
257
+ });
258
+ // Apply initial resize
259
+ image.resize({
260
+ width: maxWidth,
261
+ height: maxHeight,
262
+ fit: 'inside',
263
+ withoutEnlargement: true
264
+ });
265
+ // Format-specific optimizations
266
+ switch(targetFormat){
267
+ case 'jpeg':
268
+ case 'jpg':
269
+ image.jpeg({
270
+ quality,
271
+ mozjpeg: true,
272
+ chromaSubsampling: '4:4:4'
273
+ });
274
+ break;
275
+ case 'png':
276
+ image.png({
277
+ compressionLevel: 9,
278
+ adaptiveFiltering: true,
279
+ palette: true,
280
+ quality,
281
+ colors: 256,
282
+ dither: 1.0
283
+ });
284
+ break;
285
+ case 'webp':
286
+ image.webp({
287
+ quality,
288
+ smartSubsample: true,
289
+ effort: 6,
290
+ lossless: quality === 100
291
+ });
292
+ break;
293
+ case 'avif':
294
+ image.avif({
295
+ quality,
296
+ effort: 6,
297
+ chromaSubsampling: '4:4:4'
298
+ });
299
+ break;
300
+ case 'tiff':
301
+ image.tiff({
302
+ quality,
303
+ compression: 'lzw',
304
+ predictor: 'horizontal',
305
+ pyramid: true
306
+ });
307
+ break;
308
+ case 'gif':
309
+ image.gif({
310
+ colours: 256,
311
+ effort: 10,
312
+ dither: 1
313
+ });
314
+ break;
315
+ case 'jp2':
316
+ image.jp2({
317
+ quality,
318
+ lossless: quality === 100
319
+ });
320
+ break;
321
+ default:
322
+ // Fallback to WebP for best compression/quality ratio
323
+ targetFormat = 'webp';
324
+ image.webp({
325
+ quality,
326
+ smartSubsample: true,
327
+ effort: 6
328
+ });
329
+ break;
330
+ }
331
331
  const compressedBuffer = await image.toBuffer();
332
332
  return {
333
333
  buffer: compressedBuffer,
@@ -343,12 +343,6 @@ const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
343
343
  }
344
344
 
345
345
 
346
- },
347
- 521(module) {
348
-
349
- module.exports = __rspack_external_path;
350
-
351
-
352
346
  },
353
347
  37(module) {
354
348
 
@@ -364,7 +358,7 @@ import * as __rspack_chunk_1 from '../493.js';
364
358
  __webpack_require__.C(__rspack_chunk_1);
365
359
  import * as __rspack_chunk_2 from './index.js';
366
360
  __webpack_require__.C(__rspack_chunk_2);
367
- var __webpack_exports__ = __webpack_exec__(922);var __webpack_exports__LocalProvider = __webpack_exports__.TZ;
361
+ var __webpack_exports__ = __webpack_exec__(1922);var __webpack_exports__LocalProvider = __webpack_exports__.TZ;
368
362
  var __webpack_exports__StorageFactoryService = __webpack_exports__.Lk;
369
363
  var __webpack_exports__StorageProviderRegistry = __webpack_exports__.CG;
370
364
  export { __webpack_exports__LocalProvider as LocalProvider, __webpack_exports__StorageFactoryService as StorageFactoryService, __webpack_exports__StorageProviderRegistry as StorageProviderRegistry };
@@ -7,7 +7,7 @@ import * as __rspack_chunk_1 from '../493.js';
7
7
  __webpack_require__.C(__rspack_chunk_1);
8
8
  import * as __rspack_chunk_2 from './index.js';
9
9
  __webpack_require__.C(__rspack_chunk_2);
10
- var __webpack_exports__ = __webpack_exec__(148);var __webpack_exports__FileManagerService = __webpack_exports__.DL;
10
+ var __webpack_exports__ = __webpack_exec__(4148);var __webpack_exports__FileManagerService = __webpack_exports__.DL;
11
11
  var __webpack_exports__FolderService = __webpack_exports__.kh;
12
12
  var __webpack_exports__StorageConfigService = __webpack_exports__.tP;
13
13
  var __webpack_exports__StorageDataSourceProvider = __webpack_exports__.M0;
@@ -2,7 +2,7 @@ import * as __rspack_external_sharp from "sharp";
2
2
  export const __rspack_esm_id = 152;
3
3
  export const __rspack_esm_ids = [152];
4
4
  export const __webpack_modules__ = {
5
- 872(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
5
+ 1872(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
6
6
 
7
7
  // EXPORTS
8
8
  __webpack_require__.d(__webpack_exports__, {
@@ -15,6 +15,10 @@ __webpack_require__.d(__webpack_exports__, {
15
15
 
16
16
  // Handle ESM/CJS interop - sharp exports differently in each module system
17
17
  const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
18
+ const MULTI_FRAME_FORMATS = [
19
+ 'gif',
20
+ 'webp'
21
+ ];
18
22
  /**
19
23
  * Image Compression Utility
20
24
  * Handles image compression and format conversion using sharp
@@ -32,87 +36,87 @@ const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
32
36
  format: mimetype
33
37
  };
34
38
  }
35
- // Initialize sharp with improved error handling
36
- const image = sharp(buffer, {
37
- failOnError: false,
38
- density: 300
39
- });
40
- // Apply initial resize
41
- image.resize({
42
- width: maxWidth,
43
- height: maxHeight,
44
- fit: 'inside',
45
- withoutEnlargement: true
46
- });
47
- // Determine target format
48
- let targetFormat = format !== 'original' ? format : mimetype.split('/')[1];
49
- // Format-specific optimizations
50
- switch(targetFormat.toLowerCase()){
51
- case 'jpeg':
52
- case 'jpg':
53
- image.jpeg({
54
- quality,
55
- mozjpeg: true,
56
- chromaSubsampling: '4:4:4'
57
- });
58
- break;
59
- case 'png':
60
- image.png({
61
- compressionLevel: 9,
62
- adaptiveFiltering: true,
63
- palette: true,
64
- quality,
65
- colors: 256,
66
- dither: 1.0
67
- });
68
- break;
69
- case 'webp':
70
- image.webp({
71
- quality,
72
- smartSubsample: true,
73
- effort: 6,
74
- lossless: quality === 100
75
- });
76
- break;
77
- case 'avif':
78
- image.avif({
79
- quality,
80
- effort: 6,
81
- chromaSubsampling: '4:4:4'
82
- });
83
- break;
84
- case 'tiff':
85
- image.tiff({
86
- quality,
87
- compression: 'lzw',
88
- predictor: 'horizontal',
89
- pyramid: true
90
- });
91
- break;
92
- case 'gif':
93
- image.gif({
94
- colours: 256,
95
- effort: 10,
96
- dither: 1
97
- });
98
- break;
99
- case 'jp2':
100
- image.jp2({
101
- quality,
102
- lossless: quality === 100
103
- });
104
- break;
105
- default:
106
- // Fallback to WebP for best compression/quality ratio
107
- targetFormat = 'webp';
108
- image.webp({
109
- quality,
110
- smartSubsample: true,
111
- effort: 6
112
- });
113
- break;
114
- }
39
+ let targetFormat = (format !== 'original' ? format : mimetype.split('/')[1]).toLowerCase();
115
40
  try {
41
+ // Read every frame only when the output can hold them - a multi-page JPEG/PNG would be one tall strip
42
+ const image = sharp(buffer, {
43
+ failOnError: false,
44
+ density: 300,
45
+ animated: MULTI_FRAME_FORMATS.includes(targetFormat)
46
+ });
47
+ // Apply initial resize
48
+ image.resize({
49
+ width: maxWidth,
50
+ height: maxHeight,
51
+ fit: 'inside',
52
+ withoutEnlargement: true
53
+ });
54
+ // Format-specific optimizations
55
+ switch(targetFormat){
56
+ case 'jpeg':
57
+ case 'jpg':
58
+ image.jpeg({
59
+ quality,
60
+ mozjpeg: true,
61
+ chromaSubsampling: '4:4:4'
62
+ });
63
+ break;
64
+ case 'png':
65
+ image.png({
66
+ compressionLevel: 9,
67
+ adaptiveFiltering: true,
68
+ palette: true,
69
+ quality,
70
+ colors: 256,
71
+ dither: 1.0
72
+ });
73
+ break;
74
+ case 'webp':
75
+ image.webp({
76
+ quality,
77
+ smartSubsample: true,
78
+ effort: 6,
79
+ lossless: quality === 100
80
+ });
81
+ break;
82
+ case 'avif':
83
+ image.avif({
84
+ quality,
85
+ effort: 6,
86
+ chromaSubsampling: '4:4:4'
87
+ });
88
+ break;
89
+ case 'tiff':
90
+ image.tiff({
91
+ quality,
92
+ compression: 'lzw',
93
+ predictor: 'horizontal',
94
+ pyramid: true
95
+ });
96
+ break;
97
+ case 'gif':
98
+ image.gif({
99
+ colours: 256,
100
+ effort: 10,
101
+ dither: 1
102
+ });
103
+ break;
104
+ case 'jp2':
105
+ image.jp2({
106
+ quality,
107
+ lossless: quality === 100
108
+ });
109
+ break;
110
+ default:
111
+ // Fallback to WebP for best compression/quality ratio
112
+ targetFormat = 'webp';
113
+ image.webp({
114
+ quality,
115
+ smartSubsample: true,
116
+ effort: 6
117
+ });
118
+ break;
119
+ }
116
120
  const compressedBuffer = await image.toBuffer();
117
121
  return {
118
122
  buffer: compressedBuffer,
@@ -129,8 +133,8 @@ const sharp = __rspack_external_sharp["default"] || __rspack_external_sharp;
129
133
 
130
134
 
131
135
  },
132
- 857(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
133
- /* import */ var _image_compressor_util_js__rspack_import_0 = __webpack_require__(872);
136
+ 8857(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
137
+ /* import */ var _image_compressor_util_js__rspack_import_0 = __webpack_require__(1872);
134
138
 
135
139
 
136
140
  __webpack_require__.d(__webpack_exports__, {
@@ -145,5 +149,5 @@ import { __webpack_require__ } from '../runtime.js';
145
149
  var __webpack_exec__ = function(moduleId) { return __webpack_require__(__webpack_require__.s = moduleId); }
146
150
  import * as __rspack_chunk_1 from './index.js';
147
151
  __webpack_require__.C(__rspack_chunk_1);
148
- var __webpack_exports__ = __webpack_exec__(857);var __webpack_exports__ImageCompressor = __webpack_exports__.J;
152
+ var __webpack_exports__ = __webpack_exec__(8857);var __webpack_exports__ImageCompressor = __webpack_exports__.J;
149
153
  export { __webpack_exports__ImageCompressor as ImageCompressor };
@@ -9,7 +9,9 @@ export declare class FileServeMiddleware implements NestMiddleware {
9
9
  private serveFile;
10
10
  private extractFilePath;
11
11
  private resolveFilePath;
12
- private tryFallbackPaths;
12
+ private findInStorageRoot;
13
+ private isWithin;
14
+ private fallbackPaths;
13
15
  private getMimeType;
14
16
  private setResponseHeaders;
15
17
  private streamFile;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-storage",
3
- "version": "9.1.2",
3
+ "version": "9.2.0",
4
4
  "description": "Modular storage package with optional AWS S3, Azure Blob, and SFTP providers",
5
5
  "type": "module",
6
6
  "main": "./fesm/index.js",
@@ -118,7 +118,7 @@
118
118
  }
119
119
  },
120
120
  "dependencies": {
121
- "@flusys/nestjs-core": "9.1.2",
122
- "@flusys/nestjs-shared": "9.1.2"
121
+ "@flusys/nestjs-core": "9.2.0",
122
+ "@flusys/nestjs-shared": "9.2.0"
123
123
  }
124
124
  }
@@ -4,7 +4,9 @@ export declare class LocalProvider implements IStorageProvider {
4
4
  private basePath;
5
5
  private baseUrl;
6
6
  private relativeBasePath;
7
+ private isWithinBase;
7
8
  private validatePathWithinBase;
9
+ private throwTraversal;
8
10
  private validateKeyFormat;
9
11
  initialize(config: {
10
12
  basePath?: string;
@@ -17,6 +17,7 @@ export declare class SftpProvider implements IStorageProvider {
17
17
  uploadFile(file: Express.Multer.File, options: UploadOptionsDto): Promise<IUploadedFileInfo>;
18
18
  uploadMultipleFiles(files: Express.Multer.File[], options: UploadOptionsDto): Promise<IUploadedFileInfo[]>;
19
19
  deleteFile(key: string): Promise<void>;
20
+ private resolveWithinBasePath;
20
21
  deleteMultipleFiles(keys: string[]): Promise<void>;
21
22
  generatePresignedUrl(key: string, _expiresInSeconds?: number): Promise<string>;
22
23
  healthCheck(): Promise<boolean>;
@@ -7,9 +7,11 @@ export declare class StorageFactoryService implements OnModuleDestroy {
7
7
  constructor(configService: StorageConfigService);
8
8
  createProvider(config: IStorageProviderConfig): Promise<IStorageProvider>;
9
9
  getProvider(providerName: string): Promise<IStorageProvider>;
10
- getLocalProviderBasePath(): string | null;
11
- clearCache(): void;
10
+ clearCache(): Promise<void>;
12
11
  onModuleDestroy(): Promise<void>;
12
+ private instantiate;
13
+ private evict;
14
+ private closeEntry;
13
15
  private generateCacheKey;
14
16
  private initializeProvider;
15
17
  }
@@ -1,5 +1,5 @@
1
1
  import { ApiService, HybridCache } from '@flusys/nestjs-shared/classes';
2
- import { DeleteDto, FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
2
+ import { DeleteDto } from '@flusys/nestjs-shared/dtos';
3
3
  import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
4
4
  import { SharedPermissionCacheService, UtilsService } from '@flusys/nestjs-shared/modules';
5
5
  import { type QueryRunner, SelectQueryBuilder } from 'typeorm';
@@ -17,8 +17,9 @@ export declare class FileManagerService extends ApiService<CreateFileManagerDto,
17
17
  private readonly dataSourceProvider;
18
18
  private readonly permissionCacheService;
19
19
  constructor(cacheManager: HybridCache, utilsService: UtilsService, uploadService: UploadService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider, permissionCacheService: SharedPermissionCacheService);
20
+ protected cacheDependencies(): string[];
20
21
  convertSingleDtoToEntity(dto: CreateFileManagerDto | UpdateFileManagerDto, user: ILoggedUserInfo | null): Promise<FileManagerBase>;
21
- getSelectQuery(query: SelectQueryBuilder<FileManagerBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
22
+ getSelectQuery(query: SelectQueryBuilder<FileManagerBase>, user: ILoggedUserInfo | null, select?: string[]): Promise<{
22
23
  query: SelectQueryBuilder<FileManager>;
23
24
  isRaw: boolean;
24
25
  }>;
@@ -26,13 +27,11 @@ export declare class FileManagerService extends ApiService<CreateFileManagerDto,
26
27
  query: SelectQueryBuilder<FileManagerBase>;
27
28
  isRaw: boolean;
28
29
  }>;
29
- protected getExtraManipulateQuery(query: SelectQueryBuilder<FileManagerBase>, filterDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
30
- query: SelectQueryBuilder<FileManagerBase>;
31
- isRaw: boolean;
32
- }>;
30
+ protected beforeUpdateOperation(dto: UpdateFileManagerDto | UpdateFileManagerDto[], user: ILoggedUserInfo | null): Promise<void>;
33
31
  beforeDeleteOperation(dto: DeleteDto, user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
34
32
  getFiles(dtos: GetFilesRequestDto[], protocol: string, host: string, user?: ILoggedUserInfo): Promise<FilesResponseDto[]>;
35
33
  private buildWhereWithCompany;
34
+ private assertInUserCompany;
36
35
  private getStorageConfigRepository;
37
36
  private getStorageConfigBasePath;
38
37
  private validateFolder;
@@ -1,4 +1,5 @@
1
1
  import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
2
+ import { DeleteDto } from '@flusys/nestjs-shared/dtos';
2
3
  import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
4
  import { UtilsService } from '@flusys/nestjs-shared/modules';
4
5
  import { SelectQueryBuilder } from 'typeorm';
@@ -13,12 +14,11 @@ export declare class FolderService extends ApiService<CreateFolderDto, UpdateFol
13
14
  private readonly storageConfig;
14
15
  constructor(cacheManager: HybridCache, utilsService: UtilsService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider);
15
16
  convertSingleDtoToEntity(dto: CreateFolderDto | UpdateFolderDto, user: ILoggedUserInfo | null): Promise<FolderBase>;
16
- getSelectQuery(query: SelectQueryBuilder<FolderBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
17
- query: SelectQueryBuilder<Folder>;
18
- isRaw: boolean;
19
- }>;
20
- protected getExtraManipulateQuery(query: SelectQueryBuilder<FolderBase>, filterDto: any, user: ILoggedUserInfo | null): Promise<{
17
+ getSelectQuery(query: SelectQueryBuilder<FolderBase>, user: ILoggedUserInfo | null, select?: string[]): Promise<{
21
18
  query: SelectQueryBuilder<Folder>;
22
19
  isRaw: boolean;
23
20
  }>;
21
+ protected beforeUpdateOperation(dto: UpdateFolderDto | UpdateFolderDto[], user: ILoggedUserInfo | null): Promise<void>;
22
+ protected beforeDeleteOperation(dto: DeleteDto, user: ILoggedUserInfo | null): Promise<void>;
23
+ private assertInUserCompany;
24
24
  }