@flusys/nestjs-storage 7.1.0 → 8.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/config/index.d.ts +3 -3
- package/controllers/file-manager.controller.d.ts +4 -4
- package/controllers/folder.controller.d.ts +2 -2
- package/controllers/index.d.ts +4 -4
- package/controllers/storage-config.controller.d.ts +2 -2
- package/controllers/upload.controller.d.ts +3 -3
- package/docs/index.d.ts +1 -1
- package/docs/storage-swagger.config.d.ts +2 -2
- package/dtos/index.d.ts +4 -4
- package/entities/file-manager-with-company.entity.d.ts +2 -2
- package/entities/file-manager.entity.d.ts +1 -1
- package/entities/folder-with-company.entity.d.ts +1 -1
- package/entities/index.d.ts +15 -15
- package/entities/storage-config-with-company.entity.d.ts +1 -1
- package/enums/index.d.ts +1 -1
- package/fesm/493.js +2768 -0
- package/fesm/537.js +1157 -0
- package/fesm/562.js +786 -0
- package/fesm/{providers/azure-provider.optional.js → chunks/190.js} +33 -30
- package/fesm/chunks/252.js +12 -0
- package/fesm/chunks/327.js +12 -0
- package/fesm/chunks/385.js +12 -0
- package/fesm/{providers/s3-provider.optional.js → chunks/591.js} +37 -34
- package/fesm/chunks/746.js +12 -0
- package/fesm/chunks/798.js +12 -0
- package/fesm/{providers/sftp-provider.optional.js → chunks/918.js} +35 -31
- package/fesm/config/index.js +119 -3
- package/fesm/controllers/index.js +16 -4
- package/fesm/docs/index.js +206 -1
- package/fesm/dtos/index.js +879 -4
- package/fesm/entities/index.js +463 -18
- package/fesm/enums/index.js +36 -1
- package/fesm/index.js +398 -12
- package/fesm/interfaces/index.js +19 -5
- package/fesm/modules/index.js +16 -1
- package/fesm/providers/index.js +364 -3
- package/fesm/runtime.js +252 -0
- package/fesm/services/index.js +16 -6
- package/fesm/utils/index.js +149 -1
- package/index.d.ts +11 -11
- package/interfaces/file-manager.interface.d.ts +1 -1
- package/interfaces/folder.interface.d.ts +1 -1
- package/interfaces/index.d.ts +5 -5
- package/interfaces/storage-config.interface.d.ts +1 -1
- package/interfaces/storage-module-options.interface.d.ts +3 -3
- package/interfaces/storage-provider.interface.d.ts +1 -1
- package/middlewares/file-serve.middleware.d.ts +4 -3
- package/middlewares/index.d.ts +1 -1
- package/modules/index.d.ts +1 -1
- package/modules/storage.module.d.ts +2 -2
- package/package.json +30 -41
- package/providers/azure-provider.optional.d.ts +2 -2
- package/providers/index.d.ts +3 -3
- package/providers/local-provider.d.ts +2 -2
- package/providers/s3-provider.optional.d.ts +2 -2
- package/providers/sftp-provider.optional.d.ts +2 -2
- package/providers/storage-factory.service.d.ts +3 -3
- package/providers/storage-provider.registry.d.ts +2 -2
- package/services/file-manager.service.d.ts +9 -8
- package/services/folder.service.d.ts +6 -6
- package/services/index.d.ts +6 -6
- package/services/storage-config.service.d.ts +3 -3
- package/services/storage-datasource.provider.d.ts +3 -3
- package/services/storage-provider-config.service.d.ts +7 -7
- package/services/upload.service.d.ts +6 -6
- package/utils/image-compressor.util.d.ts +1 -1
- package/utils/index.d.ts +1 -1
- package/cjs/config/event-actions.js +0 -34
- package/cjs/config/index.js +0 -20
- package/cjs/config/message-keys.js +0 -46
- package/cjs/config/storage.constants.js +0 -28
- package/cjs/controllers/file-manager.controller.js +0 -152
- package/cjs/controllers/file-manager.controller.spec.js +0 -135
- package/cjs/controllers/folder.controller.js +0 -102
- package/cjs/controllers/folder.controller.spec.js +0 -86
- package/cjs/controllers/index.js +0 -21
- package/cjs/controllers/storage-config.controller.js +0 -102
- package/cjs/controllers/storage-config.controller.spec.js +0 -85
- package/cjs/controllers/upload.controller.js +0 -234
- package/cjs/controllers/upload.controller.spec.js +0 -132
- package/cjs/docs/index.js +0 -11
- package/cjs/docs/storage-swagger.config.js +0 -188
- package/cjs/docs/storage-swagger.config.spec.js +0 -72
- package/cjs/dtos/file-manager.dto.js +0 -327
- package/cjs/dtos/folder.dto.js +0 -105
- package/cjs/dtos/index.js +0 -21
- package/cjs/dtos/storage-config.dto.js +0 -170
- package/cjs/dtos/upload.dto.js +0 -272
- package/cjs/entities/file-manager-with-company.entity.js +0 -61
- package/cjs/entities/file-manager.entity.js +0 -122
- package/cjs/entities/folder-with-company.entity.js +0 -55
- package/cjs/entities/folder.entity.js +0 -64
- package/cjs/entities/index.js +0 -63
- package/cjs/entities/index.spec.js +0 -18
- package/cjs/entities/storage-config-with-company.entity.js +0 -51
- package/cjs/entities/storage-config.entity.js +0 -96
- package/cjs/enums/file-location.enum.js +0 -17
- package/cjs/enums/index.js +0 -18
- package/cjs/index.js +0 -29
- package/cjs/interfaces/file-manager.interface.js +0 -4
- package/cjs/interfaces/folder.interface.js +0 -4
- package/cjs/interfaces/index.js +0 -22
- package/cjs/interfaces/storage-config.interface.js +0 -4
- package/cjs/interfaces/storage-module-options.interface.js +0 -4
- package/cjs/interfaces/storage-provider.interface.js +0 -4
- package/cjs/middlewares/file-serve.middleware.js +0 -241
- package/cjs/middlewares/file-serve.middleware.spec.js +0 -211
- package/cjs/middlewares/index.js +0 -18
- package/cjs/modules/index.js +0 -18
- package/cjs/modules/storage.module.js +0 -165
- package/cjs/modules/storage.module.spec.js +0 -184
- package/cjs/providers/azure-provider.optional.js +0 -155
- package/cjs/providers/azure-provider.optional.spec.js +0 -228
- package/cjs/providers/index.js +0 -26
- package/cjs/providers/local-provider.js +0 -230
- package/cjs/providers/local-provider.spec.js +0 -239
- package/cjs/providers/s3-provider.optional.js +0 -175
- package/cjs/providers/s3-provider.optional.spec.js +0 -243
- package/cjs/providers/sftp-provider.optional.js +0 -203
- package/cjs/providers/sftp-provider.optional.spec.js +0 -217
- package/cjs/providers/storage-factory.service.js +0 -175
- package/cjs/providers/storage-factory.service.spec.js +0 -253
- package/cjs/providers/storage-provider.registry.js +0 -41
- package/cjs/providers/storage-provider.registry.spec.js +0 -67
- package/cjs/services/file-manager.service.js +0 -387
- package/cjs/services/file-manager.service.spec.js +0 -580
- package/cjs/services/folder.service.js +0 -101
- package/cjs/services/folder.service.spec.js +0 -167
- package/cjs/services/index.js +0 -23
- package/cjs/services/storage-config.service.js +0 -129
- package/cjs/services/storage-config.service.spec.js +0 -257
- package/cjs/services/storage-datasource.provider.js +0 -137
- package/cjs/services/storage-datasource.provider.spec.js +0 -217
- package/cjs/services/storage-provider-config.service.js +0 -171
- package/cjs/services/storage-provider-config.service.spec.js +0 -265
- package/cjs/services/upload.service.js +0 -376
- package/cjs/services/upload.service.spec.js +0 -426
- package/cjs/utils/file-validator.util.js +0 -440
- package/cjs/utils/file-validator.util.spec.js +0 -259
- package/cjs/utils/image-compressor.util.js +0 -162
- package/cjs/utils/image-compressor.util.spec.js +0 -166
- package/cjs/utils/index.js +0 -18
- package/fesm/config/event-actions.js +0 -13
- package/fesm/config/message-keys.js +0 -22
- package/fesm/config/storage.constants.js +0 -7
- package/fesm/controllers/file-manager.controller.js +0 -142
- package/fesm/controllers/file-manager.controller.spec.js +0 -131
- package/fesm/controllers/folder.controller.js +0 -92
- package/fesm/controllers/folder.controller.spec.js +0 -82
- package/fesm/controllers/storage-config.controller.js +0 -92
- package/fesm/controllers/storage-config.controller.spec.js +0 -81
- package/fesm/controllers/upload.controller.js +0 -224
- package/fesm/controllers/upload.controller.spec.js +0 -128
- package/fesm/docs/storage-swagger.config.js +0 -181
- package/fesm/docs/storage-swagger.config.spec.js +0 -68
- package/fesm/dtos/file-manager.dto.js +0 -300
- package/fesm/dtos/folder.dto.js +0 -84
- package/fesm/dtos/storage-config.dto.js +0 -149
- package/fesm/dtos/upload.dto.js +0 -245
- package/fesm/entities/file-manager-with-company.entity.js +0 -51
- package/fesm/entities/file-manager.entity.js +0 -112
- package/fesm/entities/folder-with-company.entity.js +0 -45
- package/fesm/entities/folder.entity.js +0 -54
- package/fesm/entities/index.spec.js +0 -14
- package/fesm/entities/storage-config-with-company.entity.js +0 -41
- package/fesm/entities/storage-config.entity.js +0 -86
- package/fesm/enums/file-location.enum.js +0 -7
- package/fesm/interfaces/file-manager.interface.js +0 -1
- package/fesm/interfaces/folder.interface.js +0 -1
- package/fesm/interfaces/storage-config.interface.js +0 -1
- package/fesm/interfaces/storage-module-options.interface.js +0 -3
- package/fesm/interfaces/storage-provider.interface.js +0 -4
- package/fesm/middlewares/file-serve.middleware.js +0 -190
- package/fesm/middlewares/file-serve.middleware.spec.js +0 -207
- package/fesm/middlewares/index.js +0 -1
- package/fesm/modules/storage.module.js +0 -156
- package/fesm/modules/storage.module.spec.js +0 -180
- package/fesm/providers/azure-provider.optional.spec.js +0 -224
- package/fesm/providers/local-provider.js +0 -182
- package/fesm/providers/local-provider.spec.js +0 -194
- package/fesm/providers/s3-provider.optional.spec.js +0 -239
- package/fesm/providers/sftp-provider.optional.spec.js +0 -213
- package/fesm/providers/storage-factory.service.js +0 -124
- package/fesm/providers/storage-factory.service.spec.js +0 -249
- package/fesm/providers/storage-provider.registry.js +0 -34
- package/fesm/providers/storage-provider.registry.spec.js +0 -63
- package/fesm/services/file-manager.service.js +0 -336
- package/fesm/services/file-manager.service.spec.js +0 -576
- package/fesm/services/folder.service.js +0 -91
- package/fesm/services/folder.service.spec.js +0 -163
- package/fesm/services/storage-config.service.js +0 -119
- package/fesm/services/storage-config.service.spec.js +0 -253
- package/fesm/services/storage-datasource.provider.js +0 -86
- package/fesm/services/storage-datasource.provider.spec.js +0 -172
- package/fesm/services/storage-provider-config.service.js +0 -161
- package/fesm/services/storage-provider-config.service.spec.js +0 -261
- package/fesm/services/upload.service.js +0 -366
- package/fesm/services/upload.service.spec.js +0 -422
- package/fesm/utils/file-validator.util.js +0 -433
- package/fesm/utils/file-validator.util.spec.js +0 -255
- package/fesm/utils/image-compressor.util.js +0 -114
- package/fesm/utils/image-compressor.util.spec.js +0 -162
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
|
|
2
|
-
import { StorageDataSourceProvider } from './storage-datasource.provider';
|
|
3
|
-
import * as entities from '../entities';
|
|
4
|
-
function buildMockConfigService(overrides = {}) {
|
|
5
|
-
const options = {
|
|
6
|
-
bootstrapAppConfig: {
|
|
7
|
-
databaseMode: 'single',
|
|
8
|
-
enableCompanyFeature: false
|
|
9
|
-
},
|
|
10
|
-
config: {},
|
|
11
|
-
...overrides
|
|
12
|
-
};
|
|
13
|
-
return {
|
|
14
|
-
isCompanyFeatureEnabled: jest.fn().mockReturnValue(options.bootstrapAppConfig?.enableCompanyFeature ?? false),
|
|
15
|
-
getOptions: jest.fn().mockReturnValue(options)
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
describe('StorageDataSourceProvider', ()=>{
|
|
19
|
-
afterEach(()=>{
|
|
20
|
-
jest.restoreAllMocks();
|
|
21
|
-
});
|
|
22
|
-
describe('construction', ()=>{
|
|
23
|
-
it('propagates bootstrap options from StorageConfigService into the parent data-source service', ()=>{
|
|
24
|
-
const configService = buildMockConfigService({
|
|
25
|
-
bootstrapAppConfig: {
|
|
26
|
-
databaseMode: 'multi-tenant',
|
|
27
|
-
enableCompanyFeature: true
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
31
|
-
expect(provider.getDatabaseMode()).toBe('multi-tenant');
|
|
32
|
-
expect(provider.isMultiTenant()).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
it('defaults to single database mode when bootstrap config is absent', ()=>{
|
|
35
|
-
const configService = buildMockConfigService({
|
|
36
|
-
bootstrapAppConfig: undefined
|
|
37
|
-
});
|
|
38
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
39
|
-
expect(provider.getDatabaseMode()).toBe('single');
|
|
40
|
-
expect(provider.isMultiTenant()).toBe(false);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
describe('getEnableCompanyFeatureForTenant', ()=>{
|
|
44
|
-
it('uses the tenant-level override when provided', ()=>{
|
|
45
|
-
const configService = buildMockConfigService();
|
|
46
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
47
|
-
const result = provider.getEnableCompanyFeatureForTenant({
|
|
48
|
-
id: 'tenant-1',
|
|
49
|
-
enableCompanyFeature: true
|
|
50
|
-
});
|
|
51
|
-
expect(result).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
it('falls back to global config when tenant has no override', ()=>{
|
|
54
|
-
const configService = buildMockConfigService({
|
|
55
|
-
bootstrapAppConfig: {
|
|
56
|
-
databaseMode: 'single',
|
|
57
|
-
enableCompanyFeature: true
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
61
|
-
const result = provider.getEnableCompanyFeatureForTenant({
|
|
62
|
-
id: 'tenant-1'
|
|
63
|
-
});
|
|
64
|
-
expect(result).toBe(true);
|
|
65
|
-
});
|
|
66
|
-
it('falls back to global config when no tenant is provided', ()=>{
|
|
67
|
-
const configService = buildMockConfigService({
|
|
68
|
-
bootstrapAppConfig: {
|
|
69
|
-
databaseMode: 'single',
|
|
70
|
-
enableCompanyFeature: false
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
74
|
-
expect(provider.getEnableCompanyFeatureForTenant(undefined)).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
describe('getStorageEntities', ()=>{
|
|
78
|
-
it('returns company-scoped entities when company feature is enabled', async ()=>{
|
|
79
|
-
const configService = buildMockConfigService();
|
|
80
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
81
|
-
const result = await provider.getStorageEntities(true);
|
|
82
|
-
expect(result).toEqual([
|
|
83
|
-
entities.FileManagerWithCompany,
|
|
84
|
-
entities.FolderWithCompany,
|
|
85
|
-
entities.StorageConfigWithCompany
|
|
86
|
-
]);
|
|
87
|
-
});
|
|
88
|
-
it('returns core entities when company feature is disabled', async ()=>{
|
|
89
|
-
const configService = buildMockConfigService();
|
|
90
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
91
|
-
const result = await provider.getStorageEntities(false);
|
|
92
|
-
expect(result).toEqual([
|
|
93
|
-
entities.FileManager,
|
|
94
|
-
entities.Folder,
|
|
95
|
-
entities.StorageConfig
|
|
96
|
-
]);
|
|
97
|
-
});
|
|
98
|
-
it('falls back to the config service value when no explicit flag is passed', async ()=>{
|
|
99
|
-
const configService = buildMockConfigService({
|
|
100
|
-
bootstrapAppConfig: {
|
|
101
|
-
databaseMode: 'single',
|
|
102
|
-
enableCompanyFeature: true
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
106
|
-
const result = await provider.getStorageEntities();
|
|
107
|
-
expect(result).toEqual([
|
|
108
|
-
entities.FileManagerWithCompany,
|
|
109
|
-
entities.FolderWithCompany,
|
|
110
|
-
entities.StorageConfigWithCompany
|
|
111
|
-
]);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
describe('createDataSourceFromConfig', ()=>{
|
|
115
|
-
it('resolves storage entities for the current tenant/config and delegates to the parent implementation', async ()=>{
|
|
116
|
-
const configService = buildMockConfigService({
|
|
117
|
-
bootstrapAppConfig: {
|
|
118
|
-
databaseMode: 'single',
|
|
119
|
-
enableCompanyFeature: false
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
123
|
-
jest.spyOn(provider, 'getCurrentTenant').mockReturnValue(null);
|
|
124
|
-
const superCreateSpy = jest.spyOn(MultiTenantDataSourceService.prototype, 'createDataSourceFromConfig').mockResolvedValue({
|
|
125
|
-
isInitialized: true
|
|
126
|
-
});
|
|
127
|
-
const config = {
|
|
128
|
-
type: 'mysql',
|
|
129
|
-
host: 'localhost',
|
|
130
|
-
port: 3306,
|
|
131
|
-
username: 'root',
|
|
132
|
-
password: '',
|
|
133
|
-
database: 'test'
|
|
134
|
-
};
|
|
135
|
-
const result = await provider.createDataSourceFromConfig(config);
|
|
136
|
-
expect(superCreateSpy).toHaveBeenCalledWith(config, [
|
|
137
|
-
entities.FileManager,
|
|
138
|
-
entities.Folder,
|
|
139
|
-
entities.StorageConfig
|
|
140
|
-
]);
|
|
141
|
-
expect(result).toEqual({
|
|
142
|
-
isInitialized: true
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
it('uses the tenant enableCompanyFeature override to pick company-scoped entities', async ()=>{
|
|
146
|
-
const configService = buildMockConfigService({
|
|
147
|
-
bootstrapAppConfig: {
|
|
148
|
-
databaseMode: 'multi-tenant',
|
|
149
|
-
enableCompanyFeature: false
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
const provider = new StorageDataSourceProvider(configService);
|
|
153
|
-
jest.spyOn(provider, 'getCurrentTenant').mockReturnValue({
|
|
154
|
-
id: 'tenant-1',
|
|
155
|
-
enableCompanyFeature: true
|
|
156
|
-
});
|
|
157
|
-
const superCreateSpy = jest.spyOn(MultiTenantDataSourceService.prototype, 'createDataSourceFromConfig').mockResolvedValue({
|
|
158
|
-
isInitialized: true
|
|
159
|
-
});
|
|
160
|
-
const config = {
|
|
161
|
-
type: 'mysql',
|
|
162
|
-
database: 'tenant_db'
|
|
163
|
-
};
|
|
164
|
-
await provider.createDataSourceFromConfig(config);
|
|
165
|
-
expect(superCreateSpy).toHaveBeenCalledWith(config, [
|
|
166
|
-
entities.FileManagerWithCompany,
|
|
167
|
-
entities.FolderWithCompany,
|
|
168
|
-
entities.StorageConfigWithCompany
|
|
169
|
-
]);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
});
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
function _ts_metadata(k, v) {
|
|
21
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
-
}
|
|
23
|
-
function _ts_param(paramIndex, decorator) {
|
|
24
|
-
return function(target, key) {
|
|
25
|
-
decorator(target, key, paramIndex);
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
import { HybridCache, ApiService } from '@flusys/nestjs-shared/classes';
|
|
29
|
-
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
30
|
-
import { applyCompanyFilter, buildCompanyWhereCondition } from '@flusys/nestjs-shared/utils';
|
|
31
|
-
import { ForbiddenException, Inject, Injectable, Scope } from '@nestjs/common';
|
|
32
|
-
import { In, IsNull } from 'typeorm';
|
|
33
|
-
import { STORAGE_CONFIG_MESSAGES, STORAGE_EVENT_ENTITIES, STORAGE_EVENT_MODULE } from '../config';
|
|
34
|
-
import { StorageConfig, StorageConfigWithCompany } from '../entities';
|
|
35
|
-
import { StorageConfigService } from './storage-config.service';
|
|
36
|
-
import { StorageDataSourceProvider } from './storage-datasource.provider';
|
|
37
|
-
export class StorageProviderConfigService extends ApiService {
|
|
38
|
-
async beforeDeleteOperation(dto, _user, _queryRunner) {
|
|
39
|
-
const ids = Array.isArray(dto.id) ? dto.id : [
|
|
40
|
-
dto.id
|
|
41
|
-
];
|
|
42
|
-
await this.ensureDataSourceRepository();
|
|
43
|
-
const defaultConfigs = await this.repository.find({
|
|
44
|
-
where: {
|
|
45
|
-
id: In(ids),
|
|
46
|
-
isDefault: true,
|
|
47
|
-
deletedAt: IsNull()
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
if (defaultConfigs.length > 0) {
|
|
51
|
-
const names = defaultConfigs.map((c)=>c.name).join(', ');
|
|
52
|
-
throw new ForbiddenException({
|
|
53
|
-
message: `Cannot delete the default storage config(s): ${names}. Set another config as default first.`,
|
|
54
|
-
messageKey: STORAGE_CONFIG_MESSAGES.DEFAULT_DELETE_FORBIDDEN,
|
|
55
|
-
messageVariables: {
|
|
56
|
-
names
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// ─── Override Methods ───────────────────────────────────────────────────────
|
|
62
|
-
async convertSingleDtoToEntity(dto, user) {
|
|
63
|
-
const entity = await super.convertSingleDtoToEntity(dto, user);
|
|
64
|
-
if (this.storageConfig.isCompanyFeatureEnabled()) {
|
|
65
|
-
entity.companyId = user?.companyId ?? null;
|
|
66
|
-
}
|
|
67
|
-
return entity;
|
|
68
|
-
}
|
|
69
|
-
async getSelectQuery(query, _user, select) {
|
|
70
|
-
if (!select?.length) {
|
|
71
|
-
select = [
|
|
72
|
-
'id',
|
|
73
|
-
'name',
|
|
74
|
-
'storage',
|
|
75
|
-
'config',
|
|
76
|
-
'isActive',
|
|
77
|
-
'isDefault',
|
|
78
|
-
'createdAt',
|
|
79
|
-
'updatedAt'
|
|
80
|
-
];
|
|
81
|
-
if (this.storageConfig.isCompanyFeatureEnabled()) {
|
|
82
|
-
select.push('companyId');
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
query.select(select.map((f)=>`${this.entityName}.${f}`));
|
|
86
|
-
return {
|
|
87
|
-
query,
|
|
88
|
-
isRaw: false
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
async getExtraManipulateQuery(query, filterDto, user) {
|
|
92
|
-
const result = await super.getExtraManipulateQuery(query, filterDto, user);
|
|
93
|
-
applyCompanyFilter(query, {
|
|
94
|
-
isCompanyFeatureEnabled: this.storageConfig.isCompanyFeatureEnabled(),
|
|
95
|
-
entityAlias: 'storageConfig'
|
|
96
|
-
}, user);
|
|
97
|
-
query.orderBy(`${this.entityName}.createdAt`, 'DESC');
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
async findByIdDirect(id) {
|
|
101
|
-
await this.ensureDataSourceRepository();
|
|
102
|
-
return await this.repository.findOne({
|
|
103
|
-
where: {
|
|
104
|
-
id
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
async getDefaultConfig(user) {
|
|
109
|
-
await this.ensureDataSourceRepository();
|
|
110
|
-
const baseWhere = buildCompanyWhereCondition({
|
|
111
|
-
isActive: true
|
|
112
|
-
}, this.storageConfig.isCompanyFeatureEnabled(), user);
|
|
113
|
-
const defaultConfig = await this.repository.findOne({
|
|
114
|
-
where: {
|
|
115
|
-
...baseWhere,
|
|
116
|
-
isDefault: true
|
|
117
|
-
},
|
|
118
|
-
order: {
|
|
119
|
-
createdAt: 'ASC'
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
if (defaultConfig) {
|
|
123
|
-
return defaultConfig;
|
|
124
|
-
}
|
|
125
|
-
return await this.repository.findOne({
|
|
126
|
-
where: baseWhere,
|
|
127
|
-
order: {
|
|
128
|
-
createdAt: 'ASC'
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
async getConfigByType(storage, user) {
|
|
133
|
-
await this.ensureDataSourceRepository();
|
|
134
|
-
const where = buildCompanyWhereCondition({
|
|
135
|
-
storage,
|
|
136
|
-
isActive: true
|
|
137
|
-
}, this.storageConfig.isCompanyFeatureEnabled(), user);
|
|
138
|
-
return await this.repository.find({
|
|
139
|
-
where
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
|
|
143
|
-
super(STORAGE_EVENT_ENTITIES.STORAGE_CONFIG, cacheManager, utilsService, StorageProviderConfigService.name, true, STORAGE_EVENT_MODULE, dataSourceProvider, storageConfig.isCompanyFeatureEnabled() ? StorageConfigWithCompany : StorageConfig), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
StorageProviderConfigService = _ts_decorate([
|
|
147
|
-
Injectable({
|
|
148
|
-
scope: Scope.REQUEST
|
|
149
|
-
}),
|
|
150
|
-
_ts_param(0, Inject('CACHE_INSTANCE')),
|
|
151
|
-
_ts_param(1, Inject(UtilsService)),
|
|
152
|
-
_ts_param(2, Inject(StorageConfigService)),
|
|
153
|
-
_ts_param(3, Inject(StorageDataSourceProvider)),
|
|
154
|
-
_ts_metadata("design:type", Function),
|
|
155
|
-
_ts_metadata("design:paramtypes", [
|
|
156
|
-
typeof HybridCache === "undefined" ? Object : HybridCache,
|
|
157
|
-
typeof UtilsService === "undefined" ? Object : UtilsService,
|
|
158
|
-
typeof StorageConfigService === "undefined" ? Object : StorageConfigService,
|
|
159
|
-
typeof StorageDataSourceProvider === "undefined" ? Object : StorageDataSourceProvider
|
|
160
|
-
])
|
|
161
|
-
], StorageProviderConfigService);
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import { Test } from '@nestjs/testing';
|
|
2
|
-
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
3
|
-
import { createMockDataSourceProvider, createMockRepository } from '@test-utils/mocks/repository.mock';
|
|
4
|
-
import { buildMockUser } from '@test-utils/mocks/logged-user.mock';
|
|
5
|
-
import { StorageProviderConfigService } from './storage-provider-config.service';
|
|
6
|
-
import { StorageConfigService } from './storage-config.service';
|
|
7
|
-
import { StorageDataSourceProvider } from './storage-datasource.provider';
|
|
8
|
-
import { StorageConfig, StorageConfigWithCompany } from '../entities';
|
|
9
|
-
function buildStorageConfig(overrides = {}) {
|
|
10
|
-
return {
|
|
11
|
-
id: 'config-uuid-1',
|
|
12
|
-
name: 'Default Local',
|
|
13
|
-
storage: 'local',
|
|
14
|
-
config: {
|
|
15
|
-
basePath: './uploads'
|
|
16
|
-
},
|
|
17
|
-
isActive: true,
|
|
18
|
-
isDefault: false,
|
|
19
|
-
createdAt: new Date(),
|
|
20
|
-
updatedAt: new Date(),
|
|
21
|
-
deletedAt: null,
|
|
22
|
-
createdById: null,
|
|
23
|
-
updatedById: null,
|
|
24
|
-
deletedById: null,
|
|
25
|
-
...overrides
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
describe('StorageProviderConfigService', ()=>{
|
|
29
|
-
let service;
|
|
30
|
-
let module;
|
|
31
|
-
let mockRepo;
|
|
32
|
-
let mockStorageConfig;
|
|
33
|
-
beforeEach(async ()=>{
|
|
34
|
-
mockRepo = createMockRepository();
|
|
35
|
-
const mockDataSourceProvider = createMockDataSourceProvider(mockRepo);
|
|
36
|
-
mockStorageConfig = {
|
|
37
|
-
isCompanyFeatureEnabled: jest.fn().mockReturnValue(false),
|
|
38
|
-
getAppUrl: jest.fn().mockReturnValue('http://localhost:2002')
|
|
39
|
-
};
|
|
40
|
-
module = await Test.createTestingModule({
|
|
41
|
-
providers: [
|
|
42
|
-
StorageProviderConfigService,
|
|
43
|
-
{
|
|
44
|
-
provide: 'CACHE_INSTANCE',
|
|
45
|
-
useValue: {}
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
provide: UtilsService,
|
|
49
|
-
useValue: {}
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
provide: StorageConfigService,
|
|
53
|
-
useValue: mockStorageConfig
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
provide: StorageDataSourceProvider,
|
|
57
|
-
useValue: mockDataSourceProvider
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
}).compile();
|
|
61
|
-
service = await module.resolve(StorageProviderConfigService);
|
|
62
|
-
});
|
|
63
|
-
describe('entity selection', ()=>{
|
|
64
|
-
it('uses StorageConfig when the company feature is disabled', async ()=>{
|
|
65
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(false);
|
|
66
|
-
const built = await module.resolve(StorageProviderConfigService);
|
|
67
|
-
expect(built['_entity']).toBe(StorageConfig);
|
|
68
|
-
});
|
|
69
|
-
it('uses StorageConfigWithCompany when the company feature is enabled', async ()=>{
|
|
70
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
71
|
-
const built = await module.resolve(StorageProviderConfigService);
|
|
72
|
-
expect(built['_entity']).toBe(StorageConfigWithCompany);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
describe('convertSingleDtoToEntity', ()=>{
|
|
76
|
-
beforeEach(async ()=>{
|
|
77
|
-
mockRepo.create.mockReturnValue({});
|
|
78
|
-
await service.ensureDataSourceRepository();
|
|
79
|
-
});
|
|
80
|
-
it('does not attach companyId when the company feature is disabled', async ()=>{
|
|
81
|
-
const entity = await service.convertSingleDtoToEntity({
|
|
82
|
-
name: 'AWS S3',
|
|
83
|
-
storage: 'aws',
|
|
84
|
-
config: {}
|
|
85
|
-
}, buildMockUser());
|
|
86
|
-
expect(entity.companyId).toBeUndefined();
|
|
87
|
-
});
|
|
88
|
-
it('attaches the current user companyId when the company feature is enabled', async ()=>{
|
|
89
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
90
|
-
const entity = await service.convertSingleDtoToEntity({
|
|
91
|
-
name: 'AWS S3',
|
|
92
|
-
storage: 'aws',
|
|
93
|
-
config: {}
|
|
94
|
-
}, buildMockUser({
|
|
95
|
-
companyId: 'company-42'
|
|
96
|
-
}));
|
|
97
|
-
expect(entity.companyId).toBe('company-42');
|
|
98
|
-
});
|
|
99
|
-
it('defaults companyId to null when company feature is enabled but user has none', async ()=>{
|
|
100
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
101
|
-
const entity = await service.convertSingleDtoToEntity({
|
|
102
|
-
name: 'AWS S3',
|
|
103
|
-
storage: 'aws',
|
|
104
|
-
config: {}
|
|
105
|
-
}, null);
|
|
106
|
-
expect(entity.companyId).toBeNull();
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
describe('getSelectQuery', ()=>{
|
|
110
|
-
it('selects the default field set when none is provided', async ()=>{
|
|
111
|
-
const query = {
|
|
112
|
-
select: jest.fn().mockReturnThis()
|
|
113
|
-
};
|
|
114
|
-
await service.getSelectQuery(query, buildMockUser());
|
|
115
|
-
expect(query.select).toHaveBeenCalledWith([
|
|
116
|
-
'storageConfig.id',
|
|
117
|
-
'storageConfig.name',
|
|
118
|
-
'storageConfig.storage',
|
|
119
|
-
'storageConfig.config',
|
|
120
|
-
'storageConfig.isActive',
|
|
121
|
-
'storageConfig.isDefault',
|
|
122
|
-
'storageConfig.createdAt',
|
|
123
|
-
'storageConfig.updatedAt'
|
|
124
|
-
]);
|
|
125
|
-
});
|
|
126
|
-
it('adds companyId to the default select list when company feature is enabled', async ()=>{
|
|
127
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
128
|
-
const query = {
|
|
129
|
-
select: jest.fn().mockReturnThis()
|
|
130
|
-
};
|
|
131
|
-
await service.getSelectQuery(query, buildMockUser());
|
|
132
|
-
const selected = query.select.mock.calls[0][0];
|
|
133
|
-
expect(selected).toContain('storageConfig.companyId');
|
|
134
|
-
});
|
|
135
|
-
it('respects an explicitly provided select list', async ()=>{
|
|
136
|
-
const query = {
|
|
137
|
-
select: jest.fn().mockReturnThis()
|
|
138
|
-
};
|
|
139
|
-
await service.getSelectQuery(query, buildMockUser(), [
|
|
140
|
-
'id',
|
|
141
|
-
'name'
|
|
142
|
-
]);
|
|
143
|
-
expect(query.select).toHaveBeenCalledWith([
|
|
144
|
-
'storageConfig.id',
|
|
145
|
-
'storageConfig.name'
|
|
146
|
-
]);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
describe('findByIdDirect', ()=>{
|
|
150
|
-
it('bypasses company filtering and returns the raw entity by id', async ()=>{
|
|
151
|
-
const config = buildStorageConfig();
|
|
152
|
-
mockRepo.findOne.mockResolvedValue(config);
|
|
153
|
-
const result = await service.findByIdDirect('config-uuid-1');
|
|
154
|
-
expect(mockRepo.findOne).toHaveBeenCalledWith({
|
|
155
|
-
where: {
|
|
156
|
-
id: 'config-uuid-1'
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
expect(result).toEqual(config);
|
|
160
|
-
});
|
|
161
|
-
it('returns null when no config exists for the given id', async ()=>{
|
|
162
|
-
mockRepo.findOne.mockResolvedValue(null);
|
|
163
|
-
const result = await service.findByIdDirect('missing-id');
|
|
164
|
-
expect(result).toBeNull();
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
describe('getDefaultConfig', ()=>{
|
|
168
|
-
it('returns the config explicitly flagged isDefault when one exists', async ()=>{
|
|
169
|
-
const defaultConfig = buildStorageConfig({
|
|
170
|
-
id: 'default-1',
|
|
171
|
-
isDefault: true
|
|
172
|
-
});
|
|
173
|
-
mockRepo.findOne.mockResolvedValueOnce(defaultConfig);
|
|
174
|
-
const result = await service.getDefaultConfig(buildMockUser());
|
|
175
|
-
expect(result).toEqual(defaultConfig);
|
|
176
|
-
expect(mockRepo.findOne).toHaveBeenCalledTimes(1);
|
|
177
|
-
});
|
|
178
|
-
it('falls back to the oldest active config when no default is flagged', async ()=>{
|
|
179
|
-
const fallbackConfig = buildStorageConfig({
|
|
180
|
-
id: 'fallback-1'
|
|
181
|
-
});
|
|
182
|
-
mockRepo.findOne.mockResolvedValueOnce(null).mockResolvedValueOnce(fallbackConfig);
|
|
183
|
-
const result = await service.getDefaultConfig(buildMockUser());
|
|
184
|
-
expect(result).toEqual(fallbackConfig);
|
|
185
|
-
expect(mockRepo.findOne).toHaveBeenCalledTimes(2);
|
|
186
|
-
});
|
|
187
|
-
it('returns null when there is no default and no active config at all', async ()=>{
|
|
188
|
-
mockRepo.findOne.mockResolvedValue(null);
|
|
189
|
-
const result = await service.getDefaultConfig(buildMockUser());
|
|
190
|
-
expect(result).toBeNull();
|
|
191
|
-
});
|
|
192
|
-
it('scopes the query to the user company when company feature is enabled', async ()=>{
|
|
193
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
194
|
-
mockRepo.findOne.mockResolvedValue(null);
|
|
195
|
-
await service.getDefaultConfig(buildMockUser({
|
|
196
|
-
companyId: 'company-9'
|
|
197
|
-
}));
|
|
198
|
-
expect(mockRepo.findOne).toHaveBeenCalledWith(expect.objectContaining({
|
|
199
|
-
where: expect.objectContaining({
|
|
200
|
-
companyId: 'company-9',
|
|
201
|
-
isActive: true
|
|
202
|
-
})
|
|
203
|
-
}));
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
describe('getConfigByType', ()=>{
|
|
207
|
-
it('returns active configs matching the requested storage type', async ()=>{
|
|
208
|
-
const localConfigs = [
|
|
209
|
-
buildStorageConfig({
|
|
210
|
-
storage: 'local'
|
|
211
|
-
})
|
|
212
|
-
];
|
|
213
|
-
mockRepo.find.mockResolvedValue(localConfigs);
|
|
214
|
-
const result = await service.getConfigByType('local', buildMockUser());
|
|
215
|
-
expect(mockRepo.find).toHaveBeenCalledWith({
|
|
216
|
-
where: {
|
|
217
|
-
storage: 'local',
|
|
218
|
-
isActive: true
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
expect(result).toEqual(localConfigs);
|
|
222
|
-
});
|
|
223
|
-
it('scopes the lookup to the current company when company feature is enabled', async ()=>{
|
|
224
|
-
mockStorageConfig.isCompanyFeatureEnabled.mockReturnValue(true);
|
|
225
|
-
mockRepo.find.mockResolvedValue([]);
|
|
226
|
-
await service.getConfigByType('aws', buildMockUser({
|
|
227
|
-
companyId: 'company-5'
|
|
228
|
-
}));
|
|
229
|
-
expect(mockRepo.find).toHaveBeenCalledWith({
|
|
230
|
-
where: {
|
|
231
|
-
storage: 'aws',
|
|
232
|
-
isActive: true,
|
|
233
|
-
companyId: 'company-5'
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
it('returns an empty array when no configs match', async ()=>{
|
|
238
|
-
mockRepo.find.mockResolvedValue([]);
|
|
239
|
-
const result = await service.getConfigByType('azure');
|
|
240
|
-
expect(result).toEqual([]);
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
describe('beforeDeleteOperation', ()=>{
|
|
244
|
-
it('rejects deleting the default storage config', async ()=>{
|
|
245
|
-
mockRepo.find.mockResolvedValue([
|
|
246
|
-
buildStorageConfig({
|
|
247
|
-
isDefault: true
|
|
248
|
-
})
|
|
249
|
-
]);
|
|
250
|
-
await expect(service.beforeDeleteOperation({
|
|
251
|
-
id: 'config-uuid-1'
|
|
252
|
-
}, null, {})).rejects.toThrow('Cannot delete the default storage config');
|
|
253
|
-
});
|
|
254
|
-
it('allows deleting a non-default storage config', async ()=>{
|
|
255
|
-
mockRepo.find.mockResolvedValue([]);
|
|
256
|
-
await expect(service.beforeDeleteOperation({
|
|
257
|
-
id: 'config-uuid-1'
|
|
258
|
-
}, null, {})).resolves.toBeUndefined();
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
});
|