@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.
- package/README.md +13 -0
- package/controllers/file-manager.controller.d.ts +1 -0
- package/controllers/folder.controller.d.ts +1 -0
- package/controllers/storage-config.controller.d.ts +1 -0
- package/fesm/493.js +416 -251
- package/fesm/537.js +25 -21
- package/fesm/562.js +184 -172
- package/fesm/chunks/190.js +6 -6
- package/fesm/chunks/252.js +1 -1
- package/fesm/chunks/327.js +1 -1
- package/fesm/chunks/385.js +1 -1
- package/fesm/chunks/591.js +11 -11
- package/fesm/chunks/746.js +1 -1
- package/fesm/chunks/798.js +1 -1
- package/fesm/chunks/918.js +19 -7
- package/fesm/config/index.js +8 -8
- package/fesm/controllers/index.js +1 -1
- package/fesm/docs/index.js +11 -15
- package/fesm/dtos/index.js +24 -20
- package/fesm/entities/index.js +6 -6
- package/fesm/enums/index.js +4 -4
- package/fesm/index.js +30 -34
- package/fesm/interfaces/index.js +2 -2
- package/fesm/modules/index.js +1 -1
- package/fesm/providers/index.js +123 -129
- package/fesm/services/index.js +1 -1
- package/fesm/utils/index.js +88 -84
- package/middlewares/file-serve.middleware.d.ts +3 -1
- package/package.json +3 -3
- package/providers/local-provider.d.ts +2 -0
- package/providers/sftp-provider.optional.d.ts +1 -0
- package/providers/storage-factory.service.d.ts +4 -2
- package/services/file-manager.service.d.ts +5 -6
- package/services/folder.service.d.ts +5 -5
- package/services/storage-provider-config.service.d.ts +5 -2
- package/services/upload.service.d.ts +3 -1
- package/utils/company-ownership.util.d.ts +3 -0
- package/utils/file-validator.util.d.ts +1 -0
package/fesm/493.js
CHANGED
|
@@ -8,13 +8,14 @@ import * as __rspack_external__nestjs_common_a04939da from "@nestjs/common";
|
|
|
8
8
|
import * as __rspack_external__nestjs_swagger_7cd450b5 from "@nestjs/swagger";
|
|
9
9
|
import * as __rspack_external_class_transformer_c5a479fb from "class-transformer";
|
|
10
10
|
import * as __rspack_external_class_validator_7b99ef4d from "class-validator";
|
|
11
|
+
import * as __rspack_external_path from "path";
|
|
11
12
|
import * as __rspack_external_typeorm from "typeorm";
|
|
12
13
|
import * as __rspack_external__nestjs_core_d7b00a1a from "@nestjs/core";
|
|
13
14
|
import * as __rspack_external_crypto from "crypto";
|
|
14
15
|
export const __rspack_esm_id = 493;
|
|
15
16
|
export const __rspack_esm_ids = [493];
|
|
16
17
|
export const __webpack_modules__ = {
|
|
17
|
-
|
|
18
|
+
4884(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
18
19
|
/**
|
|
19
20
|
* Domain event actions published by the storage module, alongside the CRUD
|
|
20
21
|
* lifecycle actions every ApiService emits.
|
|
@@ -38,7 +39,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
},
|
|
41
|
-
|
|
42
|
+
5450(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
42
43
|
// ==================== STORAGE MODULE MESSAGE KEYS ====================
|
|
43
44
|
const FILE_MESSAGES = {
|
|
44
45
|
GET_ALL_SUCCESS: 'file.get.all.success',
|
|
@@ -72,7 +73,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
72
73
|
|
|
73
74
|
|
|
74
75
|
},
|
|
75
|
-
|
|
76
|
+
9188(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
76
77
|
/**
|
|
77
78
|
* Storage Module Constants
|
|
78
79
|
*/ const STORAGE_MODULE_OPTIONS = 'STORAGE_MODULE_OPTIONS';
|
|
@@ -90,10 +91,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
90
91
|
|
|
91
92
|
|
|
92
93
|
},
|
|
93
|
-
|
|
94
|
-
/* import */ var _nestjs_swagger__rspack_import_0 = __webpack_require__(
|
|
95
|
-
/* import */ var class_transformer__rspack_import_1 = __webpack_require__(
|
|
96
|
-
/* import */ var class_validator__rspack_import_2 = __webpack_require__(
|
|
94
|
+
7322(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
95
|
+
/* import */ var _nestjs_swagger__rspack_import_0 = __webpack_require__(6176);
|
|
96
|
+
/* import */ var class_transformer__rspack_import_1 = __webpack_require__(5812);
|
|
97
|
+
/* import */ var class_validator__rspack_import_2 = __webpack_require__(5421);
|
|
97
98
|
function _ts_decorate(decorators, target, key, desc) {
|
|
98
99
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
99
100
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -266,7 +267,7 @@ _ts_decorate([
|
|
|
266
267
|
default: true
|
|
267
268
|
}),
|
|
268
269
|
(0,class_validator__rspack_import_2.IsOptional)(),
|
|
269
|
-
(0,class_transformer__rspack_import_1.
|
|
270
|
+
(0,class_transformer__rspack_import_1.Transform)(({ value })=>value === 'true' ? true : value === 'false' ? false : value),
|
|
270
271
|
(0,class_validator__rspack_import_2.IsBoolean)(),
|
|
271
272
|
_ts_metadata("design:type", Boolean)
|
|
272
273
|
], UploadOptionsDto.prototype, "compress", void 0);
|
|
@@ -338,7 +339,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
338
339
|
|
|
339
340
|
|
|
340
341
|
},
|
|
341
|
-
|
|
342
|
+
1975(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
342
343
|
|
|
343
344
|
// EXPORTS
|
|
344
345
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -359,7 +360,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
359
360
|
;// CONCATENATED MODULE: external "@flusys/nestjs-shared/entities"
|
|
360
361
|
|
|
361
362
|
// EXTERNAL MODULE: external "typeorm"
|
|
362
|
-
var external_typeorm_ = __webpack_require__(
|
|
363
|
+
var external_typeorm_ = __webpack_require__(7158);
|
|
363
364
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/entities/file-manager.entity.ts
|
|
364
365
|
function _ts_decorate(decorators, target, key, desc) {
|
|
365
366
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -530,7 +531,7 @@ Folder = folder_entity_ts_decorate([
|
|
|
530
531
|
], Folder);
|
|
531
532
|
|
|
532
533
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared"
|
|
533
|
-
var nestjs_shared_ = __webpack_require__(
|
|
534
|
+
var nestjs_shared_ = __webpack_require__(3422);
|
|
534
535
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/entities/storage-config.entity.ts
|
|
535
536
|
function storage_config_entity_ts_decorate(decorators, target, key, desc) {
|
|
536
537
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -779,7 +780,7 @@ function getStorageEntitiesByConfig(enableCompanyFeature) {
|
|
|
779
780
|
|
|
780
781
|
|
|
781
782
|
},
|
|
782
|
-
|
|
783
|
+
2733(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
783
784
|
var FileLocationEnum = /*#__PURE__*/ function(FileLocationEnum) {
|
|
784
785
|
FileLocationEnum["AWS"] = "aws";
|
|
785
786
|
FileLocationEnum["AZURE"] = "azure";
|
|
@@ -794,7 +795,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
794
795
|
|
|
795
796
|
|
|
796
797
|
},
|
|
797
|
-
|
|
798
|
+
2192(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
798
799
|
|
|
799
800
|
// EXPORTS
|
|
800
801
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -802,15 +803,15 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
802
803
|
});
|
|
803
804
|
|
|
804
805
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared/constants"
|
|
805
|
-
var constants_ = __webpack_require__(
|
|
806
|
+
var constants_ = __webpack_require__(9140);
|
|
806
807
|
// EXTERNAL MODULE: external "@nestjs/common"
|
|
807
|
-
var common_ = __webpack_require__(
|
|
808
|
+
var common_ = __webpack_require__(6157);
|
|
808
809
|
;// CONCATENATED MODULE: external "crypto"
|
|
809
810
|
|
|
810
811
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/services/index.ts
|
|
811
|
-
var services = __webpack_require__(
|
|
812
|
+
var services = __webpack_require__(4148);
|
|
812
813
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/providers/storage-provider.registry.ts
|
|
813
|
-
var storage_provider_registry = __webpack_require__(
|
|
814
|
+
var storage_provider_registry = __webpack_require__(9264);
|
|
814
815
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/providers/storage-factory.service.ts
|
|
815
816
|
function _ts_decorate(decorators, target, key, desc) {
|
|
816
817
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -840,6 +841,8 @@ function _ts_param(paramIndex, decorator) {
|
|
|
840
841
|
|
|
841
842
|
|
|
842
843
|
|
|
844
|
+
const MAX_CACHED_PROVIDERS = 50;
|
|
845
|
+
const PROVIDER_IDLE_TTL_MS = 30 * 60 * 1000;
|
|
843
846
|
class StorageFactoryService {
|
|
844
847
|
configService;
|
|
845
848
|
cache = new Map();
|
|
@@ -848,8 +851,14 @@ class StorageFactoryService {
|
|
|
848
851
|
}
|
|
849
852
|
async createProvider(config) {
|
|
850
853
|
const cacheKey = this.generateCacheKey(config);
|
|
854
|
+
const now = Date.now();
|
|
851
855
|
const cached = this.cache.get(cacheKey);
|
|
852
|
-
if (cached)
|
|
856
|
+
if (cached) {
|
|
857
|
+
cached.lastUsed = now;
|
|
858
|
+
this.cache.delete(cacheKey);
|
|
859
|
+
this.cache.set(cacheKey, cached);
|
|
860
|
+
return cached.provider;
|
|
861
|
+
}
|
|
853
862
|
const ProviderClass = storage_provider_registry/* .StorageProviderRegistry.get */.C.get(config.provider);
|
|
854
863
|
if (!ProviderClass) {
|
|
855
864
|
throw new common_.NotFoundException({
|
|
@@ -861,10 +870,37 @@ class StorageFactoryService {
|
|
|
861
870
|
}
|
|
862
871
|
});
|
|
863
872
|
}
|
|
873
|
+
// The pending promise is cached so concurrent first requests share one client instead of leaking extras
|
|
874
|
+
const entry = {
|
|
875
|
+
provider: this.instantiate(ProviderClass, config),
|
|
876
|
+
lastUsed: now
|
|
877
|
+
};
|
|
878
|
+
this.cache.set(cacheKey, entry);
|
|
879
|
+
entry.provider.catch(()=>{
|
|
880
|
+
if (this.cache.get(cacheKey) === entry) this.cache.delete(cacheKey);
|
|
881
|
+
});
|
|
882
|
+
this.evict(now);
|
|
883
|
+
return entry.provider;
|
|
884
|
+
}
|
|
885
|
+
/** A provider that needs no configuration; never one created for a specific StorageConfig row */ async getProvider(providerName) {
|
|
886
|
+
return this.createProvider({
|
|
887
|
+
provider: providerName,
|
|
888
|
+
config: {}
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
async clearCache() {
|
|
892
|
+
const entries = Array.from(this.cache.values());
|
|
893
|
+
this.cache.clear();
|
|
894
|
+
await Promise.allSettled(entries.map((entry)=>this.closeEntry(entry)));
|
|
895
|
+
}
|
|
896
|
+
async onModuleDestroy() {
|
|
897
|
+
await this.clearCache();
|
|
898
|
+
}
|
|
899
|
+
// ─── Private Helpers ──────────────────────────────────────────────────────────
|
|
900
|
+
async instantiate(ProviderClass, config) {
|
|
864
901
|
try {
|
|
865
902
|
const instance = new ProviderClass();
|
|
866
903
|
await this.initializeProvider(instance, config);
|
|
867
|
-
this.cache.set(cacheKey, instance);
|
|
868
904
|
return instance;
|
|
869
905
|
} catch (error) {
|
|
870
906
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -878,32 +914,25 @@ class StorageFactoryService {
|
|
|
878
914
|
});
|
|
879
915
|
}
|
|
880
916
|
}
|
|
881
|
-
|
|
882
|
-
const
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
getLocalProviderBasePath() {
|
|
890
|
-
const localKey = Array.from(this.cache.keys()).find((k)=>k.startsWith('local'));
|
|
891
|
-
const provider = localKey ? this.cache.get(localKey) : null;
|
|
892
|
-
return provider && 'basePath' in provider ? provider.basePath : null;
|
|
893
|
-
}
|
|
894
|
-
clearCache() {
|
|
895
|
-
this.cache.clear();
|
|
917
|
+
evict(now) {
|
|
918
|
+
for (const [key, entry] of this.cache){
|
|
919
|
+
const overCapacity = this.cache.size > MAX_CACHED_PROVIDERS;
|
|
920
|
+
if (!overCapacity && now - entry.lastUsed < PROVIDER_IDLE_TTL_MS) continue;
|
|
921
|
+
this.cache.delete(key);
|
|
922
|
+
void this.closeEntry(entry);
|
|
923
|
+
}
|
|
896
924
|
}
|
|
897
|
-
async
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
925
|
+
async closeEntry(entry) {
|
|
926
|
+
try {
|
|
927
|
+
const provider = await entry.provider;
|
|
928
|
+
if (typeof provider.close === 'function') await provider.close();
|
|
929
|
+
} catch {
|
|
930
|
+
// A client that failed to initialize or to close has nothing left to release
|
|
931
|
+
}
|
|
901
932
|
}
|
|
902
|
-
// ─── Private Helpers ──────────────────────────────────────────────────────────
|
|
903
933
|
generateCacheKey(config) {
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
return `${config.provider}-${hash}`;
|
|
934
|
+
const hash = __rspack_external_crypto.createHash('sha256').update(stableStringify(config.config ?? {})).digest('hex');
|
|
935
|
+
return `${config.provider}:${hash}`;
|
|
907
936
|
}
|
|
908
937
|
async initializeProvider(instance, config) {
|
|
909
938
|
if (!('initialize' in instance) || typeof instance.initialize !== 'function') {
|
|
@@ -931,10 +960,18 @@ StorageFactoryService = _ts_decorate([
|
|
|
931
960
|
typeof services/* .StorageConfigService */.tP === "undefined" ? Object : services/* .StorageConfigService */.tP
|
|
932
961
|
])
|
|
933
962
|
], StorageFactoryService);
|
|
963
|
+
/** Key order never changes the key, and nested values always do - two configs must never share a client */ function stableStringify(value) {
|
|
964
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;
|
|
965
|
+
if (value && typeof value === 'object') {
|
|
966
|
+
const entries = Object.keys(value).toSorted().map((key)=>`${JSON.stringify(key)}:${stableStringify(value[key])}`);
|
|
967
|
+
return `{${entries.join(',')}}`;
|
|
968
|
+
}
|
|
969
|
+
return JSON.stringify(value) ?? 'undefined';
|
|
970
|
+
}
|
|
934
971
|
|
|
935
972
|
|
|
936
973
|
},
|
|
937
|
-
|
|
974
|
+
9264(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
938
975
|
/**
|
|
939
976
|
* Static registry for storage provider classes
|
|
940
977
|
* Allows dynamic registration at runtime
|
|
@@ -963,22 +1000,23 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
963
1000
|
|
|
964
1001
|
|
|
965
1002
|
},
|
|
966
|
-
|
|
1003
|
+
7955(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
967
1004
|
__webpack_require__.d(__webpack_exports__, {
|
|
968
1005
|
D: () => (FileManagerService)
|
|
969
1006
|
});
|
|
970
|
-
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(
|
|
971
|
-
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(
|
|
972
|
-
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(
|
|
973
|
-
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(
|
|
974
|
-
/* import */ var typeorm__rspack_import_4 = __webpack_require__(
|
|
975
|
-
/* import */ var
|
|
976
|
-
/* import */ var
|
|
977
|
-
/* import */ var _entities_index_js__rspack_import_5 = __webpack_require__(
|
|
978
|
-
/* import */ var
|
|
979
|
-
/* import */ var
|
|
980
|
-
/* import */ var
|
|
981
|
-
/* import */ var
|
|
1007
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
1008
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
1009
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(9216);
|
|
1010
|
+
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(6157);
|
|
1011
|
+
/* import */ var typeorm__rspack_import_4 = __webpack_require__(7158);
|
|
1012
|
+
/* import */ var _config_index_js__rspack_import_10 = __webpack_require__(4884);
|
|
1013
|
+
/* import */ var _config_index_js__rspack_import_11 = __webpack_require__(5450);
|
|
1014
|
+
/* import */ var _entities_index_js__rspack_import_5 = __webpack_require__(1975);
|
|
1015
|
+
/* import */ var _enums_file_location_enum_js__rspack_import_12 = __webpack_require__(2733);
|
|
1016
|
+
/* import */ var _utils_company_ownership_util_js__rspack_import_6 = __webpack_require__(5198);
|
|
1017
|
+
/* import */ var _storage_config_service_js__rspack_import_7 = __webpack_require__(6397);
|
|
1018
|
+
/* import */ var _storage_datasource_provider_js__rspack_import_8 = __webpack_require__(8616);
|
|
1019
|
+
/* import */ var _upload_service_js__rspack_import_9 = __webpack_require__(5018);
|
|
982
1020
|
function _ts_decorate(decorators, target, key, desc) {
|
|
983
1021
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
984
1022
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1013,6 +1051,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
1013
1051
|
|
|
1014
1052
|
|
|
1015
1053
|
|
|
1054
|
+
|
|
1016
1055
|
const URL_EXPIRY_SECONDS = 3600;
|
|
1017
1056
|
const DEFAULT_SELECT_FIELDS = [
|
|
1018
1057
|
'id',
|
|
@@ -1035,9 +1074,15 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1035
1074
|
dataSourceProvider;
|
|
1036
1075
|
permissionCacheService;
|
|
1037
1076
|
constructor(cacheManager, utilsService, uploadService, storageConfig, dataSourceProvider, permissionCacheService){
|
|
1038
|
-
super(
|
|
1077
|
+
super(_config_index_js__rspack_import_10/* .STORAGE_EVENT_ENTITIES.FILE */.fR.FILE, cacheManager, utilsService, FileManagerService.name, true, _config_index_js__rspack_import_10/* .STORAGE_EVENT_MODULE */.qh, dataSourceProvider, storageConfig.isCompanyFeatureEnabled() ? _entities_index_js__rspack_import_5.FileManagerWithCompany : _entities_index_js__rspack_import_5.FileManager), this.cacheManager = cacheManager, this.utilsService = utilsService, this.uploadService = uploadService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider, this.permissionCacheService = permissionCacheService;
|
|
1039
1078
|
}
|
|
1040
1079
|
// ─── Override Methods ───────────────────────────────────────────────────────
|
|
1080
|
+
/** Cached reads join the folder (id, name), and a hard folder delete nulls file.folder_id */ cacheDependencies() {
|
|
1081
|
+
return [
|
|
1082
|
+
this.entityName,
|
|
1083
|
+
_config_index_js__rspack_import_10/* .STORAGE_EVENT_ENTITIES.FOLDER */.fR.FOLDER
|
|
1084
|
+
];
|
|
1085
|
+
}
|
|
1041
1086
|
async convertSingleDtoToEntity(dto, user) {
|
|
1042
1087
|
let entity = {};
|
|
1043
1088
|
if ('id' in dto && dto.id && typeof dto.id === 'string') {
|
|
@@ -1048,30 +1093,36 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1048
1093
|
});
|
|
1049
1094
|
if (!existing) throw new _nestjs_common__rspack_import_3.NotFoundException({
|
|
1050
1095
|
message: 'Entity not found for update',
|
|
1051
|
-
messageKey:
|
|
1096
|
+
messageKey: _config_index_js__rspack_import_11/* .FILE_MESSAGES.NOT_FOUND */.uA.NOT_FOUND
|
|
1052
1097
|
});
|
|
1053
1098
|
entity = existing;
|
|
1054
1099
|
}
|
|
1055
|
-
const validatedFolder = dto.folderId ? await this.validateFolder(dto.folderId, user) : null;
|
|
1056
|
-
const storageLocation = await this.resolveStorageLocation(dto, user);
|
|
1057
1100
|
const merged = {
|
|
1058
1101
|
...entity,
|
|
1059
1102
|
...dto,
|
|
1060
|
-
location:
|
|
1061
|
-
folder: validatedFolder
|
|
1103
|
+
location: await this.resolveStorageLocation(dto, user, entity.location)
|
|
1062
1104
|
};
|
|
1105
|
+
// A partial update that leaves folderId out keeps the file where it is; null moves it to the root
|
|
1106
|
+
if (dto.folderId !== undefined || !entity.id) {
|
|
1107
|
+
merged.folder = dto.folderId ? await this.validateFolder(dto.folderId, user) : null;
|
|
1108
|
+
}
|
|
1063
1109
|
if (this.storageConfig.isCompanyFeatureEnabled()) {
|
|
1064
1110
|
merged.companyId = user?.companyId ?? null;
|
|
1065
1111
|
}
|
|
1066
1112
|
return merged;
|
|
1067
1113
|
}
|
|
1068
|
-
async getSelectQuery(query,
|
|
1114
|
+
/** Every read (get-all, get/:id, get-by-ids) is scoped here: company first, then private files */ async getSelectQuery(query, user, select) {
|
|
1069
1115
|
const fields = (select?.length ? select : DEFAULT_SELECT_FIELDS).map((f)=>`${this.entityName}.${f}`);
|
|
1070
1116
|
if (this.storageConfig.isCompanyFeatureEnabled()) {
|
|
1071
1117
|
fields.push('file_manager.companyId');
|
|
1072
1118
|
}
|
|
1073
1119
|
fields.push('folder.id', 'folder.name');
|
|
1074
1120
|
query.leftJoinAndSelect('file_manager.folder', 'folder').select(fields);
|
|
1121
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_2.applyCompanyFilter)(query, {
|
|
1122
|
+
isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
|
|
1123
|
+
entityAlias: 'file_manager'
|
|
1124
|
+
}, user);
|
|
1125
|
+
await this.applyPrivateFileFilter(query, user);
|
|
1075
1126
|
return {
|
|
1076
1127
|
query,
|
|
1077
1128
|
isRaw: false
|
|
@@ -1090,27 +1141,28 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1090
1141
|
isRaw: false
|
|
1091
1142
|
};
|
|
1092
1143
|
}
|
|
1093
|
-
async
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
}, user);
|
|
1099
|
-
await this.applyPrivateFileFilter(query, user);
|
|
1100
|
-
return result;
|
|
1144
|
+
async beforeUpdateOperation(dto, user) {
|
|
1145
|
+
const ids = (Array.isArray(dto) ? dto : [
|
|
1146
|
+
dto
|
|
1147
|
+
]).map((d)=>d.id).filter(Boolean);
|
|
1148
|
+
await this.assertInUserCompany(ids, user);
|
|
1101
1149
|
}
|
|
1102
1150
|
async beforeDeleteOperation(dto, user, _qr) {
|
|
1103
|
-
if (dto.type !== 'permanent') return;
|
|
1104
1151
|
const ids = Array.isArray(dto.id) ? dto.id : [
|
|
1105
1152
|
dto.id
|
|
1106
1153
|
];
|
|
1107
|
-
|
|
1108
|
-
|
|
1154
|
+
await this.assertInUserCompany(ids, user);
|
|
1155
|
+
if (dto.type !== 'permanent') return;
|
|
1156
|
+
const files = await this.repository.find({
|
|
1157
|
+
where: {
|
|
1158
|
+
id: (0,typeorm__rspack_import_4.In)(ids)
|
|
1159
|
+
},
|
|
1160
|
+
withDeleted: true
|
|
1109
1161
|
});
|
|
1110
1162
|
const grouped = this.groupFilesByConfig(files);
|
|
1111
1163
|
for (const [configId, { keys, location }] of grouped){
|
|
1112
1164
|
let deleteKeys = keys;
|
|
1113
|
-
if (location ===
|
|
1165
|
+
if (location === _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.LOCAL */.N.LOCAL && configId !== 'default') {
|
|
1114
1166
|
const basePath = await this.getStorageConfigBasePath(configId);
|
|
1115
1167
|
if (basePath) {
|
|
1116
1168
|
deleteKeys = keys.map((k)=>k.includes('/') ? k : `${basePath}/${k}`);
|
|
@@ -1125,7 +1177,7 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1125
1177
|
const ids = dtos.map((d)=>d.id).filter(Boolean);
|
|
1126
1178
|
if (!ids.length) throw new _nestjs_common__rspack_import_3.BadRequestException({
|
|
1127
1179
|
message: 'No valid file IDs provided',
|
|
1128
|
-
messageKey:
|
|
1180
|
+
messageKey: _config_index_js__rspack_import_11/* .UPLOAD_MESSAGES.NO_FILES_PROVIDED */.dS.NO_FILES_PROVIDED
|
|
1129
1181
|
});
|
|
1130
1182
|
const fetched = await this.repository.findBy({
|
|
1131
1183
|
id: (0,typeorm__rspack_import_4.In)(ids)
|
|
@@ -1141,28 +1193,25 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1141
1193
|
if (updatedFiles.length) {
|
|
1142
1194
|
try {
|
|
1143
1195
|
await this.repository.save(updatedFiles);
|
|
1144
|
-
await Promise.all([
|
|
1145
|
-
this.clearCacheForAll(),
|
|
1146
|
-
this.clearCacheForId(updatedFiles)
|
|
1147
|
-
]);
|
|
1148
1196
|
} catch {
|
|
1149
1197
|
// Silent failure - URL update is non-critical
|
|
1150
1198
|
}
|
|
1199
|
+
await this.invalidateCache();
|
|
1151
1200
|
}
|
|
1152
1201
|
return responses;
|
|
1153
1202
|
}
|
|
1154
1203
|
// ─── Private Helpers ────────────────────────────────────────────────────────
|
|
1155
1204
|
buildWhereWithCompany(id, user) {
|
|
1156
|
-
|
|
1205
|
+
return (0,_flusys_nestjs_shared_utils__rspack_import_2.buildCompanyWhereCondition)({
|
|
1157
1206
|
id
|
|
1158
|
-
};
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1207
|
+
}, this.storageConfig.isCompanyFeatureEnabled(), user);
|
|
1208
|
+
}
|
|
1209
|
+
async assertInUserCompany(ids, user) {
|
|
1210
|
+
await this.ensureDataSourceRepository();
|
|
1211
|
+
await (0,_utils_company_ownership_util_js__rspack_import_6/* .assertRowsInUserCompany */.p)(this.repository, ids, user, this.storageConfig.isCompanyFeatureEnabled(), 'File');
|
|
1163
1212
|
}
|
|
1164
1213
|
async getStorageConfigRepository() {
|
|
1165
|
-
const entity = this.storageConfig.isCompanyFeatureEnabled() ? (await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
1214
|
+
const entity = this.storageConfig.isCompanyFeatureEnabled() ? (await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 1975))).StorageConfigWithCompany : (await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 1975))).StorageConfig;
|
|
1166
1215
|
return this.dataSourceProvider.getRepository(entity);
|
|
1167
1216
|
}
|
|
1168
1217
|
async getStorageConfigBasePath(configId) {
|
|
@@ -1191,7 +1240,7 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1191
1240
|
if (!folder) {
|
|
1192
1241
|
throw new _nestjs_common__rspack_import_3.BadRequestException({
|
|
1193
1242
|
message: `Folder "${folderId}" not found or access denied`,
|
|
1194
|
-
messageKey:
|
|
1243
|
+
messageKey: _config_index_js__rspack_import_11/* .FOLDER_MESSAGES.NOT_FOUND */.Ee.NOT_FOUND,
|
|
1195
1244
|
messageVariables: {
|
|
1196
1245
|
folderId
|
|
1197
1246
|
}
|
|
@@ -1199,22 +1248,23 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1199
1248
|
}
|
|
1200
1249
|
return folder;
|
|
1201
1250
|
}
|
|
1202
|
-
async resolveStorageLocation(dto, user) {
|
|
1251
|
+
async resolveStorageLocation(dto, user, currentLocation) {
|
|
1252
|
+
const fallback = dto.location || currentLocation || _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.LOCAL */.N.LOCAL;
|
|
1203
1253
|
const configId = dto.storageConfigId;
|
|
1204
|
-
if (!configId) return
|
|
1254
|
+
if (!configId) return fallback;
|
|
1205
1255
|
try {
|
|
1206
1256
|
const repo = await this.getStorageConfigRepository();
|
|
1207
1257
|
const config = await repo.findOne({
|
|
1208
1258
|
where: this.buildWhereWithCompany(configId, user)
|
|
1209
1259
|
});
|
|
1210
|
-
return config?.storage ||
|
|
1260
|
+
return config?.storage || fallback;
|
|
1211
1261
|
} catch {
|
|
1212
|
-
return
|
|
1262
|
+
return fallback;
|
|
1213
1263
|
}
|
|
1214
1264
|
}
|
|
1215
1265
|
applyContentTypeFilter(query, value) {
|
|
1216
1266
|
const patterns = value.split(',').map((t)=>t.trim().replace('*', '%'));
|
|
1217
|
-
query.
|
|
1267
|
+
query.andWhere(new typeorm__rspack_import_4.Brackets((qb)=>{
|
|
1218
1268
|
patterns.forEach((p, i)=>{
|
|
1219
1269
|
const method = i === 0 ? 'where' : 'orWhere';
|
|
1220
1270
|
qb[method](`${this.entityName}.contentType LIKE :p${i}`, {
|
|
@@ -1230,8 +1280,8 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1230
1280
|
* for any file ID, including other companies' or other users' private files.
|
|
1231
1281
|
*/ async scopeFilesToRequester(files, user) {
|
|
1232
1282
|
let scoped = files;
|
|
1233
|
-
if (this.storageConfig.isCompanyFeatureEnabled() && user
|
|
1234
|
-
scoped = scoped.filter((file)=>file.companyId === user.companyId);
|
|
1283
|
+
if (this.storageConfig.isCompanyFeatureEnabled() && user) {
|
|
1284
|
+
scoped = user.companyId ? scoped.filter((file)=>file.companyId === user.companyId) : [];
|
|
1235
1285
|
}
|
|
1236
1286
|
const canViewPrivate = user ? await this.permissionCacheService.hasPermission({
|
|
1237
1287
|
userId: user.id,
|
|
@@ -1280,7 +1330,7 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1280
1330
|
return appUrl || `${protocol}://${host}`;
|
|
1281
1331
|
}
|
|
1282
1332
|
async refreshFileUrl(file, protocol, host, now, user) {
|
|
1283
|
-
const isCloudProvider = file.location ===
|
|
1333
|
+
const isCloudProvider = file.location === _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.AWS */.N.AWS || file.location === _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.AZURE */.N.AZURE;
|
|
1284
1334
|
const needsNewUrl = !file.url || isCloudProvider && (typeof file.expiresAt !== 'number' || now >= file.expiresAt);
|
|
1285
1335
|
if (needsNewUrl && file.storageConfigId) {
|
|
1286
1336
|
try {
|
|
@@ -1291,7 +1341,7 @@ class FileManagerService extends _flusys_nestjs_shared_classes__rspack_import_0.
|
|
|
1291
1341
|
file.url = `${this.getFileBaseUrl(protocol, host)}/storage/upload/file/${file.key}`;
|
|
1292
1342
|
}
|
|
1293
1343
|
}
|
|
1294
|
-
if (file.location ===
|
|
1344
|
+
if (file.location === _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.SFTP */.N.SFTP || file.location === _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.LOCAL */.N.LOCAL) {
|
|
1295
1345
|
let fileKey = file.key;
|
|
1296
1346
|
if (!fileKey.includes('/') && file.storageConfigId) {
|
|
1297
1347
|
const basePath = await this.getStorageConfigBasePath(file.storageConfigId);
|
|
@@ -1322,32 +1372,33 @@ FileManagerService = _ts_decorate([
|
|
|
1322
1372
|
}),
|
|
1323
1373
|
_ts_param(0, (0,_nestjs_common__rspack_import_3.Inject)('CACHE_INSTANCE')),
|
|
1324
1374
|
_ts_param(1, (0,_nestjs_common__rspack_import_3.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
1325
|
-
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1326
|
-
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1327
|
-
_ts_param(4, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1375
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(_upload_service_js__rspack_import_9/* .UploadService */.B)),
|
|
1376
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(_storage_config_service_js__rspack_import_7/* .StorageConfigService */.t)),
|
|
1377
|
+
_ts_param(4, (0,_nestjs_common__rspack_import_3.Inject)(_storage_datasource_provider_js__rspack_import_8/* .StorageDataSourceProvider */.M)),
|
|
1328
1378
|
_ts_param(5, (0,_nestjs_common__rspack_import_3.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.SharedPermissionCacheService)),
|
|
1329
1379
|
_ts_metadata("design:type", Function),
|
|
1330
1380
|
_ts_metadata("design:paramtypes", [
|
|
1331
1381
|
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
1332
1382
|
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService,
|
|
1333
|
-
typeof
|
|
1334
|
-
typeof
|
|
1335
|
-
typeof
|
|
1383
|
+
typeof _upload_service_js__rspack_import_9/* .UploadService */.B === "undefined" ? Object : _upload_service_js__rspack_import_9/* .UploadService */.B,
|
|
1384
|
+
typeof _storage_config_service_js__rspack_import_7/* .StorageConfigService */.t === "undefined" ? Object : _storage_config_service_js__rspack_import_7/* .StorageConfigService */.t,
|
|
1385
|
+
typeof _storage_datasource_provider_js__rspack_import_8/* .StorageDataSourceProvider */.M === "undefined" ? Object : _storage_datasource_provider_js__rspack_import_8/* .StorageDataSourceProvider */.M,
|
|
1336
1386
|
typeof _flusys_nestjs_shared_modules__rspack_import_1.SharedPermissionCacheService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.SharedPermissionCacheService
|
|
1337
1387
|
])
|
|
1338
1388
|
], FileManagerService);
|
|
1339
1389
|
|
|
1340
1390
|
|
|
1341
1391
|
},
|
|
1342
|
-
|
|
1343
|
-
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(
|
|
1344
|
-
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(
|
|
1345
|
-
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(
|
|
1346
|
-
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(
|
|
1347
|
-
/* import */ var
|
|
1348
|
-
/* import */ var _entities_index_js__rspack_import_4 = __webpack_require__(
|
|
1349
|
-
/* import */ var
|
|
1350
|
-
/* import */ var
|
|
1392
|
+
8195(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1393
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
1394
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
1395
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(9216);
|
|
1396
|
+
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(6157);
|
|
1397
|
+
/* import */ var _config_index_js__rspack_import_8 = __webpack_require__(4884);
|
|
1398
|
+
/* import */ var _entities_index_js__rspack_import_4 = __webpack_require__(1975);
|
|
1399
|
+
/* import */ var _utils_company_ownership_util_js__rspack_import_5 = __webpack_require__(5198);
|
|
1400
|
+
/* import */ var _storage_config_service_js__rspack_import_6 = __webpack_require__(6397);
|
|
1401
|
+
/* import */ var _storage_datasource_provider_js__rspack_import_7 = __webpack_require__(8616);
|
|
1351
1402
|
function _ts_decorate(decorators, target, key, desc) {
|
|
1352
1403
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1353
1404
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1379,12 +1430,13 @@ function _ts_param(paramIndex, decorator) {
|
|
|
1379
1430
|
|
|
1380
1431
|
|
|
1381
1432
|
|
|
1433
|
+
|
|
1382
1434
|
class FolderService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiService {
|
|
1383
1435
|
cacheManager;
|
|
1384
1436
|
utilsService;
|
|
1385
1437
|
storageConfig;
|
|
1386
1438
|
constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
|
|
1387
|
-
super(
|
|
1439
|
+
super(_config_index_js__rspack_import_8/* .STORAGE_EVENT_ENTITIES.FOLDER */.fR.FOLDER, cacheManager, utilsService, FolderService.name, true, _config_index_js__rspack_import_8/* .STORAGE_EVENT_MODULE */.qh, dataSourceProvider, storageConfig.isCompanyFeatureEnabled() ? _entities_index_js__rspack_import_4.FolderWithCompany : _entities_index_js__rspack_import_4.Folder), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
|
|
1388
1440
|
}
|
|
1389
1441
|
// ─── Override Methods ───────────────────────────────────────────────────────
|
|
1390
1442
|
async convertSingleDtoToEntity(dto, user) {
|
|
@@ -1394,7 +1446,7 @@ class FolderService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiSe
|
|
|
1394
1446
|
}
|
|
1395
1447
|
return entity;
|
|
1396
1448
|
}
|
|
1397
|
-
async getSelectQuery(query,
|
|
1449
|
+
async getSelectQuery(query, user, select) {
|
|
1398
1450
|
if (!select?.length) {
|
|
1399
1451
|
select = [
|
|
1400
1452
|
'id',
|
|
@@ -1408,18 +1460,28 @@ class FolderService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiSe
|
|
|
1408
1460
|
}
|
|
1409
1461
|
}
|
|
1410
1462
|
query.select(select.map((f)=>`${this.entityName}.${f}`));
|
|
1463
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_2.applyCompanyFilter)(query, {
|
|
1464
|
+
isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
|
|
1465
|
+
entityAlias: 'folder'
|
|
1466
|
+
}, user);
|
|
1411
1467
|
return {
|
|
1412
1468
|
query,
|
|
1413
1469
|
isRaw: false
|
|
1414
1470
|
};
|
|
1415
1471
|
}
|
|
1416
|
-
async
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1472
|
+
async beforeUpdateOperation(dto, user) {
|
|
1473
|
+
await this.assertInUserCompany((Array.isArray(dto) ? dto : [
|
|
1474
|
+
dto
|
|
1475
|
+
]).map((d)=>d.id), user);
|
|
1476
|
+
}
|
|
1477
|
+
async beforeDeleteOperation(dto, user) {
|
|
1478
|
+
await this.assertInUserCompany(Array.isArray(dto.id) ? dto.id : [
|
|
1479
|
+
dto.id
|
|
1480
|
+
], user);
|
|
1481
|
+
}
|
|
1482
|
+
async assertInUserCompany(ids, user) {
|
|
1483
|
+
await this.ensureDataSourceRepository();
|
|
1484
|
+
await (0,_utils_company_ownership_util_js__rspack_import_5/* .assertRowsInUserCompany */.p)(this.repository, ids.filter(Boolean), user, this.storageConfig.isCompanyFeatureEnabled(), 'Folder');
|
|
1423
1485
|
}
|
|
1424
1486
|
}
|
|
1425
1487
|
FolderService = _ts_decorate([
|
|
@@ -1428,14 +1490,14 @@ FolderService = _ts_decorate([
|
|
|
1428
1490
|
}),
|
|
1429
1491
|
_ts_param(0, (0,_nestjs_common__rspack_import_3.Inject)('CACHE_INSTANCE')),
|
|
1430
1492
|
_ts_param(1, (0,_nestjs_common__rspack_import_3.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
1431
|
-
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1432
|
-
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1493
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(_storage_config_service_js__rspack_import_6/* .StorageConfigService */.t)),
|
|
1494
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(_storage_datasource_provider_js__rspack_import_7/* .StorageDataSourceProvider */.M)),
|
|
1433
1495
|
_ts_metadata("design:type", Function),
|
|
1434
1496
|
_ts_metadata("design:paramtypes", [
|
|
1435
1497
|
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
1436
1498
|
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService,
|
|
1437
|
-
typeof
|
|
1438
|
-
typeof
|
|
1499
|
+
typeof _storage_config_service_js__rspack_import_6/* .StorageConfigService */.t === "undefined" ? Object : _storage_config_service_js__rspack_import_6/* .StorageConfigService */.t,
|
|
1500
|
+
typeof _storage_datasource_provider_js__rspack_import_7/* .StorageDataSourceProvider */.M === "undefined" ? Object : _storage_datasource_provider_js__rspack_import_7/* .StorageDataSourceProvider */.M
|
|
1439
1501
|
])
|
|
1440
1502
|
], FolderService);
|
|
1441
1503
|
|
|
@@ -1445,7 +1507,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1445
1507
|
|
|
1446
1508
|
|
|
1447
1509
|
},
|
|
1448
|
-
|
|
1510
|
+
4148(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1449
1511
|
__webpack_require__.d(__webpack_exports__, {
|
|
1450
1512
|
BB: () => (/* reexport safe */ _upload_service_js__rspack_import_5.B),
|
|
1451
1513
|
DL: () => (/* reexport safe */ _file_manager_service_js__rspack_import_0.D),
|
|
@@ -1454,12 +1516,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1454
1516
|
ol: () => (/* reexport safe */ _storage_provider_config_service_js__rspack_import_3.o),
|
|
1455
1517
|
tP: () => (/* reexport safe */ _storage_config_service_js__rspack_import_2.t)
|
|
1456
1518
|
});
|
|
1457
|
-
/* import */ var _file_manager_service_js__rspack_import_0 = __webpack_require__(
|
|
1458
|
-
/* import */ var _folder_service_js__rspack_import_1 = __webpack_require__(
|
|
1459
|
-
/* import */ var _storage_config_service_js__rspack_import_2 = __webpack_require__(
|
|
1460
|
-
/* import */ var _storage_provider_config_service_js__rspack_import_3 = __webpack_require__(
|
|
1461
|
-
/* import */ var _storage_datasource_provider_js__rspack_import_4 = __webpack_require__(
|
|
1462
|
-
/* import */ var _upload_service_js__rspack_import_5 = __webpack_require__(
|
|
1519
|
+
/* import */ var _file_manager_service_js__rspack_import_0 = __webpack_require__(7955);
|
|
1520
|
+
/* import */ var _folder_service_js__rspack_import_1 = __webpack_require__(8195);
|
|
1521
|
+
/* import */ var _storage_config_service_js__rspack_import_2 = __webpack_require__(6397);
|
|
1522
|
+
/* import */ var _storage_provider_config_service_js__rspack_import_3 = __webpack_require__(8623);
|
|
1523
|
+
/* import */ var _storage_datasource_provider_js__rspack_import_4 = __webpack_require__(8616);
|
|
1524
|
+
/* import */ var _upload_service_js__rspack_import_5 = __webpack_require__(5018);
|
|
1463
1525
|
|
|
1464
1526
|
|
|
1465
1527
|
|
|
@@ -1469,10 +1531,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1469
1531
|
|
|
1470
1532
|
|
|
1471
1533
|
},
|
|
1472
|
-
|
|
1473
|
-
/* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(
|
|
1474
|
-
/* import */ var _config_index_js__rspack_import_2 = __webpack_require__(
|
|
1475
|
-
/* import */ var _config_storage_constants_js__rspack_import_1 = __webpack_require__(
|
|
1534
|
+
6397(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1535
|
+
/* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(6157);
|
|
1536
|
+
/* import */ var _config_index_js__rspack_import_2 = __webpack_require__(5450);
|
|
1537
|
+
/* import */ var _config_storage_constants_js__rspack_import_1 = __webpack_require__(9188);
|
|
1476
1538
|
function _ts_decorate(decorators, target, key, desc) {
|
|
1477
1539
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1478
1540
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1539,7 +1601,7 @@ class StorageConfigService {
|
|
|
1539
1601
|
if (allowedTypes.includes('*/*')) {
|
|
1540
1602
|
return true;
|
|
1541
1603
|
}
|
|
1542
|
-
return allowedTypes.some((type)=>type.endsWith('/*') ? mimeType.startsWith(type.slice(0, -
|
|
1604
|
+
return allowedTypes.some((type)=>type.endsWith('/*') ? mimeType.startsWith(type.slice(0, -1)) : type === mimeType);
|
|
1543
1605
|
}
|
|
1544
1606
|
validateFileSize(fileSize) {
|
|
1545
1607
|
const maxSize = this.getMaxFileSize();
|
|
@@ -1594,7 +1656,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1594
1656
|
|
|
1595
1657
|
|
|
1596
1658
|
},
|
|
1597
|
-
|
|
1659
|
+
8616(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1598
1660
|
|
|
1599
1661
|
// EXPORTS
|
|
1600
1662
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -1602,13 +1664,13 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1602
1664
|
});
|
|
1603
1665
|
|
|
1604
1666
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared/modules"
|
|
1605
|
-
var modules_ = __webpack_require__(
|
|
1667
|
+
var modules_ = __webpack_require__(1236);
|
|
1606
1668
|
// EXTERNAL MODULE: external "@nestjs/common"
|
|
1607
|
-
var common_ = __webpack_require__(
|
|
1669
|
+
var common_ = __webpack_require__(6157);
|
|
1608
1670
|
;// CONCATENATED MODULE: external "@nestjs/core"
|
|
1609
1671
|
|
|
1610
1672
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/services/storage-config.service.ts
|
|
1611
|
-
var storage_config_service = __webpack_require__(
|
|
1673
|
+
var storage_config_service = __webpack_require__(6397);
|
|
1612
1674
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/services/storage-datasource.provider.ts
|
|
1613
1675
|
function _ts_decorate(decorators, target, key, desc) {
|
|
1614
1676
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -1661,7 +1723,7 @@ class StorageDataSourceProvider extends modules_.MultiTenantDataSourceService {
|
|
|
1661
1723
|
}
|
|
1662
1724
|
async getStorageEntities(enableCompanyFeature) {
|
|
1663
1725
|
const enable = enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
|
|
1664
|
-
const entities = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
1726
|
+
const entities = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 1975));
|
|
1665
1727
|
return enable ? [
|
|
1666
1728
|
entities.FileManagerWithCompany,
|
|
1667
1729
|
entities.FolderWithCompany,
|
|
@@ -1695,17 +1757,20 @@ StorageDataSourceProvider = _ts_decorate([
|
|
|
1695
1757
|
|
|
1696
1758
|
|
|
1697
1759
|
},
|
|
1698
|
-
|
|
1699
|
-
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(
|
|
1700
|
-
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(
|
|
1701
|
-
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(
|
|
1702
|
-
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(
|
|
1703
|
-
/* import */ var
|
|
1704
|
-
/* import */ var
|
|
1705
|
-
/* import */ var
|
|
1706
|
-
/* import */ var
|
|
1707
|
-
/* import */ var
|
|
1708
|
-
/* import */ var
|
|
1760
|
+
8623(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1761
|
+
/* import */ var _flusys_nestjs_shared_classes__rspack_import_0 = __webpack_require__(6937);
|
|
1762
|
+
/* import */ var _flusys_nestjs_shared_modules__rspack_import_1 = __webpack_require__(1236);
|
|
1763
|
+
/* import */ var _flusys_nestjs_shared_utils__rspack_import_2 = __webpack_require__(9216);
|
|
1764
|
+
/* import */ var _nestjs_common__rspack_import_3 = __webpack_require__(6157);
|
|
1765
|
+
/* import */ var path__rspack_import_4 = __webpack_require__(2521);
|
|
1766
|
+
/* import */ var typeorm__rspack_import_5 = __webpack_require__(7158);
|
|
1767
|
+
/* import */ var _config_index_js__rspack_import_10 = __webpack_require__(4884);
|
|
1768
|
+
/* import */ var _config_index_js__rspack_import_11 = __webpack_require__(5450);
|
|
1769
|
+
/* import */ var _enums_file_location_enum_js__rspack_import_12 = __webpack_require__(2733);
|
|
1770
|
+
/* import */ var _entities_index_js__rspack_import_6 = __webpack_require__(1975);
|
|
1771
|
+
/* import */ var _utils_company_ownership_util_js__rspack_import_7 = __webpack_require__(5198);
|
|
1772
|
+
/* import */ var _storage_config_service_js__rspack_import_8 = __webpack_require__(6397);
|
|
1773
|
+
/* import */ var _storage_datasource_provider_js__rspack_import_9 = __webpack_require__(8616);
|
|
1709
1774
|
function _ts_decorate(decorators, target, key, desc) {
|
|
1710
1775
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1711
1776
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1738,30 +1803,39 @@ function _ts_param(paramIndex, decorator) {
|
|
|
1738
1803
|
|
|
1739
1804
|
|
|
1740
1805
|
|
|
1806
|
+
|
|
1807
|
+
|
|
1808
|
+
|
|
1741
1809
|
class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack_import_0.ApiService {
|
|
1742
1810
|
cacheManager;
|
|
1743
1811
|
utilsService;
|
|
1744
1812
|
storageConfig;
|
|
1745
1813
|
constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
|
|
1746
|
-
super(
|
|
1814
|
+
super(_config_index_js__rspack_import_10/* .STORAGE_EVENT_ENTITIES.STORAGE_CONFIG */.fR.STORAGE_CONFIG, cacheManager, utilsService, StorageProviderConfigService.name, // Rows carry provider credentials - keep them out of the shared cache
|
|
1815
|
+
false, _config_index_js__rspack_import_10/* .STORAGE_EVENT_MODULE */.qh, dataSourceProvider, storageConfig.isCompanyFeatureEnabled() ? _entities_index_js__rspack_import_6.StorageConfigWithCompany : _entities_index_js__rspack_import_6.StorageConfig), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
|
|
1816
|
+
}
|
|
1817
|
+
async beforeUpdateOperation(dto, user) {
|
|
1818
|
+
await this.assertInUserCompany((Array.isArray(dto) ? dto : [
|
|
1819
|
+
dto
|
|
1820
|
+
]).map((d)=>d.id), user);
|
|
1747
1821
|
}
|
|
1748
|
-
async beforeDeleteOperation(dto,
|
|
1822
|
+
async beforeDeleteOperation(dto, user, _queryRunner) {
|
|
1749
1823
|
const ids = Array.isArray(dto.id) ? dto.id : [
|
|
1750
1824
|
dto.id
|
|
1751
1825
|
];
|
|
1752
|
-
await this.
|
|
1826
|
+
await this.assertInUserCompany(ids, user);
|
|
1753
1827
|
const defaultConfigs = await this.repository.find({
|
|
1754
1828
|
where: {
|
|
1755
|
-
id: (0,
|
|
1829
|
+
id: (0,typeorm__rspack_import_5.In)(ids),
|
|
1756
1830
|
isDefault: true,
|
|
1757
|
-
deletedAt: (0,
|
|
1831
|
+
deletedAt: (0,typeorm__rspack_import_5.IsNull)()
|
|
1758
1832
|
}
|
|
1759
1833
|
});
|
|
1760
1834
|
if (defaultConfigs.length > 0) {
|
|
1761
1835
|
const names = defaultConfigs.map((c)=>c.name).join(', ');
|
|
1762
1836
|
throw new _nestjs_common__rspack_import_3.ForbiddenException({
|
|
1763
1837
|
message: `Cannot delete the default storage config(s): ${names}. Set another config as default first.`,
|
|
1764
|
-
messageKey:
|
|
1838
|
+
messageKey: _config_index_js__rspack_import_11/* .STORAGE_CONFIG_MESSAGES.DEFAULT_DELETE_FORBIDDEN */.Y8.DEFAULT_DELETE_FORBIDDEN,
|
|
1765
1839
|
messageVariables: {
|
|
1766
1840
|
names
|
|
1767
1841
|
}
|
|
@@ -1776,7 +1850,7 @@ class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack
|
|
|
1776
1850
|
}
|
|
1777
1851
|
return entity;
|
|
1778
1852
|
}
|
|
1779
|
-
async getSelectQuery(query,
|
|
1853
|
+
async getSelectQuery(query, user, select) {
|
|
1780
1854
|
if (!select?.length) {
|
|
1781
1855
|
select = [
|
|
1782
1856
|
'id',
|
|
@@ -1793,6 +1867,10 @@ class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack
|
|
|
1793
1867
|
}
|
|
1794
1868
|
}
|
|
1795
1869
|
query.select(select.map((f)=>`${this.entityName}.${f}`));
|
|
1870
|
+
(0,_flusys_nestjs_shared_utils__rspack_import_2.applyCompanyFilter)(query, {
|
|
1871
|
+
isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
|
|
1872
|
+
entityAlias: this.entityName
|
|
1873
|
+
}, user);
|
|
1796
1874
|
return {
|
|
1797
1875
|
query,
|
|
1798
1876
|
isRaw: false
|
|
@@ -1800,10 +1878,6 @@ class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack
|
|
|
1800
1878
|
}
|
|
1801
1879
|
async getExtraManipulateQuery(query, filterDto, user) {
|
|
1802
1880
|
const result = await super.getExtraManipulateQuery(query, filterDto, user);
|
|
1803
|
-
(0,_flusys_nestjs_shared_utils__rspack_import_2.applyCompanyFilter)(query, {
|
|
1804
|
-
isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
|
|
1805
|
-
entityAlias: 'storageConfig'
|
|
1806
|
-
}, user);
|
|
1807
1881
|
query.orderBy(`${this.entityName}.createdAt`, 'DESC');
|
|
1808
1882
|
return result;
|
|
1809
1883
|
}
|
|
@@ -1839,6 +1913,10 @@ class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack
|
|
|
1839
1913
|
}
|
|
1840
1914
|
});
|
|
1841
1915
|
}
|
|
1916
|
+
async assertInUserCompany(ids, user) {
|
|
1917
|
+
await this.ensureDataSourceRepository();
|
|
1918
|
+
await (0,_utils_company_ownership_util_js__rspack_import_7/* .assertRowsInUserCompany */.p)(this.repository, ids.filter(Boolean), user, this.storageConfig.isCompanyFeatureEnabled(), 'Storage configuration');
|
|
1919
|
+
}
|
|
1842
1920
|
async getConfigByType(storage, user) {
|
|
1843
1921
|
await this.ensureDataSourceRepository();
|
|
1844
1922
|
const where = (0,_flusys_nestjs_shared_utils__rspack_import_2.buildCompanyWhereCondition)({
|
|
@@ -1849,6 +1927,42 @@ class StorageProviderConfigService extends _flusys_nestjs_shared_classes__rspack
|
|
|
1849
1927
|
where
|
|
1850
1928
|
});
|
|
1851
1929
|
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Absolute storage roots of every active local config in the current tenant, resolved the way
|
|
1932
|
+
* LocalProvider resolves them. Cached under the storage-config stamp, which every config write
|
|
1933
|
+
* moves, so an edited or deactivated config stops being served on all instances.
|
|
1934
|
+
*/ async getActiveLocalBasePaths() {
|
|
1935
|
+
await this.ensureDataSourceRepository();
|
|
1936
|
+
const tenantId = this.cacheTenant();
|
|
1937
|
+
let cacheKey = null;
|
|
1938
|
+
try {
|
|
1939
|
+
const stamp = await this.utilsService.getCacheStamp(this.cacheManager, [
|
|
1940
|
+
this.entityName
|
|
1941
|
+
], tenantId);
|
|
1942
|
+
cacheKey = this.utilsService.getCacheKey(this.entityName, {
|
|
1943
|
+
localBasePaths: true
|
|
1944
|
+
}, undefined, tenantId, stamp);
|
|
1945
|
+
const cached = await this.cacheManager.get(cacheKey);
|
|
1946
|
+
if (cached) return cached;
|
|
1947
|
+
} catch {
|
|
1948
|
+
cacheKey = null;
|
|
1949
|
+
}
|
|
1950
|
+
const configs = await this.repository.find({
|
|
1951
|
+
where: {
|
|
1952
|
+
storage: _enums_file_location_enum_js__rspack_import_12/* .FileLocationEnum.LOCAL */.N.LOCAL,
|
|
1953
|
+
isActive: true
|
|
1954
|
+
},
|
|
1955
|
+
select: [
|
|
1956
|
+
'id',
|
|
1957
|
+
'config'
|
|
1958
|
+
]
|
|
1959
|
+
});
|
|
1960
|
+
const basePaths = [
|
|
1961
|
+
...new Set(configs.map((c)=>path__rspack_import_4.resolve(c.config?.basePath || './uploads')))
|
|
1962
|
+
];
|
|
1963
|
+
if (cacheKey) await this.cacheManager.set(cacheKey, basePaths).catch(()=>undefined);
|
|
1964
|
+
return basePaths;
|
|
1965
|
+
}
|
|
1852
1966
|
}
|
|
1853
1967
|
StorageProviderConfigService = _ts_decorate([
|
|
1854
1968
|
(0,_nestjs_common__rspack_import_3.Injectable)({
|
|
@@ -1856,14 +1970,14 @@ StorageProviderConfigService = _ts_decorate([
|
|
|
1856
1970
|
}),
|
|
1857
1971
|
_ts_param(0, (0,_nestjs_common__rspack_import_3.Inject)('CACHE_INSTANCE')),
|
|
1858
1972
|
_ts_param(1, (0,_nestjs_common__rspack_import_3.Inject)(_flusys_nestjs_shared_modules__rspack_import_1.UtilsService)),
|
|
1859
|
-
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1860
|
-
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(
|
|
1973
|
+
_ts_param(2, (0,_nestjs_common__rspack_import_3.Inject)(_storage_config_service_js__rspack_import_8/* .StorageConfigService */.t)),
|
|
1974
|
+
_ts_param(3, (0,_nestjs_common__rspack_import_3.Inject)(_storage_datasource_provider_js__rspack_import_9/* .StorageDataSourceProvider */.M)),
|
|
1861
1975
|
_ts_metadata("design:type", Function),
|
|
1862
1976
|
_ts_metadata("design:paramtypes", [
|
|
1863
1977
|
typeof _flusys_nestjs_shared_classes__rspack_import_0.HybridCache === "undefined" ? Object : _flusys_nestjs_shared_classes__rspack_import_0.HybridCache,
|
|
1864
1978
|
typeof _flusys_nestjs_shared_modules__rspack_import_1.UtilsService === "undefined" ? Object : _flusys_nestjs_shared_modules__rspack_import_1.UtilsService,
|
|
1865
|
-
typeof
|
|
1866
|
-
typeof
|
|
1979
|
+
typeof _storage_config_service_js__rspack_import_8/* .StorageConfigService */.t === "undefined" ? Object : _storage_config_service_js__rspack_import_8/* .StorageConfigService */.t,
|
|
1980
|
+
typeof _storage_datasource_provider_js__rspack_import_9/* .StorageDataSourceProvider */.M === "undefined" ? Object : _storage_datasource_provider_js__rspack_import_9/* .StorageDataSourceProvider */.M
|
|
1867
1981
|
])
|
|
1868
1982
|
], StorageProviderConfigService);
|
|
1869
1983
|
|
|
@@ -1873,7 +1987,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1873
1987
|
|
|
1874
1988
|
|
|
1875
1989
|
},
|
|
1876
|
-
|
|
1990
|
+
5018(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1877
1991
|
|
|
1878
1992
|
// EXPORTS
|
|
1879
1993
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -1881,23 +1995,23 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1881
1995
|
});
|
|
1882
1996
|
|
|
1883
1997
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared"
|
|
1884
|
-
var nestjs_shared_ = __webpack_require__(
|
|
1998
|
+
var nestjs_shared_ = __webpack_require__(3422);
|
|
1885
1999
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared/classes"
|
|
1886
|
-
var classes_ = __webpack_require__(
|
|
2000
|
+
var classes_ = __webpack_require__(6937);
|
|
1887
2001
|
// EXTERNAL MODULE: external "@flusys/nestjs-shared/utils"
|
|
1888
|
-
var utils_ = __webpack_require__(
|
|
2002
|
+
var utils_ = __webpack_require__(9216);
|
|
1889
2003
|
// EXTERNAL MODULE: external "@nestjs/common"
|
|
1890
|
-
var common_ = __webpack_require__(
|
|
2004
|
+
var common_ = __webpack_require__(6157);
|
|
1891
2005
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/config/message-keys.ts
|
|
1892
|
-
var message_keys = __webpack_require__(
|
|
2006
|
+
var message_keys = __webpack_require__(5450);
|
|
1893
2007
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/config/event-actions.ts
|
|
1894
|
-
var event_actions = __webpack_require__(
|
|
2008
|
+
var event_actions = __webpack_require__(4884);
|
|
1895
2009
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/dtos/upload.dto.ts
|
|
1896
|
-
var upload_dto = __webpack_require__(
|
|
2010
|
+
var upload_dto = __webpack_require__(7322);
|
|
1897
2011
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/enums/file-location.enum.ts
|
|
1898
|
-
var file_location_enum = __webpack_require__(
|
|
2012
|
+
var file_location_enum = __webpack_require__(2733);
|
|
1899
2013
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/providers/storage-factory.service.ts + 1 modules
|
|
1900
|
-
var storage_factory_service = __webpack_require__(
|
|
2014
|
+
var storage_factory_service = __webpack_require__(2192);
|
|
1901
2015
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/utils/file-validator.util.ts
|
|
1902
2016
|
/**
|
|
1903
2017
|
* Result of file content validation.
|
|
@@ -1963,12 +2077,12 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
1963
2077
|
},
|
|
1964
2078
|
{
|
|
1965
2079
|
signature: [
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2080
|
+
0x57,
|
|
2081
|
+
0x45,
|
|
2082
|
+
0x42,
|
|
2083
|
+
0x50
|
|
1970
2084
|
],
|
|
1971
|
-
offset:
|
|
2085
|
+
offset: 8,
|
|
1972
2086
|
mimeType: 'image/webp'
|
|
1973
2087
|
},
|
|
1974
2088
|
{
|
|
@@ -2058,33 +2172,25 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2058
2172
|
offset: 0,
|
|
2059
2173
|
mimeType: 'audio/flac'
|
|
2060
2174
|
},
|
|
2061
|
-
// Video
|
|
2062
2175
|
{
|
|
2063
2176
|
signature: [
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
0x66,
|
|
2069
|
-
0x74,
|
|
2070
|
-
0x79,
|
|
2071
|
-
0x70
|
|
2177
|
+
0x57,
|
|
2178
|
+
0x41,
|
|
2179
|
+
0x56,
|
|
2180
|
+
0x45
|
|
2072
2181
|
],
|
|
2073
|
-
offset:
|
|
2074
|
-
mimeType: '
|
|
2182
|
+
offset: 8,
|
|
2183
|
+
mimeType: 'audio/wav'
|
|
2075
2184
|
},
|
|
2185
|
+
// Video
|
|
2076
2186
|
{
|
|
2077
2187
|
signature: [
|
|
2078
|
-
0x00,
|
|
2079
|
-
0x00,
|
|
2080
|
-
0x00,
|
|
2081
|
-
0x20,
|
|
2082
2188
|
0x66,
|
|
2083
2189
|
0x74,
|
|
2084
2190
|
0x79,
|
|
2085
2191
|
0x70
|
|
2086
2192
|
],
|
|
2087
|
-
offset:
|
|
2193
|
+
offset: 4,
|
|
2088
2194
|
mimeType: 'video/mp4'
|
|
2089
2195
|
},
|
|
2090
2196
|
{
|
|
@@ -2099,12 +2205,12 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2099
2205
|
},
|
|
2100
2206
|
{
|
|
2101
2207
|
signature: [
|
|
2102
|
-
|
|
2208
|
+
0x41,
|
|
2209
|
+
0x56,
|
|
2103
2210
|
0x49,
|
|
2104
|
-
|
|
2105
|
-
0x46
|
|
2211
|
+
0x20
|
|
2106
2212
|
],
|
|
2107
|
-
offset:
|
|
2213
|
+
offset: 8,
|
|
2108
2214
|
mimeType: 'video/avi'
|
|
2109
2215
|
},
|
|
2110
2216
|
// Archives
|
|
@@ -2237,7 +2343,8 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2237
2343
|
/**
|
|
2238
2344
|
* Check if a MIME type is a dangerous text type that can execute scripts.
|
|
2239
2345
|
*/ static isDangerousTextType(mimeType) {
|
|
2240
|
-
|
|
2346
|
+
const baseType = mimeType.split(';')[0].trim().toLowerCase();
|
|
2347
|
+
return DANGEROUS_TEXT_TYPES.includes(baseType);
|
|
2241
2348
|
}
|
|
2242
2349
|
/**
|
|
2243
2350
|
* Check if two MIME types are compatible (exact match or aliases).
|
|
@@ -2267,7 +2374,7 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2267
2374
|
return allowedTypes.some((allowed)=>{
|
|
2268
2375
|
// Category wildcard (e.g., "image/*")
|
|
2269
2376
|
if (allowed.endsWith('/*')) {
|
|
2270
|
-
const category = allowed.slice(0, -
|
|
2377
|
+
const category = allowed.slice(0, -1);
|
|
2271
2378
|
return mimeType.startsWith(category);
|
|
2272
2379
|
}
|
|
2273
2380
|
return allowed === mimeType;
|
|
@@ -2283,6 +2390,8 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2283
2390
|
'*/*'
|
|
2284
2391
|
]) {
|
|
2285
2392
|
try {
|
|
2393
|
+
const dangerous = this.rejectUnlistedDangerousType(declaredMimeType, allowedTypes);
|
|
2394
|
+
if (dangerous) return dangerous;
|
|
2286
2395
|
const detectedType = this.detectFileType(buffer);
|
|
2287
2396
|
// No magic bytes detected - handle text-based types
|
|
2288
2397
|
if (!detectedType) {
|
|
@@ -2302,15 +2411,16 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2302
2411
|
}
|
|
2303
2412
|
}
|
|
2304
2413
|
/**
|
|
2414
|
+
* Script-capable types (HTML, JS, SVG) pass only when listed by exact name - a polyglot
|
|
2415
|
+
* with a GIF or PNG header must not slip through as "same category as the content".
|
|
2416
|
+
*/ static rejectUnlistedDangerousType(declaredMimeType, allowedTypes) {
|
|
2417
|
+
if (!this.isDangerousTextType(declaredMimeType)) return null;
|
|
2418
|
+
if (allowedTypes.includes(declaredMimeType)) return null;
|
|
2419
|
+
return this.failureResult(`File type "${declaredMimeType}" is potentially dangerous and not explicitly allowed`, declaredMimeType, declaredMimeType);
|
|
2420
|
+
}
|
|
2421
|
+
/**
|
|
2305
2422
|
* Handle validation for files without detectable magic bytes.
|
|
2306
2423
|
*/ static validateUndetectedType(declaredMimeType, allowedTypes) {
|
|
2307
|
-
// Check for dangerous text types first (HTML, JS, SVG)
|
|
2308
|
-
if (this.isDangerousTextType(declaredMimeType)) {
|
|
2309
|
-
const explicitlyAllowed = allowedTypes.some((t)=>t === declaredMimeType && t !== '*/*' && !t.endsWith('/*'));
|
|
2310
|
-
if (!explicitlyAllowed) {
|
|
2311
|
-
return this.failureResult(`File type "${declaredMimeType}" is potentially dangerous and not explicitly allowed`, declaredMimeType, declaredMimeType);
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
2424
|
// Safe text-based files don't have magic bytes, trust declared type
|
|
2315
2425
|
if (this.isTextBasedType(declaredMimeType)) {
|
|
2316
2426
|
const isAllowed = this.isTypeAllowed(declaredMimeType, allowedTypes);
|
|
@@ -2334,9 +2444,9 @@ var storage_factory_service = __webpack_require__(192);
|
|
|
2334
2444
|
}
|
|
2335
2445
|
|
|
2336
2446
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/services/storage-config.service.ts
|
|
2337
|
-
var storage_config_service = __webpack_require__(
|
|
2447
|
+
var storage_config_service = __webpack_require__(6397);
|
|
2338
2448
|
// EXTERNAL MODULE: ./projects/nestjs-storage/src/services/storage-provider-config.service.ts
|
|
2339
|
-
var storage_provider_config_service = __webpack_require__(
|
|
2449
|
+
var storage_provider_config_service = __webpack_require__(8623);
|
|
2340
2450
|
;// CONCATENATED MODULE: ./projects/nestjs-storage/src/services/upload.service.ts
|
|
2341
2451
|
function _ts_decorate(decorators, target, key, desc) {
|
|
2342
2452
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -2442,7 +2552,7 @@ class UploadService {
|
|
|
2442
2552
|
/**
|
|
2443
2553
|
* Get storage provider and config info based on storage config ID
|
|
2444
2554
|
* Validates company ownership when company feature is enabled
|
|
2445
|
-
*/ async getStorageProviderWithConfig(storageConfigId, user) {
|
|
2555
|
+
*/ async getStorageProviderWithConfig(storageConfigId, user, requireActive = false) {
|
|
2446
2556
|
let storageConfig;
|
|
2447
2557
|
// Get storage config from database
|
|
2448
2558
|
if (storageConfigId) {
|
|
@@ -2456,6 +2566,13 @@ class UploadService {
|
|
|
2456
2566
|
}
|
|
2457
2567
|
// Validate company ownership using shared utility
|
|
2458
2568
|
(0,utils_.validateCompanyOwnership)(config, user, this.storageConfigService.isCompanyFeatureEnabled(), 'Storage configuration');
|
|
2569
|
+
// A deactivated config keeps serving and deleting its existing files but takes no new uploads
|
|
2570
|
+
if (requireActive && config.isActive === false) {
|
|
2571
|
+
throw new common_.NotFoundException({
|
|
2572
|
+
message: 'Storage configuration is inactive',
|
|
2573
|
+
messageKey: message_keys/* .UPLOAD_MESSAGES.CONFIG_NOT_FOUND */.dS.CONFIG_NOT_FOUND
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2459
2576
|
storageConfig = config;
|
|
2460
2577
|
} else {
|
|
2461
2578
|
// Use default config (scoped to user's company/branch)
|
|
@@ -2483,6 +2600,7 @@ class UploadService {
|
|
|
2483
2600
|
if (storageConfigId) {
|
|
2484
2601
|
const config = await this.storageProviderConfigService.findByIdDirect(storageConfigId);
|
|
2485
2602
|
if (config) {
|
|
2603
|
+
(0,utils_.validateCompanyOwnership)(config, user, this.storageConfigService.isCompanyFeatureEnabled(), 'Storage configuration');
|
|
2486
2604
|
return this.createProviderFromConfig(config);
|
|
2487
2605
|
}
|
|
2488
2606
|
}
|
|
@@ -2504,8 +2622,11 @@ class UploadService {
|
|
|
2504
2622
|
return this.createFallbackLocalProvider();
|
|
2505
2623
|
}
|
|
2506
2624
|
async uploadSingleFile(file, options, user) {
|
|
2625
|
+
this.assertFilesProvided(file ? [
|
|
2626
|
+
file
|
|
2627
|
+
] : []);
|
|
2507
2628
|
this.validateFile(file);
|
|
2508
|
-
const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user);
|
|
2629
|
+
const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user, true);
|
|
2509
2630
|
const result = await provider.uploadFile(file, options);
|
|
2510
2631
|
await this.publishFileEvent(event_actions/* .STORAGE_EVENT_ACTIONS.UPLOADED */.hw.UPLOADED, [
|
|
2511
2632
|
result.key
|
|
@@ -2522,11 +2643,12 @@ class UploadService {
|
|
|
2522
2643
|
};
|
|
2523
2644
|
}
|
|
2524
2645
|
async uploadMultipleFiles(files, options, user) {
|
|
2646
|
+
this.assertFilesProvided(files);
|
|
2525
2647
|
for (const file of files){
|
|
2526
2648
|
this.validateFile(file);
|
|
2527
2649
|
}
|
|
2528
|
-
const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user);
|
|
2529
|
-
const results = await
|
|
2650
|
+
const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user, true);
|
|
2651
|
+
const results = await this.uploadAllOrNothing(provider, files, options);
|
|
2530
2652
|
await this.publishFileEvent(event_actions/* .STORAGE_EVENT_ACTIONS.UPLOADED */.hw.UPLOADED, results.map((result)=>result.key), user, {
|
|
2531
2653
|
location,
|
|
2532
2654
|
storageConfigId: configId,
|
|
@@ -2567,6 +2689,26 @@ class UploadService {
|
|
|
2567
2689
|
});
|
|
2568
2690
|
return true;
|
|
2569
2691
|
}
|
|
2692
|
+
assertFilesProvided(files) {
|
|
2693
|
+
if (!files?.length) {
|
|
2694
|
+
throw new common_.BadRequestException({
|
|
2695
|
+
message: 'No files provided',
|
|
2696
|
+
messageKey: message_keys/* .UPLOAD_MESSAGES.NO_FILES_PROVIDED */.dS.NO_FILES_PROVIDED
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
/** One failed file fails the batch, and the files already stored are removed again */ async uploadAllOrNothing(provider, files, options) {
|
|
2701
|
+
const settled = await Promise.allSettled(files.map((file)=>provider.uploadFile(file, options)));
|
|
2702
|
+
const uploaded = settled.filter((r)=>r.status === 'fulfilled').map((r)=>r.value);
|
|
2703
|
+
const failure = settled.find((r)=>r.status === 'rejected');
|
|
2704
|
+
if (failure) {
|
|
2705
|
+
if (uploaded.length) {
|
|
2706
|
+
await provider.deleteMultipleFiles(uploaded.map((r)=>r.key)).catch(()=>undefined);
|
|
2707
|
+
}
|
|
2708
|
+
throw failure.reason;
|
|
2709
|
+
}
|
|
2710
|
+
return uploaded;
|
|
2711
|
+
}
|
|
2570
2712
|
async publishFileEvent(action, keys, user, metadata) {
|
|
2571
2713
|
await (0,classes_.publishDomainEvent)({
|
|
2572
2714
|
module: event_actions/* .STORAGE_EVENT_MODULE */.qh,
|
|
@@ -2580,31 +2722,11 @@ class UploadService {
|
|
|
2580
2722
|
bytesToKb(bytes) {
|
|
2581
2723
|
return Number((bytes * 0.001).toFixed(2));
|
|
2582
2724
|
}
|
|
2583
|
-
/**
|
|
2584
|
-
* Get local storage basePath from DB config
|
|
2585
|
-
* Initializes local provider if not cached, ensuring basePath is from DB
|
|
2586
|
-
*/ async getLocalStorageBasePath() {
|
|
2725
|
+
/** Storage roots the public file route may serve from; empty when they cannot be read */ async getLocalStorageBasePaths() {
|
|
2587
2726
|
try {
|
|
2588
|
-
|
|
2589
|
-
const cachedPath = this.storageFactory.getLocalProviderBasePath();
|
|
2590
|
-
if (cachedPath) {
|
|
2591
|
-
return cachedPath;
|
|
2592
|
-
}
|
|
2593
|
-
// Get local config from DB (without user context for public access)
|
|
2594
|
-
const localConfigs = await this.storageProviderConfigService.getConfigByType(file_location_enum/* .FileLocationEnum.LOCAL */.N.LOCAL);
|
|
2595
|
-
if (localConfigs.length > 0) {
|
|
2596
|
-
const localConfig = localConfigs[0];
|
|
2597
|
-
// Initialize provider to cache it
|
|
2598
|
-
await this.storageFactory.createProvider({
|
|
2599
|
-
provider: file_location_enum/* .FileLocationEnum.LOCAL */.N.LOCAL,
|
|
2600
|
-
config: localConfig.config
|
|
2601
|
-
});
|
|
2602
|
-
// Now get the cached basePath
|
|
2603
|
-
return this.storageFactory.getLocalProviderBasePath();
|
|
2604
|
-
}
|
|
2605
|
-
return null;
|
|
2727
|
+
return await this.storageProviderConfigService.getActiveLocalBasePaths();
|
|
2606
2728
|
} catch {
|
|
2607
|
-
return
|
|
2729
|
+
return [];
|
|
2608
2730
|
}
|
|
2609
2731
|
}
|
|
2610
2732
|
async makeFileUrl(key, storageConfigId, expiresIn = 3600, user) {
|
|
@@ -2702,61 +2824,104 @@ UploadService = _ts_decorate([
|
|
|
2702
2824
|
|
|
2703
2825
|
|
|
2704
2826
|
},
|
|
2705
|
-
|
|
2827
|
+
5198(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
2828
|
+
/* import */ var _flusys_nestjs_shared_constants__rspack_import_0 = __webpack_require__(9140);
|
|
2829
|
+
/* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(6157);
|
|
2830
|
+
/* import */ var typeorm__rspack_import_2 = __webpack_require__(7158);
|
|
2831
|
+
|
|
2832
|
+
|
|
2833
|
+
|
|
2834
|
+
/**
|
|
2835
|
+
* Write paths of ApiService load rows by id alone, so a caller could update or delete another
|
|
2836
|
+
* company's row by guessing its id. Every row must belong to the caller's company - a caller
|
|
2837
|
+
* without a company may only touch rows without one.
|
|
2838
|
+
*/ async function assertRowsInUserCompany(repository, ids, user, isCompanyFeatureEnabled, entityName) {
|
|
2839
|
+
if (!isCompanyFeatureEnabled || !user || !ids.length) return;
|
|
2840
|
+
const rows = await repository.find({
|
|
2841
|
+
where: {
|
|
2842
|
+
id: (0,typeorm__rspack_import_2.In)(ids)
|
|
2843
|
+
},
|
|
2844
|
+
withDeleted: true
|
|
2845
|
+
});
|
|
2846
|
+
const userCompanyId = user.companyId ?? null;
|
|
2847
|
+
if (rows.some((row)=>(row.companyId ?? null) !== userCompanyId)) {
|
|
2848
|
+
throw new _nestjs_common__rspack_import_1.ForbiddenException({
|
|
2849
|
+
message: `${entityName} belongs to another company`,
|
|
2850
|
+
messageKey: _flusys_nestjs_shared_constants__rspack_import_0.AUTH_MESSAGES.ENTITY_BELOG_ANOTHER_COMPANY,
|
|
2851
|
+
messageVariables: {
|
|
2852
|
+
entity: entityName
|
|
2853
|
+
}
|
|
2854
|
+
});
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2858
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
2859
|
+
p: () => (assertRowsInUserCompany)
|
|
2860
|
+
});
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
},
|
|
2864
|
+
3422(module) {
|
|
2706
2865
|
|
|
2707
2866
|
module.exports = __rspack_external__flusys_nestjs_shared_393d2cae;
|
|
2708
2867
|
|
|
2709
2868
|
|
|
2710
2869
|
},
|
|
2711
|
-
|
|
2870
|
+
6937(module) {
|
|
2712
2871
|
|
|
2713
2872
|
module.exports = __rspack_external__flusys_nestjs_shared_classes_6076a329;
|
|
2714
2873
|
|
|
2715
2874
|
|
|
2716
2875
|
},
|
|
2717
|
-
|
|
2876
|
+
9140(module) {
|
|
2718
2877
|
|
|
2719
2878
|
module.exports = __rspack_external__flusys_nestjs_shared_constants_81f33d5b;
|
|
2720
2879
|
|
|
2721
2880
|
|
|
2722
2881
|
},
|
|
2723
|
-
|
|
2882
|
+
1236(module) {
|
|
2724
2883
|
|
|
2725
2884
|
module.exports = __rspack_external__flusys_nestjs_shared_modules_24702bee;
|
|
2726
2885
|
|
|
2727
2886
|
|
|
2728
2887
|
},
|
|
2729
|
-
|
|
2888
|
+
9216(module) {
|
|
2730
2889
|
|
|
2731
2890
|
module.exports = __rspack_external__flusys_nestjs_shared_utils_9125c1f1;
|
|
2732
2891
|
|
|
2733
2892
|
|
|
2734
2893
|
},
|
|
2735
|
-
|
|
2894
|
+
6157(module) {
|
|
2736
2895
|
|
|
2737
2896
|
module.exports = __rspack_external__nestjs_common_a04939da;
|
|
2738
2897
|
|
|
2739
2898
|
|
|
2740
2899
|
},
|
|
2741
|
-
|
|
2900
|
+
6176(module) {
|
|
2742
2901
|
|
|
2743
2902
|
module.exports = __rspack_external__nestjs_swagger_7cd450b5;
|
|
2744
2903
|
|
|
2745
2904
|
|
|
2746
2905
|
},
|
|
2747
|
-
|
|
2906
|
+
5812(module) {
|
|
2748
2907
|
|
|
2749
2908
|
module.exports = __rspack_external_class_transformer_c5a479fb;
|
|
2750
2909
|
|
|
2751
2910
|
|
|
2752
2911
|
},
|
|
2753
|
-
|
|
2912
|
+
5421(module) {
|
|
2754
2913
|
|
|
2755
2914
|
module.exports = __rspack_external_class_validator_7b99ef4d;
|
|
2756
2915
|
|
|
2757
2916
|
|
|
2758
2917
|
},
|
|
2759
|
-
|
|
2918
|
+
2521(module) {
|
|
2919
|
+
|
|
2920
|
+
module.exports = __rspack_external_path;
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
},
|
|
2924
|
+
7158(module) {
|
|
2760
2925
|
|
|
2761
2926
|
module.exports = __rspack_external_typeorm;
|
|
2762
2927
|
|