@flusys/nestjs-storage 4.1.1 → 5.0.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 +71 -483
- package/cjs/config/message-keys.js +2 -52
- package/cjs/controllers/storage-config.controller.js +2 -2
- package/cjs/docs/storage-swagger.config.js +5 -3
- package/cjs/middlewares/file-serve.middleware.js +5 -5
- package/cjs/providers/azure-provider.optional.js +1 -1
- package/cjs/providers/s3-provider.optional.js +1 -1
- package/cjs/providers/sftp-provider.optional.js +1 -1
- package/cjs/providers/storage-factory.service.js +4 -4
- package/cjs/services/file-manager.service.js +3 -39
- package/cjs/services/storage-config.service.js +14 -3
- package/cjs/services/storage-datasource.provider.js +1 -6
- package/cjs/services/upload.service.js +12 -6
- package/config/message-keys.d.ts +0 -96
- package/fesm/config/message-keys.js +2 -47
- package/fesm/controllers/storage-config.controller.js +2 -2
- package/fesm/docs/storage-swagger.config.js +5 -3
- package/fesm/middlewares/file-serve.middleware.js +5 -5
- package/fesm/providers/azure-provider.optional.js +1 -1
- package/fesm/providers/s3-provider.optional.js +1 -1
- package/fesm/providers/sftp-provider.optional.js +1 -1
- package/fesm/providers/storage-factory.service.js +4 -4
- package/fesm/services/file-manager.service.js +3 -39
- package/fesm/services/storage-config.service.js +14 -3
- package/fesm/services/storage-datasource.provider.js +1 -6
- package/fesm/services/upload.service.js +12 -6
- package/package.json +3 -3
- package/services/file-manager.service.d.ts +1 -6
- package/services/storage-config.service.d.ts +2 -0
- package/services/storage-datasource.provider.d.ts +1 -2
- package/services/upload.service.d.ts +1 -1
|
@@ -16,75 +16,25 @@ _export(exports, {
|
|
|
16
16
|
get FOLDER_MESSAGES () {
|
|
17
17
|
return FOLDER_MESSAGES;
|
|
18
18
|
},
|
|
19
|
-
get STORAGE_CONFIG_MESSAGES () {
|
|
20
|
-
return STORAGE_CONFIG_MESSAGES;
|
|
21
|
-
},
|
|
22
|
-
get STORAGE_MODULE_MESSAGES () {
|
|
23
|
-
return STORAGE_MODULE_MESSAGES;
|
|
24
|
-
},
|
|
25
19
|
get UPLOAD_MESSAGES () {
|
|
26
20
|
return UPLOAD_MESSAGES;
|
|
27
21
|
}
|
|
28
22
|
});
|
|
29
23
|
const FILE_MESSAGES = {
|
|
30
|
-
CREATE_SUCCESS: 'file.create.success',
|
|
31
|
-
CREATE_MANY_SUCCESS: 'file.create.many.success',
|
|
32
|
-
GET_SUCCESS: 'file.get.success',
|
|
33
24
|
GET_ALL_SUCCESS: 'file.get.all.success',
|
|
34
|
-
UPDATE_SUCCESS: 'file.update.success',
|
|
35
|
-
UPDATE_MANY_SUCCESS: 'file.update.many.success',
|
|
36
25
|
DELETE_SUCCESS: 'file.delete.success',
|
|
37
|
-
|
|
38
|
-
NOT_FOUND: 'file.not.found',
|
|
39
|
-
UPLOAD_SUCCESS: 'file.upload.success',
|
|
40
|
-
UPLOAD_MANY_SUCCESS: 'file.upload.many.success',
|
|
41
|
-
DOWNLOAD_SUCCESS: 'file.download.success',
|
|
42
|
-
MOVE_SUCCESS: 'file.move.success',
|
|
43
|
-
COPY_SUCCESS: 'file.copy.success'
|
|
26
|
+
NOT_FOUND: 'file.not.found'
|
|
44
27
|
};
|
|
45
28
|
const FOLDER_MESSAGES = {
|
|
46
|
-
|
|
47
|
-
CREATE_MANY_SUCCESS: 'folder.create.many.success',
|
|
48
|
-
GET_SUCCESS: 'folder.get.success',
|
|
49
|
-
GET_ALL_SUCCESS: 'folder.get.all.success',
|
|
50
|
-
UPDATE_SUCCESS: 'folder.update.success',
|
|
51
|
-
UPDATE_MANY_SUCCESS: 'folder.update.many.success',
|
|
52
|
-
DELETE_SUCCESS: 'folder.delete.success',
|
|
53
|
-
RESTORE_SUCCESS: 'folder.restore.success',
|
|
54
|
-
NOT_FOUND: 'folder.not.found',
|
|
55
|
-
TREE_SUCCESS: 'folder.tree.success',
|
|
56
|
-
CONTENTS_SUCCESS: 'folder.contents.success'
|
|
57
|
-
};
|
|
58
|
-
const STORAGE_CONFIG_MESSAGES = {
|
|
59
|
-
CREATE_SUCCESS: 'storage.config.create.success',
|
|
60
|
-
CREATE_MANY_SUCCESS: 'storage.config.create.many.success',
|
|
61
|
-
GET_SUCCESS: 'storage.config.get.success',
|
|
62
|
-
GET_ALL_SUCCESS: 'storage.config.get.all.success',
|
|
63
|
-
UPDATE_SUCCESS: 'storage.config.update.success',
|
|
64
|
-
UPDATE_MANY_SUCCESS: 'storage.config.update.many.success',
|
|
65
|
-
DELETE_SUCCESS: 'storage.config.delete.success',
|
|
66
|
-
RESTORE_SUCCESS: 'storage.config.restore.success',
|
|
67
|
-
NOT_FOUND: 'storage.config.not.found',
|
|
68
|
-
ACTIVE_SUCCESS: 'storage.config.active.success',
|
|
69
|
-
TEST_SUCCESS: 'storage.config.test.success',
|
|
70
|
-
TEST_FAILED: 'storage.config.test.failed'
|
|
29
|
+
NOT_FOUND: 'folder.not.found'
|
|
71
30
|
};
|
|
72
31
|
const UPLOAD_MESSAGES = {
|
|
73
32
|
SUCCESS: 'upload.success',
|
|
74
33
|
MANY_SUCCESS: 'upload.many.success',
|
|
75
|
-
FAILED: 'upload.failed',
|
|
76
34
|
FILE_TOO_LARGE: 'upload.file.too.large',
|
|
77
35
|
INVALID_TYPE: 'upload.invalid.type',
|
|
78
|
-
CHUNK_SUCCESS: 'upload.chunk.success',
|
|
79
|
-
COMPLETE_SUCCESS: 'upload.complete.success',
|
|
80
36
|
NO_FILES_PROVIDED: 'upload.no.files.provided',
|
|
81
37
|
NO_FILE_PATH: 'upload.no.file.path',
|
|
82
38
|
INVALID_FILE_PATH: 'upload.invalid.file.path',
|
|
83
39
|
CONFIG_NOT_FOUND: 'upload.config.not.found'
|
|
84
40
|
};
|
|
85
|
-
const STORAGE_MODULE_MESSAGES = {
|
|
86
|
-
FILE: FILE_MESSAGES,
|
|
87
|
-
FOLDER: FOLDER_MESSAGES,
|
|
88
|
-
STORAGE_CONFIG: STORAGE_CONFIG_MESSAGES,
|
|
89
|
-
UPLOAD: UPLOAD_MESSAGES
|
|
90
|
-
};
|
|
@@ -9,9 +9,9 @@ Object.defineProperty(exports, "StorageConfigController", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _classes = require("@flusys/nestjs-shared/classes");
|
|
12
|
-
const _dtos = require("../dtos");
|
|
13
12
|
const _common = require("@nestjs/common");
|
|
14
13
|
const _swagger = require("@nestjs/swagger");
|
|
14
|
+
const _dtos = require("../dtos");
|
|
15
15
|
const _storageproviderconfigservice = require("../services/storage-provider-config.service");
|
|
16
16
|
function _define_property(obj, key, value) {
|
|
17
17
|
if (key in obj) {
|
|
@@ -41,7 +41,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
let StorageConfigController = class StorageConfigController extends (0, _classes.createApiController)(_dtos.CreateStorageConfigDto, _dtos.UpdateStorageConfigDto, _dtos.StorageConfigResponseDto, {
|
|
44
|
-
entityName: '
|
|
44
|
+
entityName: 'storage.config',
|
|
45
45
|
security: {
|
|
46
46
|
insert: {
|
|
47
47
|
level: 'permission',
|
|
@@ -28,7 +28,8 @@ const COMPANY_SCHEMA_EXCLUSIONS = [
|
|
|
28
28
|
]
|
|
29
29
|
}
|
|
30
30
|
];
|
|
31
|
-
function buildDescription(enableCompanyFeature) {
|
|
31
|
+
function buildDescription(enableCompanyFeature, isMultiTenant) {
|
|
32
|
+
const multiTenantNote = isMultiTenant ? `\n> **Multi-Tenant Mode**: Include \`x-tenant-id\` header to target a specific tenant database.\n` : '';
|
|
32
33
|
const companyIsolation = enableCompanyFeature ? '\n- **Company isolation**' : '';
|
|
33
34
|
const companyPermissions = enableCompanyFeature ? '\n- **Company-level permissions**' : '';
|
|
34
35
|
const multiTenantSection = enableCompanyFeature ? `
|
|
@@ -56,7 +57,7 @@ POST /storage/folder/insert with JSON body containing folder name
|
|
|
56
57
|
` : '';
|
|
57
58
|
return `
|
|
58
59
|
# Storage Management API
|
|
59
|
-
|
|
60
|
+
${multiTenantNote}
|
|
60
61
|
Complete file storage and management system${enableCompanyFeature ? ' with multi-tenant support' : ''}.
|
|
61
62
|
|
|
62
63
|
## Features
|
|
@@ -174,9 +175,10 @@ All endpoints are rate-limited to prevent abuse. Default limits:
|
|
|
174
175
|
}
|
|
175
176
|
function storageSwaggerConfig(bootstrapConfig) {
|
|
176
177
|
const enableCompanyFeature = bootstrapConfig?.enableCompanyFeature ?? true;
|
|
178
|
+
const isMultiTenant = bootstrapConfig?.databaseMode === 'multi-tenant';
|
|
177
179
|
return {
|
|
178
180
|
title: 'Storage API',
|
|
179
|
-
description: buildDescription(enableCompanyFeature),
|
|
181
|
+
description: buildDescription(enableCompanyFeature, isMultiTenant),
|
|
180
182
|
version: '1.0',
|
|
181
183
|
path: 'api/docs/storage',
|
|
182
184
|
bearerAuth: true,
|
|
@@ -101,7 +101,7 @@ let FileServeMiddleware = class FileServeMiddleware {
|
|
|
101
101
|
throw new _common.NotFoundException({
|
|
102
102
|
message: `Not a file: ${normalizedPath}`,
|
|
103
103
|
messageKey: _config.FILE_MESSAGES.NOT_FOUND,
|
|
104
|
-
|
|
104
|
+
messageVariables: {
|
|
105
105
|
path: normalizedPath
|
|
106
106
|
}
|
|
107
107
|
});
|
|
@@ -150,7 +150,7 @@ let FileServeMiddleware = class FileServeMiddleware {
|
|
|
150
150
|
throw new _common.NotFoundException({
|
|
151
151
|
message: `File not found: ${normalizedPath}`,
|
|
152
152
|
messageKey: _config.FILE_MESSAGES.NOT_FOUND,
|
|
153
|
-
|
|
153
|
+
messageVariables: {
|
|
154
154
|
path: normalizedPath
|
|
155
155
|
}
|
|
156
156
|
});
|
|
@@ -199,7 +199,7 @@ let FileServeMiddleware = class FileServeMiddleware {
|
|
|
199
199
|
this.sendErrorResponse(res, new _common.NotFoundException({
|
|
200
200
|
message: `Failed to serve file: ${normalizedPath}`,
|
|
201
201
|
messageKey: _config.FILE_MESSAGES.NOT_FOUND,
|
|
202
|
-
|
|
202
|
+
messageVariables: {
|
|
203
203
|
path: normalizedPath
|
|
204
204
|
}
|
|
205
205
|
}));
|
|
@@ -213,12 +213,12 @@ let FileServeMiddleware = class FileServeMiddleware {
|
|
|
213
213
|
const response = isNotFound ? error.getResponse() : null;
|
|
214
214
|
const message = response?.message ?? 'File not found';
|
|
215
215
|
const messageKey = response?.messageKey ?? _config.FILE_MESSAGES.NOT_FOUND;
|
|
216
|
-
const
|
|
216
|
+
const messageVariables = response?.messageVariables;
|
|
217
217
|
res.status(404).json({
|
|
218
218
|
success: false,
|
|
219
219
|
message,
|
|
220
220
|
messageKey,
|
|
221
|
-
|
|
221
|
+
messageVariables,
|
|
222
222
|
error: 'Not Found',
|
|
223
223
|
statusCode: 404
|
|
224
224
|
});
|
|
@@ -82,7 +82,7 @@ let AzureProvider = class AzureProvider {
|
|
|
82
82
|
throw new _common.InternalServerErrorException({
|
|
83
83
|
message: 'Azure Storage SDK not found',
|
|
84
84
|
messageKey: _constants.SYSTEM_MESSAGES.SDK_NOT_INSTALLED,
|
|
85
|
-
|
|
85
|
+
messageVariables: {
|
|
86
86
|
sdk: '@azure/storage-blob'
|
|
87
87
|
}
|
|
88
88
|
});
|
|
@@ -87,7 +87,7 @@ let S3Provider = class S3Provider {
|
|
|
87
87
|
throw new _common.InternalServerErrorException({
|
|
88
88
|
message: 'AWS SDK not found',
|
|
89
89
|
messageKey: _constants.SYSTEM_MESSAGES.SDK_NOT_INSTALLED,
|
|
90
|
-
|
|
90
|
+
messageVariables: {
|
|
91
91
|
sdk: '@aws-sdk/client-s3'
|
|
92
92
|
}
|
|
93
93
|
});
|
|
@@ -107,7 +107,7 @@ let SftpProvider = class SftpProvider {
|
|
|
107
107
|
throw new _common.InternalServerErrorException({
|
|
108
108
|
message: 'SFTP client not found',
|
|
109
109
|
messageKey: _constants.SYSTEM_MESSAGES.SDK_NOT_INSTALLED,
|
|
110
|
-
|
|
110
|
+
messageVariables: {
|
|
111
111
|
sdk: 'ssh2-sftp-client'
|
|
112
112
|
}
|
|
113
113
|
});
|
|
@@ -8,9 +8,9 @@ Object.defineProperty(exports, "StorageFactoryService", {
|
|
|
8
8
|
return StorageFactoryService;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _constants = require("@flusys/nestjs-shared/constants");
|
|
11
12
|
const _common = require("@nestjs/common");
|
|
12
13
|
const _crypto = /*#__PURE__*/ _interop_require_wildcard(require("crypto"));
|
|
13
|
-
const _constants = require("@flusys/nestjs-shared/constants");
|
|
14
14
|
const _services = require("../services");
|
|
15
15
|
const _storageproviderregistry = require("./storage-provider.registry");
|
|
16
16
|
function _define_property(obj, key, value) {
|
|
@@ -89,9 +89,9 @@ let StorageFactoryService = class StorageFactoryService {
|
|
|
89
89
|
const ProviderClass = _storageproviderregistry.StorageProviderRegistry.get(config.provider);
|
|
90
90
|
if (!ProviderClass) {
|
|
91
91
|
throw new _common.NotFoundException({
|
|
92
|
-
message: `Storage provider '${config.provider}' not
|
|
92
|
+
message: `Storage provider '${config.provider}' not available. Available: ${_storageproviderregistry.StorageProviderRegistry.getAll().join(', ')}`,
|
|
93
93
|
messageKey: _constants.SYSTEM_MESSAGES.SERVICE_NOT_AVAILABLE,
|
|
94
|
-
|
|
94
|
+
messageVariables: {
|
|
95
95
|
provider: config.provider,
|
|
96
96
|
available: _storageproviderregistry.StorageProviderRegistry.getAll().join(', ')
|
|
97
97
|
}
|
|
@@ -107,7 +107,7 @@ let StorageFactoryService = class StorageFactoryService {
|
|
|
107
107
|
throw new _common.InternalServerErrorException({
|
|
108
108
|
message: `Failed to initialize '${config.provider}': ${errorMessage}`,
|
|
109
109
|
messageKey: _constants.SYSTEM_MESSAGES.INTERNAL_ERROR,
|
|
110
|
-
|
|
110
|
+
messageVariables: {
|
|
111
111
|
provider: config.provider,
|
|
112
112
|
error: errorMessage
|
|
113
113
|
}
|
|
@@ -11,12 +11,12 @@ Object.defineProperty(exports, "FileManagerService", {
|
|
|
11
11
|
const _classes = require("@flusys/nestjs-shared/classes");
|
|
12
12
|
const _modules = require("@flusys/nestjs-shared/modules");
|
|
13
13
|
const _utils = require("@flusys/nestjs-shared/utils");
|
|
14
|
-
const _config = require("../config");
|
|
15
14
|
const _common = require("@nestjs/common");
|
|
16
15
|
const _typeorm = require("typeorm");
|
|
17
|
-
const
|
|
16
|
+
const _config = require("../config");
|
|
18
17
|
const _entities = require("../entities");
|
|
19
18
|
const _filelocationenum = require("../enums/file-location.enum");
|
|
19
|
+
const _storageconfigservice = require("./storage-config.service");
|
|
20
20
|
const _storagedatasourceprovider = require("./storage-datasource.provider");
|
|
21
21
|
const _uploadservice = require("./upload.service");
|
|
22
22
|
function _define_property(obj, key, value) {
|
|
@@ -195,42 +195,6 @@ let FileManagerService = class FileManagerService extends _classes.RequestScoped
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
// ─── Public Methods ─────────────────────────────────────────────────────────
|
|
198
|
-
async enrichWithProviderNames(items) {
|
|
199
|
-
const configIds = [
|
|
200
|
-
...new Set(items.map((i)=>i.storageConfigId).filter(Boolean))
|
|
201
|
-
];
|
|
202
|
-
if (!configIds.length) {
|
|
203
|
-
return items.map((item)=>({
|
|
204
|
-
...item,
|
|
205
|
-
providerName: undefined
|
|
206
|
-
}));
|
|
207
|
-
}
|
|
208
|
-
try {
|
|
209
|
-
const repo = await this.getStorageConfigRepository();
|
|
210
|
-
const configs = await repo.find({
|
|
211
|
-
where: {
|
|
212
|
-
id: (0, _typeorm.In)(configIds)
|
|
213
|
-
},
|
|
214
|
-
select: [
|
|
215
|
-
'id',
|
|
216
|
-
'name'
|
|
217
|
-
]
|
|
218
|
-
});
|
|
219
|
-
const nameMap = new Map(configs.map((c)=>[
|
|
220
|
-
c.id,
|
|
221
|
-
c.name
|
|
222
|
-
]));
|
|
223
|
-
return items.map((item)=>({
|
|
224
|
-
...item,
|
|
225
|
-
providerName: item.storageConfigId ? nameMap.get(item.storageConfigId) : undefined
|
|
226
|
-
}));
|
|
227
|
-
} catch {
|
|
228
|
-
return items.map((item)=>({
|
|
229
|
-
...item,
|
|
230
|
-
providerName: undefined
|
|
231
|
-
}));
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
198
|
async getFiles(dtos, protocol, host, user) {
|
|
235
199
|
await this.ensureRepositoryInitialized();
|
|
236
200
|
const ids = dtos.map((d)=>d.id).filter(Boolean);
|
|
@@ -298,7 +262,7 @@ let FileManagerService = class FileManagerService extends _classes.RequestScoped
|
|
|
298
262
|
throw new _common.BadRequestException({
|
|
299
263
|
message: `Folder "${folderId}" not found or access denied`,
|
|
300
264
|
messageKey: _config.FOLDER_MESSAGES.NOT_FOUND,
|
|
301
|
-
|
|
265
|
+
messageVariables: {
|
|
302
266
|
folderId
|
|
303
267
|
}
|
|
304
268
|
});
|
|
@@ -9,8 +9,9 @@ Object.defineProperty(exports, "StorageConfigService", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _common = require("@nestjs/common");
|
|
12
|
-
const
|
|
12
|
+
const _config = require("../config");
|
|
13
13
|
const _storageconstants = require("../config/storage.constants");
|
|
14
|
+
const _interfaces = require("../interfaces");
|
|
14
15
|
function _define_property(obj, key, value) {
|
|
15
16
|
if (key in obj) {
|
|
16
17
|
Object.defineProperty(obj, key, {
|
|
@@ -81,7 +82,12 @@ let StorageConfigService = class StorageConfigService {
|
|
|
81
82
|
if (fileSize > maxSize) {
|
|
82
83
|
return {
|
|
83
84
|
valid: false,
|
|
84
|
-
message: `File size (${this.toMB(fileSize)}MB) exceeds maximum ${this.toMB(maxSize)}MB
|
|
85
|
+
message: `File size (${this.toMB(fileSize)}MB) exceeds maximum ${this.toMB(maxSize)}MB`,
|
|
86
|
+
messageKey: _config.UPLOAD_MESSAGES.FILE_TOO_LARGE,
|
|
87
|
+
messageVariables: {
|
|
88
|
+
fileSize: this.toMB(fileSize),
|
|
89
|
+
maxSize: this.toMB(maxSize)
|
|
90
|
+
}
|
|
85
91
|
};
|
|
86
92
|
}
|
|
87
93
|
return {
|
|
@@ -92,7 +98,12 @@ let StorageConfigService = class StorageConfigService {
|
|
|
92
98
|
if (!this.isFileTypeAllowed(mimeType)) {
|
|
93
99
|
return {
|
|
94
100
|
valid: false,
|
|
95
|
-
message: `File type "${mimeType}" not allowed. Allowed: ${this.getAllowedFileTypes().join(', ')}
|
|
101
|
+
message: `File type "${mimeType}" not allowed. Allowed: ${this.getAllowedFileTypes().join(', ')}`,
|
|
102
|
+
messageKey: _config.UPLOAD_MESSAGES.INVALID_TYPE,
|
|
103
|
+
messageVariables: {
|
|
104
|
+
mimeType,
|
|
105
|
+
allowedTypes: this.getAllowedFileTypes().join(', ')
|
|
106
|
+
}
|
|
96
107
|
};
|
|
97
108
|
}
|
|
98
109
|
return {
|
|
@@ -8,9 +8,9 @@ Object.defineProperty(exports, "StorageDataSourceProvider", {
|
|
|
8
8
|
return StorageDataSourceProvider;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _constants = require("@flusys/nestjs-shared/constants");
|
|
11
12
|
const _modules = require("@flusys/nestjs-shared/modules");
|
|
12
13
|
const _common = require("@nestjs/common");
|
|
13
|
-
const _constants = require("@flusys/nestjs-shared/constants");
|
|
14
14
|
const _core = require("@nestjs/core");
|
|
15
15
|
const _express = require("express");
|
|
16
16
|
const _storageconfigservice = require("./storage-config.service");
|
|
@@ -99,11 +99,6 @@ let StorageDataSourceProvider = class StorageDataSourceProvider extends _modules
|
|
|
99
99
|
*/ getEnableCompanyFeatureForTenant(tenant) {
|
|
100
100
|
return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
|
|
101
101
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Get enable company feature for current request context
|
|
104
|
-
*/ getEnableCompanyFeatureForCurrentTenant() {
|
|
105
|
-
return this.getEnableCompanyFeatureForTenant(this.getCurrentTenant() ?? undefined);
|
|
106
|
-
}
|
|
107
102
|
// Entity Management
|
|
108
103
|
/**
|
|
109
104
|
* Get storage entities for migrations based on company feature flag.
|
|
@@ -9,16 +9,16 @@ Object.defineProperty(exports, "UploadService", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _nestjsshared = require("@flusys/nestjs-shared");
|
|
12
|
-
const _config = require("../config");
|
|
13
12
|
const _interfaces = require("@flusys/nestjs-shared/interfaces");
|
|
14
13
|
const _utils = require("@flusys/nestjs-shared/utils");
|
|
15
14
|
const _common = require("@nestjs/common");
|
|
16
|
-
const
|
|
15
|
+
const _config = require("../config");
|
|
17
16
|
const _uploaddto = require("../dtos/upload.dto");
|
|
18
17
|
const _filelocationenum = require("../enums/file-location.enum");
|
|
19
18
|
const _storagefactoryservice = require("../providers/storage-factory.service");
|
|
20
|
-
const _storageproviderconfigservice = require("./storage-provider-config.service");
|
|
21
19
|
const _filevalidatorutil = require("../utils/file-validator.util");
|
|
20
|
+
const _storageconfigservice = require("./storage-config.service");
|
|
21
|
+
const _storageproviderconfigservice = require("./storage-provider-config.service");
|
|
22
22
|
function _define_property(obj, key, value) {
|
|
23
23
|
if (key in obj) {
|
|
24
24
|
Object.defineProperty(obj, key, {
|
|
@@ -56,7 +56,8 @@ let UploadService = class UploadService {
|
|
|
56
56
|
if (!sizeValidation.valid) {
|
|
57
57
|
throw new _common.BadRequestException({
|
|
58
58
|
message: sizeValidation.message,
|
|
59
|
-
messageKey:
|
|
59
|
+
messageKey: sizeValidation.messageKey,
|
|
60
|
+
messageVariables: sizeValidation.messageVariables
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
// Validate declared file type (MIME)
|
|
@@ -64,7 +65,8 @@ let UploadService = class UploadService {
|
|
|
64
65
|
if (!typeValidation.valid) {
|
|
65
66
|
throw new _common.BadRequestException({
|
|
66
67
|
message: typeValidation.message,
|
|
67
|
-
messageKey:
|
|
68
|
+
messageKey: typeValidation.messageKey,
|
|
69
|
+
messageVariables: typeValidation.messageVariables
|
|
68
70
|
});
|
|
69
71
|
}
|
|
70
72
|
// Validate file content matches declared type (magic bytes check)
|
|
@@ -74,7 +76,11 @@ let UploadService = class UploadService {
|
|
|
74
76
|
if (!contentValidation.valid) {
|
|
75
77
|
throw new _common.BadRequestException({
|
|
76
78
|
message: contentValidation.message || 'File content validation failed',
|
|
77
|
-
messageKey: _config.UPLOAD_MESSAGES.INVALID_TYPE
|
|
79
|
+
messageKey: _config.UPLOAD_MESSAGES.INVALID_TYPE,
|
|
80
|
+
messageVariables: {
|
|
81
|
+
mimeType: file.mimetype,
|
|
82
|
+
allowedTypes: allowedTypes.join(', ')
|
|
83
|
+
}
|
|
78
84
|
});
|
|
79
85
|
}
|
|
80
86
|
// Sanitize filename to prevent path traversal attacks
|
package/config/message-keys.d.ts
CHANGED
|
@@ -1,114 +1,18 @@
|
|
|
1
1
|
export declare const FILE_MESSAGES: {
|
|
2
|
-
readonly CREATE_SUCCESS: "file.create.success";
|
|
3
|
-
readonly CREATE_MANY_SUCCESS: "file.create.many.success";
|
|
4
|
-
readonly GET_SUCCESS: "file.get.success";
|
|
5
2
|
readonly GET_ALL_SUCCESS: "file.get.all.success";
|
|
6
|
-
readonly UPDATE_SUCCESS: "file.update.success";
|
|
7
|
-
readonly UPDATE_MANY_SUCCESS: "file.update.many.success";
|
|
8
3
|
readonly DELETE_SUCCESS: "file.delete.success";
|
|
9
|
-
readonly RESTORE_SUCCESS: "file.restore.success";
|
|
10
4
|
readonly NOT_FOUND: "file.not.found";
|
|
11
|
-
readonly UPLOAD_SUCCESS: "file.upload.success";
|
|
12
|
-
readonly UPLOAD_MANY_SUCCESS: "file.upload.many.success";
|
|
13
|
-
readonly DOWNLOAD_SUCCESS: "file.download.success";
|
|
14
|
-
readonly MOVE_SUCCESS: "file.move.success";
|
|
15
|
-
readonly COPY_SUCCESS: "file.copy.success";
|
|
16
5
|
};
|
|
17
6
|
export declare const FOLDER_MESSAGES: {
|
|
18
|
-
readonly CREATE_SUCCESS: "folder.create.success";
|
|
19
|
-
readonly CREATE_MANY_SUCCESS: "folder.create.many.success";
|
|
20
|
-
readonly GET_SUCCESS: "folder.get.success";
|
|
21
|
-
readonly GET_ALL_SUCCESS: "folder.get.all.success";
|
|
22
|
-
readonly UPDATE_SUCCESS: "folder.update.success";
|
|
23
|
-
readonly UPDATE_MANY_SUCCESS: "folder.update.many.success";
|
|
24
|
-
readonly DELETE_SUCCESS: "folder.delete.success";
|
|
25
|
-
readonly RESTORE_SUCCESS: "folder.restore.success";
|
|
26
7
|
readonly NOT_FOUND: "folder.not.found";
|
|
27
|
-
readonly TREE_SUCCESS: "folder.tree.success";
|
|
28
|
-
readonly CONTENTS_SUCCESS: "folder.contents.success";
|
|
29
|
-
};
|
|
30
|
-
export declare const STORAGE_CONFIG_MESSAGES: {
|
|
31
|
-
readonly CREATE_SUCCESS: "storage.config.create.success";
|
|
32
|
-
readonly CREATE_MANY_SUCCESS: "storage.config.create.many.success";
|
|
33
|
-
readonly GET_SUCCESS: "storage.config.get.success";
|
|
34
|
-
readonly GET_ALL_SUCCESS: "storage.config.get.all.success";
|
|
35
|
-
readonly UPDATE_SUCCESS: "storage.config.update.success";
|
|
36
|
-
readonly UPDATE_MANY_SUCCESS: "storage.config.update.many.success";
|
|
37
|
-
readonly DELETE_SUCCESS: "storage.config.delete.success";
|
|
38
|
-
readonly RESTORE_SUCCESS: "storage.config.restore.success";
|
|
39
|
-
readonly NOT_FOUND: "storage.config.not.found";
|
|
40
|
-
readonly ACTIVE_SUCCESS: "storage.config.active.success";
|
|
41
|
-
readonly TEST_SUCCESS: "storage.config.test.success";
|
|
42
|
-
readonly TEST_FAILED: "storage.config.test.failed";
|
|
43
8
|
};
|
|
44
9
|
export declare const UPLOAD_MESSAGES: {
|
|
45
10
|
readonly SUCCESS: "upload.success";
|
|
46
11
|
readonly MANY_SUCCESS: "upload.many.success";
|
|
47
|
-
readonly FAILED: "upload.failed";
|
|
48
12
|
readonly FILE_TOO_LARGE: "upload.file.too.large";
|
|
49
13
|
readonly INVALID_TYPE: "upload.invalid.type";
|
|
50
|
-
readonly CHUNK_SUCCESS: "upload.chunk.success";
|
|
51
|
-
readonly COMPLETE_SUCCESS: "upload.complete.success";
|
|
52
14
|
readonly NO_FILES_PROVIDED: "upload.no.files.provided";
|
|
53
15
|
readonly NO_FILE_PATH: "upload.no.file.path";
|
|
54
16
|
readonly INVALID_FILE_PATH: "upload.invalid.file.path";
|
|
55
17
|
readonly CONFIG_NOT_FOUND: "upload.config.not.found";
|
|
56
18
|
};
|
|
57
|
-
export declare const STORAGE_MODULE_MESSAGES: {
|
|
58
|
-
readonly FILE: {
|
|
59
|
-
readonly CREATE_SUCCESS: "file.create.success";
|
|
60
|
-
readonly CREATE_MANY_SUCCESS: "file.create.many.success";
|
|
61
|
-
readonly GET_SUCCESS: "file.get.success";
|
|
62
|
-
readonly GET_ALL_SUCCESS: "file.get.all.success";
|
|
63
|
-
readonly UPDATE_SUCCESS: "file.update.success";
|
|
64
|
-
readonly UPDATE_MANY_SUCCESS: "file.update.many.success";
|
|
65
|
-
readonly DELETE_SUCCESS: "file.delete.success";
|
|
66
|
-
readonly RESTORE_SUCCESS: "file.restore.success";
|
|
67
|
-
readonly NOT_FOUND: "file.not.found";
|
|
68
|
-
readonly UPLOAD_SUCCESS: "file.upload.success";
|
|
69
|
-
readonly UPLOAD_MANY_SUCCESS: "file.upload.many.success";
|
|
70
|
-
readonly DOWNLOAD_SUCCESS: "file.download.success";
|
|
71
|
-
readonly MOVE_SUCCESS: "file.move.success";
|
|
72
|
-
readonly COPY_SUCCESS: "file.copy.success";
|
|
73
|
-
};
|
|
74
|
-
readonly FOLDER: {
|
|
75
|
-
readonly CREATE_SUCCESS: "folder.create.success";
|
|
76
|
-
readonly CREATE_MANY_SUCCESS: "folder.create.many.success";
|
|
77
|
-
readonly GET_SUCCESS: "folder.get.success";
|
|
78
|
-
readonly GET_ALL_SUCCESS: "folder.get.all.success";
|
|
79
|
-
readonly UPDATE_SUCCESS: "folder.update.success";
|
|
80
|
-
readonly UPDATE_MANY_SUCCESS: "folder.update.many.success";
|
|
81
|
-
readonly DELETE_SUCCESS: "folder.delete.success";
|
|
82
|
-
readonly RESTORE_SUCCESS: "folder.restore.success";
|
|
83
|
-
readonly NOT_FOUND: "folder.not.found";
|
|
84
|
-
readonly TREE_SUCCESS: "folder.tree.success";
|
|
85
|
-
readonly CONTENTS_SUCCESS: "folder.contents.success";
|
|
86
|
-
};
|
|
87
|
-
readonly STORAGE_CONFIG: {
|
|
88
|
-
readonly CREATE_SUCCESS: "storage.config.create.success";
|
|
89
|
-
readonly CREATE_MANY_SUCCESS: "storage.config.create.many.success";
|
|
90
|
-
readonly GET_SUCCESS: "storage.config.get.success";
|
|
91
|
-
readonly GET_ALL_SUCCESS: "storage.config.get.all.success";
|
|
92
|
-
readonly UPDATE_SUCCESS: "storage.config.update.success";
|
|
93
|
-
readonly UPDATE_MANY_SUCCESS: "storage.config.update.many.success";
|
|
94
|
-
readonly DELETE_SUCCESS: "storage.config.delete.success";
|
|
95
|
-
readonly RESTORE_SUCCESS: "storage.config.restore.success";
|
|
96
|
-
readonly NOT_FOUND: "storage.config.not.found";
|
|
97
|
-
readonly ACTIVE_SUCCESS: "storage.config.active.success";
|
|
98
|
-
readonly TEST_SUCCESS: "storage.config.test.success";
|
|
99
|
-
readonly TEST_FAILED: "storage.config.test.failed";
|
|
100
|
-
};
|
|
101
|
-
readonly UPLOAD: {
|
|
102
|
-
readonly SUCCESS: "upload.success";
|
|
103
|
-
readonly MANY_SUCCESS: "upload.many.success";
|
|
104
|
-
readonly FAILED: "upload.failed";
|
|
105
|
-
readonly FILE_TOO_LARGE: "upload.file.too.large";
|
|
106
|
-
readonly INVALID_TYPE: "upload.invalid.type";
|
|
107
|
-
readonly CHUNK_SUCCESS: "upload.chunk.success";
|
|
108
|
-
readonly COMPLETE_SUCCESS: "upload.complete.success";
|
|
109
|
-
readonly NO_FILES_PROVIDED: "upload.no.files.provided";
|
|
110
|
-
readonly NO_FILE_PATH: "upload.no.file.path";
|
|
111
|
-
readonly INVALID_FILE_PATH: "upload.invalid.file.path";
|
|
112
|
-
readonly CONFIG_NOT_FOUND: "upload.config.not.found";
|
|
113
|
-
};
|
|
114
|
-
};
|
|
@@ -1,64 +1,19 @@
|
|
|
1
1
|
// ==================== STORAGE MODULE MESSAGE KEYS ====================
|
|
2
2
|
export const FILE_MESSAGES = {
|
|
3
|
-
CREATE_SUCCESS: 'file.create.success',
|
|
4
|
-
CREATE_MANY_SUCCESS: 'file.create.many.success',
|
|
5
|
-
GET_SUCCESS: 'file.get.success',
|
|
6
3
|
GET_ALL_SUCCESS: 'file.get.all.success',
|
|
7
|
-
UPDATE_SUCCESS: 'file.update.success',
|
|
8
|
-
UPDATE_MANY_SUCCESS: 'file.update.many.success',
|
|
9
4
|
DELETE_SUCCESS: 'file.delete.success',
|
|
10
|
-
|
|
11
|
-
NOT_FOUND: 'file.not.found',
|
|
12
|
-
UPLOAD_SUCCESS: 'file.upload.success',
|
|
13
|
-
UPLOAD_MANY_SUCCESS: 'file.upload.many.success',
|
|
14
|
-
DOWNLOAD_SUCCESS: 'file.download.success',
|
|
15
|
-
MOVE_SUCCESS: 'file.move.success',
|
|
16
|
-
COPY_SUCCESS: 'file.copy.success'
|
|
5
|
+
NOT_FOUND: 'file.not.found'
|
|
17
6
|
};
|
|
18
7
|
export const FOLDER_MESSAGES = {
|
|
19
|
-
|
|
20
|
-
CREATE_MANY_SUCCESS: 'folder.create.many.success',
|
|
21
|
-
GET_SUCCESS: 'folder.get.success',
|
|
22
|
-
GET_ALL_SUCCESS: 'folder.get.all.success',
|
|
23
|
-
UPDATE_SUCCESS: 'folder.update.success',
|
|
24
|
-
UPDATE_MANY_SUCCESS: 'folder.update.many.success',
|
|
25
|
-
DELETE_SUCCESS: 'folder.delete.success',
|
|
26
|
-
RESTORE_SUCCESS: 'folder.restore.success',
|
|
27
|
-
NOT_FOUND: 'folder.not.found',
|
|
28
|
-
TREE_SUCCESS: 'folder.tree.success',
|
|
29
|
-
CONTENTS_SUCCESS: 'folder.contents.success'
|
|
30
|
-
};
|
|
31
|
-
export const STORAGE_CONFIG_MESSAGES = {
|
|
32
|
-
CREATE_SUCCESS: 'storage.config.create.success',
|
|
33
|
-
CREATE_MANY_SUCCESS: 'storage.config.create.many.success',
|
|
34
|
-
GET_SUCCESS: 'storage.config.get.success',
|
|
35
|
-
GET_ALL_SUCCESS: 'storage.config.get.all.success',
|
|
36
|
-
UPDATE_SUCCESS: 'storage.config.update.success',
|
|
37
|
-
UPDATE_MANY_SUCCESS: 'storage.config.update.many.success',
|
|
38
|
-
DELETE_SUCCESS: 'storage.config.delete.success',
|
|
39
|
-
RESTORE_SUCCESS: 'storage.config.restore.success',
|
|
40
|
-
NOT_FOUND: 'storage.config.not.found',
|
|
41
|
-
ACTIVE_SUCCESS: 'storage.config.active.success',
|
|
42
|
-
TEST_SUCCESS: 'storage.config.test.success',
|
|
43
|
-
TEST_FAILED: 'storage.config.test.failed'
|
|
8
|
+
NOT_FOUND: 'folder.not.found'
|
|
44
9
|
};
|
|
45
10
|
export const UPLOAD_MESSAGES = {
|
|
46
11
|
SUCCESS: 'upload.success',
|
|
47
12
|
MANY_SUCCESS: 'upload.many.success',
|
|
48
|
-
FAILED: 'upload.failed',
|
|
49
13
|
FILE_TOO_LARGE: 'upload.file.too.large',
|
|
50
14
|
INVALID_TYPE: 'upload.invalid.type',
|
|
51
|
-
CHUNK_SUCCESS: 'upload.chunk.success',
|
|
52
|
-
COMPLETE_SUCCESS: 'upload.complete.success',
|
|
53
15
|
NO_FILES_PROVIDED: 'upload.no.files.provided',
|
|
54
16
|
NO_FILE_PATH: 'upload.no.file.path',
|
|
55
17
|
INVALID_FILE_PATH: 'upload.invalid.file.path',
|
|
56
18
|
CONFIG_NOT_FOUND: 'upload.config.not.found'
|
|
57
19
|
};
|
|
58
|
-
// Aggregated export for backward compatibility
|
|
59
|
-
export const STORAGE_MODULE_MESSAGES = {
|
|
60
|
-
FILE: FILE_MESSAGES,
|
|
61
|
-
FOLDER: FOLDER_MESSAGES,
|
|
62
|
-
STORAGE_CONFIG: STORAGE_CONFIG_MESSAGES,
|
|
63
|
-
UPLOAD: UPLOAD_MESSAGES
|
|
64
|
-
};
|
|
@@ -26,12 +26,12 @@ function _ts_param(paramIndex, decorator) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
import { createApiController, STORAGE_CONFIG_PERMISSIONS } from '@flusys/nestjs-shared/classes';
|
|
29
|
-
import { CreateStorageConfigDto, StorageConfigResponseDto, UpdateStorageConfigDto } from '../dtos';
|
|
30
29
|
import { Controller, Inject } from '@nestjs/common';
|
|
31
30
|
import { ApiTags } from '@nestjs/swagger';
|
|
31
|
+
import { CreateStorageConfigDto, StorageConfigResponseDto, UpdateStorageConfigDto } from '../dtos';
|
|
32
32
|
import { StorageProviderConfigService } from '../services/storage-provider-config.service';
|
|
33
33
|
export class StorageConfigController extends createApiController(CreateStorageConfigDto, UpdateStorageConfigDto, StorageConfigResponseDto, {
|
|
34
|
-
entityName: '
|
|
34
|
+
entityName: 'storage.config',
|
|
35
35
|
security: {
|
|
36
36
|
insert: {
|
|
37
37
|
level: 'permission',
|
|
@@ -18,7 +18,8 @@ const COMPANY_SCHEMA_EXCLUSIONS = [
|
|
|
18
18
|
]
|
|
19
19
|
}
|
|
20
20
|
];
|
|
21
|
-
function buildDescription(enableCompanyFeature) {
|
|
21
|
+
function buildDescription(enableCompanyFeature, isMultiTenant) {
|
|
22
|
+
const multiTenantNote = isMultiTenant ? `\n> **Multi-Tenant Mode**: Include \`x-tenant-id\` header to target a specific tenant database.\n` : '';
|
|
22
23
|
const companyIsolation = enableCompanyFeature ? '\n- **Company isolation**' : '';
|
|
23
24
|
const companyPermissions = enableCompanyFeature ? '\n- **Company-level permissions**' : '';
|
|
24
25
|
const multiTenantSection = enableCompanyFeature ? `
|
|
@@ -46,7 +47,7 @@ POST /storage/folder/insert with JSON body containing folder name
|
|
|
46
47
|
` : '';
|
|
47
48
|
return `
|
|
48
49
|
# Storage Management API
|
|
49
|
-
|
|
50
|
+
${multiTenantNote}
|
|
50
51
|
Complete file storage and management system${enableCompanyFeature ? ' with multi-tenant support' : ''}.
|
|
51
52
|
|
|
52
53
|
## Features
|
|
@@ -167,9 +168,10 @@ All endpoints are rate-limited to prevent abuse. Default limits:
|
|
|
167
168
|
* Use this with setupSwaggerDocs() from @flusys/nestjs-core
|
|
168
169
|
*/ export function storageSwaggerConfig(bootstrapConfig) {
|
|
169
170
|
const enableCompanyFeature = bootstrapConfig?.enableCompanyFeature ?? true;
|
|
171
|
+
const isMultiTenant = bootstrapConfig?.databaseMode === 'multi-tenant';
|
|
170
172
|
return {
|
|
171
173
|
title: 'Storage API',
|
|
172
|
-
description: buildDescription(enableCompanyFeature),
|
|
174
|
+
description: buildDescription(enableCompanyFeature, isMultiTenant),
|
|
173
175
|
version: '1.0',
|
|
174
176
|
path: 'api/docs/storage',
|
|
175
177
|
bearerAuth: true,
|