@flusys/nestjs-auth 1.1.0-beta → 1.1.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 +633 -468
- package/cjs/config/auth.constants.js +8 -0
- package/cjs/controllers/authentication.controller.js +175 -167
- package/cjs/controllers/branch.controller.js +44 -1
- package/cjs/controllers/company-selection.controller.js +27 -20
- package/cjs/controllers/company.controller.js +44 -1
- package/cjs/controllers/email-verification.controller.js +220 -0
- package/cjs/controllers/index.js +1 -0
- package/cjs/controllers/user-permission.controller.js +82 -154
- package/cjs/controllers/user.controller.js +68 -15
- package/cjs/docs/auth-swagger.config.js +14 -7
- package/cjs/dtos/authentication.dto.js +16 -43
- package/cjs/dtos/index.js +0 -1
- package/cjs/dtos/user-permission.dto.js +28 -0
- package/cjs/dtos/user.dto.js +19 -4
- package/cjs/entities/index.js +16 -17
- package/cjs/entities/user-company-permission.entity.js +3 -9
- package/cjs/interceptors/clear-token.interceptor.js +10 -23
- package/cjs/interceptors/set-token.interceptor.js +15 -55
- package/cjs/interfaces/auth-email-provider.interface.js +1 -1
- package/cjs/modules/auth.module.js +79 -154
- package/cjs/services/auth-config.service.js +33 -35
- package/cjs/services/auth-datasource.provider.js +18 -42
- package/cjs/services/auth-email.service.js +89 -85
- package/cjs/services/authentication.service.js +248 -414
- package/cjs/services/branch.service.js +9 -4
- package/cjs/services/company-selection-session.service.js +1 -1
- package/cjs/services/user-permission.service.js +43 -73
- package/cjs/services/user.service.js +78 -64
- package/cjs/strategies/jwt.strategy.js +44 -44
- package/cjs/validators/password.validator.js +45 -0
- package/config/auth.constants.d.ts +2 -0
- package/controllers/authentication.controller.d.ts +4 -10
- package/controllers/company-selection.controller.d.ts +6 -2
- package/controllers/email-verification.controller.d.ts +20 -0
- package/controllers/index.d.ts +1 -0
- package/controllers/user-permission.controller.d.ts +5 -4
- package/controllers/user.controller.d.ts +6 -0
- package/dtos/authentication.dto.d.ts +0 -4
- package/dtos/company-branch.dto.d.ts +0 -1
- package/dtos/company.dto.d.ts +0 -1
- package/dtos/index.d.ts +0 -1
- package/dtos/user-permission.dto.d.ts +4 -0
- package/dtos/user.dto.d.ts +1 -3
- package/entities/index.d.ts +5 -10
- package/entities/user-company-permission.entity.d.ts +1 -3
- package/fesm/config/auth.constants.js +6 -13
- package/fesm/controllers/authentication.controller.js +178 -170
- package/fesm/controllers/branch.controller.js +45 -2
- package/fesm/controllers/company-selection.controller.js +28 -21
- package/fesm/controllers/company.controller.js +45 -2
- package/fesm/controllers/email-verification.controller.js +210 -0
- package/fesm/controllers/index.js +1 -0
- package/fesm/controllers/user-permission.controller.js +84 -156
- package/fesm/controllers/user.controller.js +71 -18
- package/fesm/docs/auth-swagger.config.js +14 -7
- package/fesm/dtos/authentication.dto.js +17 -44
- package/fesm/dtos/index.js +0 -1
- package/fesm/dtos/user-permission.dto.js +28 -0
- package/fesm/dtos/user.dto.js +20 -5
- package/fesm/entities/index.js +17 -9
- package/fesm/entities/user-company-permission.entity.js +3 -9
- package/fesm/interceptors/clear-token.interceptor.js +9 -22
- package/fesm/interceptors/set-token.interceptor.js +14 -54
- package/fesm/interfaces/auth-email-provider.interface.js +1 -1
- package/fesm/modules/auth.module.js +82 -157
- package/fesm/services/auth-config.service.js +34 -36
- package/fesm/services/auth-datasource.provider.js +19 -43
- package/fesm/services/auth-email.service.js +90 -86
- package/fesm/services/authentication.service.js +248 -414
- package/fesm/services/branch.service.js +9 -4
- package/fesm/services/company-selection-session.service.js +1 -1
- package/fesm/services/user-permission.service.js +44 -74
- package/fesm/services/user.service.js +79 -65
- package/fesm/strategies/jwt.strategy.js +44 -44
- package/fesm/validators/password.validator.js +48 -0
- package/interceptors/clear-token.interceptor.d.ts +0 -1
- package/interceptors/set-token.interceptor.d.ts +1 -1
- package/interfaces/authentication.interface.d.ts +0 -4
- package/interfaces/user-enricher.interface.d.ts +1 -4
- package/modules/auth.module.d.ts +9 -4
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +7 -8
- package/services/auth-datasource.provider.d.ts +3 -4
- package/services/auth-email.service.d.ts +8 -4
- package/services/authentication.service.d.ts +16 -16
- package/services/company-selection-session.service.d.ts +1 -1
- package/services/user-permission.service.d.ts +6 -9
- package/services/user.service.d.ts +3 -0
- package/strategies/jwt.strategy.d.ts +4 -1
- package/validators/password.validator.d.ts +10 -0
- package/cjs/dtos/user-company-permission.dto.js +0 -110
- package/dtos/user-company-permission.dto.d.ts +0 -10
- package/fesm/dtos/user-company-permission.dto.js +0 -98
|
@@ -5,98 +5,63 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
7
|
import { CacheModule, UtilsModule } from '@flusys/nestjs-shared/modules';
|
|
8
|
-
import { Module
|
|
8
|
+
import { Module } from '@nestjs/common';
|
|
9
9
|
import { JwtModule } from '@nestjs/jwt';
|
|
10
10
|
import { PassportModule } from '@nestjs/passport';
|
|
11
|
-
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
12
|
-
import { AuthConfigService } from '../services/auth-config.service';
|
|
13
|
-
import { AuthDataSourceProvider } from '../services/auth-datasource.provider';
|
|
14
|
-
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
15
|
-
import { AuthenticationController, BranchController, CompanyController, CompanySelectionController, UserController, UserPermissionController } from '../controllers';
|
|
16
|
-
import { Company, CompanyBranch, User, UserCompanyPermission } from '../entities';
|
|
17
11
|
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
|
|
12
|
+
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
13
|
+
import { AuthenticationController, BranchController, CompanyController, CompanySelectionController, EmailVerificationController, UserController, UserPermissionController } from '../controllers';
|
|
14
|
+
import { getEntitiesByConfig } from '../entities';
|
|
18
15
|
import { ClearToken } from '../interceptors/clear-token.interceptor';
|
|
19
16
|
import { SetToken } from '../interceptors/set-token.interceptor';
|
|
20
17
|
import { AuthEmailService, AuthenticationService, BranchService, CompanySelectionSessionService, CompanyService, UserPermissionService, UserService } from '../services';
|
|
18
|
+
import { AuthConfigService } from '../services/auth-config.service';
|
|
19
|
+
import { AuthDataSourceProvider } from '../services/auth-datasource.provider';
|
|
21
20
|
import { JwtStrategy } from '../strategies/jwt.strategy';
|
|
22
21
|
export class AuthModule {
|
|
23
22
|
static forRoot(options) {
|
|
24
|
-
|
|
23
|
+
const optionsProvider = {
|
|
24
|
+
provide: AUTH_MODULE_OPTIONS,
|
|
25
|
+
useValue: options
|
|
26
|
+
};
|
|
27
|
+
return this.buildModule(options, [
|
|
28
|
+
optionsProvider,
|
|
29
|
+
...options.providers ?? []
|
|
30
|
+
]);
|
|
25
31
|
}
|
|
26
|
-
static forRootAsync(
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
// Build imports
|
|
30
|
-
const imports = [
|
|
31
|
-
...externalImports,
|
|
32
|
-
PassportModule.register({
|
|
33
|
-
defaultStrategy: 'jwt'
|
|
34
|
-
}),
|
|
35
|
-
JwtModule.register({}),
|
|
36
|
-
CacheModule,
|
|
37
|
-
UtilsModule
|
|
38
|
-
];
|
|
39
|
-
// Build controllers based on configuration
|
|
40
|
-
const controllers = [];
|
|
41
|
-
if (includeController) {
|
|
42
|
-
// Core authentication controller (always included)
|
|
43
|
-
controllers.push(AuthenticationController);
|
|
44
|
-
// User controller (always included)
|
|
45
|
-
controllers.push(UserController);
|
|
46
|
-
// Company feature controllers (conditional)
|
|
47
|
-
if (enableCompanyFeature) {
|
|
48
|
-
controllers.push(CompanySelectionController, CompanyController, BranchController, UserPermissionController);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Build providers
|
|
52
|
-
const providers = [
|
|
32
|
+
static forRootAsync(options) {
|
|
33
|
+
const asyncProviders = this.createAsyncProviders(options);
|
|
34
|
+
return this.buildModule(options, [
|
|
53
35
|
...asyncProviders,
|
|
54
|
-
...
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
JwtAuthGuard,
|
|
61
|
-
AuthenticationService,
|
|
62
|
-
AuthEmailService,
|
|
63
|
-
// Interceptors
|
|
64
|
-
SetToken,
|
|
65
|
-
ClearToken,
|
|
66
|
-
// Core services (always included)
|
|
67
|
-
UserService
|
|
68
|
-
];
|
|
69
|
-
// Company feature services (conditional)
|
|
70
|
-
if (enableCompanyFeature) {
|
|
71
|
-
providers.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
72
|
-
}
|
|
73
|
-
// Build exports
|
|
74
|
-
const exports = [
|
|
75
|
-
PassportModule,
|
|
76
|
-
AUTH_MODULE_OPTIONS,
|
|
77
|
-
AuthConfigService,
|
|
78
|
-
AuthDataSourceProvider,
|
|
79
|
-
JwtStrategy,
|
|
80
|
-
JwtAuthGuard,
|
|
81
|
-
AuthenticationService,
|
|
82
|
-
AuthEmailService,
|
|
83
|
-
UserService
|
|
84
|
-
];
|
|
85
|
-
if (enableCompanyFeature) {
|
|
86
|
-
exports.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
87
|
-
}
|
|
36
|
+
...options.providers ?? []
|
|
37
|
+
], options.imports);
|
|
38
|
+
}
|
|
39
|
+
static buildModule(options, providers, externalImports = []) {
|
|
40
|
+
const { global = false, includeController = true, bootstrapAppConfig } = options;
|
|
41
|
+
const featureFlags = this.getFeatureFlags(bootstrapAppConfig);
|
|
88
42
|
return {
|
|
89
43
|
module: AuthModule,
|
|
90
44
|
global,
|
|
91
|
-
imports
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
45
|
+
imports: [
|
|
46
|
+
...externalImports,
|
|
47
|
+
...this.buildImports()
|
|
48
|
+
],
|
|
49
|
+
controllers: this.buildControllers(includeController, featureFlags),
|
|
50
|
+
providers: [
|
|
51
|
+
...providers,
|
|
52
|
+
...this.buildProviders(featureFlags)
|
|
53
|
+
],
|
|
54
|
+
exports: this.buildExports(featureFlags)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
static getFeatureFlags(bootstrapAppConfig) {
|
|
58
|
+
return {
|
|
59
|
+
enableCompanyFeature: bootstrapAppConfig?.enableCompanyFeature ?? false,
|
|
60
|
+
enableEmailVerification: bootstrapAppConfig?.enableEmailVerification ?? true
|
|
95
61
|
};
|
|
96
62
|
}
|
|
97
|
-
static
|
|
98
|
-
|
|
99
|
-
const imports = [
|
|
63
|
+
static buildImports() {
|
|
64
|
+
return [
|
|
100
65
|
PassportModule.register({
|
|
101
66
|
defaultStrategy: 'jwt'
|
|
102
67
|
}),
|
|
@@ -104,42 +69,41 @@ export class AuthModule {
|
|
|
104
69
|
CacheModule,
|
|
105
70
|
UtilsModule
|
|
106
71
|
];
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (includeController)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
controllers.push(CompanySelectionController, CompanyController, BranchController, UserPermissionController);
|
|
117
|
-
}
|
|
72
|
+
}
|
|
73
|
+
static buildControllers(includeController, flags) {
|
|
74
|
+
if (!includeController) return [];
|
|
75
|
+
const controllers = [
|
|
76
|
+
AuthenticationController,
|
|
77
|
+
UserController
|
|
78
|
+
];
|
|
79
|
+
if (flags.enableEmailVerification) {
|
|
80
|
+
controllers.push(EmailVerificationController);
|
|
118
81
|
}
|
|
82
|
+
if (flags.enableCompanyFeature) {
|
|
83
|
+
controllers.push(CompanySelectionController, CompanyController, BranchController, UserPermissionController);
|
|
84
|
+
}
|
|
85
|
+
return controllers;
|
|
86
|
+
}
|
|
87
|
+
static buildProviders(flags) {
|
|
119
88
|
const providers = [
|
|
120
|
-
{
|
|
121
|
-
provide: AUTH_MODULE_OPTIONS,
|
|
122
|
-
useValue: options
|
|
123
|
-
},
|
|
124
|
-
...additionalProviders,
|
|
125
|
-
// Config & Infrastructure
|
|
126
89
|
AuthConfigService,
|
|
127
90
|
AuthDataSourceProvider,
|
|
128
|
-
// Auth core
|
|
129
91
|
JwtStrategy,
|
|
130
92
|
JwtAuthGuard,
|
|
131
93
|
AuthenticationService,
|
|
132
|
-
AuthEmailService,
|
|
133
|
-
// Interceptors
|
|
134
94
|
SetToken,
|
|
135
95
|
ClearToken,
|
|
136
|
-
// Core services (always included)
|
|
137
96
|
UserService
|
|
138
97
|
];
|
|
139
|
-
|
|
140
|
-
|
|
98
|
+
if (flags.enableEmailVerification) {
|
|
99
|
+
providers.push(AuthEmailService);
|
|
100
|
+
}
|
|
101
|
+
if (flags.enableCompanyFeature) {
|
|
141
102
|
providers.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
142
103
|
}
|
|
104
|
+
return providers;
|
|
105
|
+
}
|
|
106
|
+
static buildExports(flags) {
|
|
143
107
|
const exports = [
|
|
144
108
|
PassportModule,
|
|
145
109
|
AUTH_MODULE_OPTIONS,
|
|
@@ -148,20 +112,15 @@ export class AuthModule {
|
|
|
148
112
|
JwtStrategy,
|
|
149
113
|
JwtAuthGuard,
|
|
150
114
|
AuthenticationService,
|
|
151
|
-
AuthEmailService,
|
|
152
115
|
UserService
|
|
153
116
|
];
|
|
154
|
-
if (
|
|
117
|
+
if (flags.enableEmailVerification) {
|
|
118
|
+
exports.push(AuthEmailService);
|
|
119
|
+
}
|
|
120
|
+
if (flags.enableCompanyFeature) {
|
|
155
121
|
exports.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
156
122
|
}
|
|
157
|
-
return
|
|
158
|
-
module: AuthModule,
|
|
159
|
-
global,
|
|
160
|
-
imports,
|
|
161
|
-
controllers,
|
|
162
|
-
providers,
|
|
163
|
-
exports
|
|
164
|
-
};
|
|
123
|
+
return exports;
|
|
165
124
|
}
|
|
166
125
|
static createAsyncProviders(options) {
|
|
167
126
|
const staticOptions = {
|
|
@@ -173,13 +132,10 @@ export class AuthModule {
|
|
|
173
132
|
return [
|
|
174
133
|
{
|
|
175
134
|
provide: AUTH_MODULE_OPTIONS,
|
|
176
|
-
useFactory: async (...args)=>{
|
|
177
|
-
const config = await options.useFactory(...args);
|
|
178
|
-
return {
|
|
135
|
+
useFactory: async (...args)=>({
|
|
179
136
|
...staticOptions,
|
|
180
|
-
config
|
|
181
|
-
}
|
|
182
|
-
},
|
|
137
|
+
config: await options.useFactory(...args)
|
|
138
|
+
}),
|
|
183
139
|
inject: options.inject || []
|
|
184
140
|
}
|
|
185
141
|
];
|
|
@@ -192,13 +148,10 @@ export class AuthModule {
|
|
|
192
148
|
},
|
|
193
149
|
{
|
|
194
150
|
provide: AUTH_MODULE_OPTIONS,
|
|
195
|
-
useFactory: async (factory)=>{
|
|
196
|
-
const config = await factory.createAuthOptions();
|
|
197
|
-
return {
|
|
151
|
+
useFactory: async (factory)=>({
|
|
198
152
|
...staticOptions,
|
|
199
|
-
config
|
|
200
|
-
}
|
|
201
|
-
},
|
|
153
|
+
config: await factory.createAuthOptions()
|
|
154
|
+
}),
|
|
202
155
|
inject: [
|
|
203
156
|
options.useClass
|
|
204
157
|
]
|
|
@@ -209,13 +162,10 @@ export class AuthModule {
|
|
|
209
162
|
return [
|
|
210
163
|
{
|
|
211
164
|
provide: AUTH_MODULE_OPTIONS,
|
|
212
|
-
useFactory: async (factory)=>{
|
|
213
|
-
const config = await factory.createAuthOptions();
|
|
214
|
-
return {
|
|
165
|
+
useFactory: async (factory)=>({
|
|
215
166
|
...staticOptions,
|
|
216
|
-
config
|
|
217
|
-
}
|
|
218
|
-
},
|
|
167
|
+
config: await factory.createAuthOptions()
|
|
168
|
+
}),
|
|
219
169
|
inject: [
|
|
220
170
|
options.useExisting
|
|
221
171
|
]
|
|
@@ -229,36 +179,11 @@ export class AuthModule {
|
|
|
229
179
|
}
|
|
230
180
|
];
|
|
231
181
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const entities = this.getEntities(enableCompanyFeature);
|
|
238
|
-
return entities.map((entity)=>({
|
|
239
|
-
provide: getRepositoryToken(entity),
|
|
240
|
-
scope: Scope.REQUEST,
|
|
241
|
-
useFactory: async (dataSourceProvider)=>{
|
|
242
|
-
return await dataSourceProvider.getRepository(entity);
|
|
243
|
-
},
|
|
244
|
-
inject: [
|
|
245
|
-
AuthDataSourceProvider
|
|
246
|
-
]
|
|
247
|
-
}));
|
|
248
|
-
}
|
|
249
|
-
static getEntities(enableCompanyFeature = false) {
|
|
250
|
-
const coreEntities = [
|
|
251
|
-
User
|
|
252
|
-
];
|
|
253
|
-
const companyEntities = enableCompanyFeature ? [
|
|
254
|
-
Company,
|
|
255
|
-
CompanyBranch,
|
|
256
|
-
UserCompanyPermission
|
|
257
|
-
] : [];
|
|
258
|
-
return [
|
|
259
|
-
...coreEntities,
|
|
260
|
-
...companyEntities
|
|
261
|
-
];
|
|
182
|
+
static getEntities(config) {
|
|
183
|
+
return getEntitiesByConfig({
|
|
184
|
+
enableCompanyFeature: config.enableCompanyFeature ?? false,
|
|
185
|
+
enableEmailVerification: config.enableEmailVerification ?? true
|
|
186
|
+
});
|
|
262
187
|
}
|
|
263
188
|
}
|
|
264
189
|
AuthModule = _ts_decorate([
|
|
@@ -25,65 +25,63 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
28
|
+
import { envConfig } from '@flusys/nestjs-core/config';
|
|
29
|
+
import { Inject, Injectable, InternalServerErrorException, Logger, Optional } from '@nestjs/common';
|
|
30
30
|
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
31
|
+
import { AuthModuleOptions } from '../interfaces/auth-module-options.interface';
|
|
31
32
|
export class AuthConfigService {
|
|
32
|
-
// Database Mode
|
|
33
|
-
|
|
33
|
+
// Database Mode (required by IModuleConfigService)
|
|
34
|
+
getDatabaseMode() {
|
|
34
35
|
return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
isMultiTenant() {
|
|
37
38
|
return this.getDatabaseMode() === 'multi-tenant';
|
|
38
39
|
}
|
|
39
40
|
// Feature Flags
|
|
40
|
-
|
|
41
|
+
isCompanyFeatureEnabled() {
|
|
41
42
|
return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
42
43
|
}
|
|
44
|
+
isEmailVerificationEnabled() {
|
|
45
|
+
return this.options.bootstrapAppConfig?.enableEmailVerification ?? true;
|
|
46
|
+
}
|
|
43
47
|
// JWT Configuration
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
getJwtSecret() {
|
|
49
|
+
if (!this.config.jwtSecret) {
|
|
50
|
+
throw new InternalServerErrorException('[AuthModule] JWT_SECRET is required - set via environment or module config');
|
|
51
|
+
}
|
|
52
|
+
return this.config.jwtSecret;
|
|
46
53
|
}
|
|
47
|
-
|
|
54
|
+
getJwtExpiration() {
|
|
48
55
|
return this.config.jwtExpiration ?? '1h';
|
|
49
56
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
getRefreshTokenSecret() {
|
|
58
|
+
if (this.config.refreshTokenSecret) {
|
|
59
|
+
return this.config.refreshTokenSecret;
|
|
60
|
+
}
|
|
61
|
+
if (envConfig.isProduction()) {
|
|
62
|
+
throw new InternalServerErrorException('[AuthModule] REFRESH_TOKEN_SECRET is required in production - ' + 'using the same secret for access and refresh tokens is a security risk');
|
|
63
|
+
}
|
|
64
|
+
if (!this.refreshTokenSecretWarned) {
|
|
65
|
+
this.refreshTokenSecretWarned = true;
|
|
66
|
+
this.logger.warn('REFRESH_TOKEN_SECRET not configured - using JWT_SECRET as fallback. ' + 'For better security, configure a separate refresh token secret.');
|
|
67
|
+
}
|
|
68
|
+
return this.getJwtSecret();
|
|
69
|
+
}
|
|
70
|
+
getRefreshTokenExpiration() {
|
|
54
71
|
return this.config.refreshTokenExpiration ?? '7d';
|
|
55
72
|
}
|
|
56
|
-
|
|
73
|
+
getRefreshTokenCookieName() {
|
|
57
74
|
return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
|
|
58
75
|
}
|
|
59
76
|
// Frontend Configuration
|
|
60
|
-
|
|
77
|
+
getFrontendUrl() {
|
|
61
78
|
return this.config.frontendUrl;
|
|
62
79
|
}
|
|
63
|
-
// Database Configuration
|
|
64
|
-
/** Get default database config */ getDefaultDatabaseConfig() {
|
|
65
|
-
return this.config.defaultDatabaseConfig ?? this.config.tenantDefaultDatabaseConfig;
|
|
66
|
-
}
|
|
67
|
-
/** Get tenant default database config (for multi-tenant) */ getTenantDefaultDatabaseConfig() {
|
|
68
|
-
return this.config.tenantDefaultDatabaseConfig;
|
|
69
|
-
}
|
|
70
|
-
/** Get registered tenants */ getTenants() {
|
|
71
|
-
return this.config.tenants ?? [];
|
|
72
|
-
}
|
|
73
|
-
// Raw Options
|
|
74
|
-
/** Get full module options */ getOptions() {
|
|
75
|
-
return {
|
|
76
|
-
...this.options
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/** Get runtime config */ getConfig() {
|
|
80
|
-
return {
|
|
81
|
-
...this.config
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
80
|
constructor(injectedOptions){
|
|
81
|
+
_define_property(this, "logger", new Logger(AuthConfigService.name));
|
|
85
82
|
_define_property(this, "options", void 0);
|
|
86
83
|
_define_property(this, "config", void 0);
|
|
84
|
+
_define_property(this, "refreshTokenSecretWarned", false);
|
|
87
85
|
this.options = injectedOptions ?? {
|
|
88
86
|
global: false,
|
|
89
87
|
includeController: true
|
|
@@ -26,14 +26,13 @@ function _ts_param(paramIndex, decorator) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
|
|
29
|
-
import { Inject, Injectable, Logger, Optional, Scope } from '@nestjs/common';
|
|
29
|
+
import { Inject, Injectable, InternalServerErrorException, Logger, Optional, Scope } from '@nestjs/common';
|
|
30
30
|
import { REQUEST } from '@nestjs/core';
|
|
31
31
|
import { Request } from 'express';
|
|
32
32
|
import { AuthModuleOptions } from '../interfaces/auth-module-options.interface';
|
|
33
33
|
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
34
34
|
export class AuthDataSourceProvider extends MultiTenantDataSourceService {
|
|
35
|
-
|
|
36
|
-
/** Override to access Auth-specific static properties */ async getSingleDataSource() {
|
|
35
|
+
async getSingleDataSource() {
|
|
37
36
|
if (!AuthDataSourceProvider.singleDataSource) {
|
|
38
37
|
if (AuthDataSourceProvider.singleConnectionLock) {
|
|
39
38
|
return AuthDataSourceProvider.singleConnectionLock;
|
|
@@ -41,7 +40,7 @@ export class AuthDataSourceProvider extends MultiTenantDataSourceService {
|
|
|
41
40
|
const lockPromise = (async ()=>{
|
|
42
41
|
const config = this.getDefaultDatabaseConfig();
|
|
43
42
|
if (!config) {
|
|
44
|
-
throw new
|
|
43
|
+
throw new InternalServerErrorException('Default database config is not available');
|
|
45
44
|
}
|
|
46
45
|
const ds = await this.createDataSourceFromConfig(config);
|
|
47
46
|
AuthDataSourceProvider.singleDataSource = ds;
|
|
@@ -57,18 +56,15 @@ export class AuthDataSourceProvider extends MultiTenantDataSourceService {
|
|
|
57
56
|
}
|
|
58
57
|
return AuthDataSourceProvider.singleDataSource;
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
// Return existing initialized connection from Auth-specific cache
|
|
59
|
+
async getOrCreateTenantConnection(tenant) {
|
|
62
60
|
const existing = AuthDataSourceProvider.tenantConnections.get(tenant.id);
|
|
63
61
|
if (existing?.isInitialized) {
|
|
64
62
|
return existing;
|
|
65
63
|
}
|
|
66
|
-
// If another request is creating this tenant's connection, wait for it
|
|
67
64
|
const pendingConnection = AuthDataSourceProvider.connectionLocks.get(tenant.id);
|
|
68
65
|
if (pendingConnection) {
|
|
69
66
|
return pendingConnection;
|
|
70
67
|
}
|
|
71
|
-
// Create connection with lock to prevent race conditions
|
|
72
68
|
const config = this.buildTenantDatabaseConfig(tenant);
|
|
73
69
|
const connectionPromise = this.createDataSourceFromConfig(config);
|
|
74
70
|
AuthDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
|
|
@@ -80,8 +76,7 @@ export class AuthDataSourceProvider extends MultiTenantDataSourceService {
|
|
|
80
76
|
AuthDataSourceProvider.connectionLocks.delete(tenant.id);
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
|
-
|
|
84
|
-
/** Build parent options from AuthModuleOptions */ static buildParentOptions(options) {
|
|
79
|
+
static buildParentOptions(options) {
|
|
85
80
|
return {
|
|
86
81
|
bootstrapAppConfig: options.bootstrapAppConfig,
|
|
87
82
|
defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
|
|
@@ -89,47 +84,28 @@ export class AuthDataSourceProvider extends MultiTenantDataSourceService {
|
|
|
89
84
|
tenants: options.config?.tenants
|
|
90
85
|
};
|
|
91
86
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return this.authOptions.bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
87
|
+
isCompanyFeatureEnabled(tenant) {
|
|
88
|
+
const effectiveTenant = tenant ?? this.getCurrentTenant();
|
|
89
|
+
return effectiveTenant?.enableCompanyFeature ?? this.authOptions.bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
95
90
|
}
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
isEmailVerificationEnabled(tenant) {
|
|
92
|
+
const effectiveTenant = tenant ?? this.getCurrentTenant();
|
|
93
|
+
return effectiveTenant?.enableEmailVerification ?? this.authOptions.bootstrapAppConfig?.enableEmailVerification ?? true;
|
|
98
94
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const { Company, CompanyBranch, User, UserCompanyPermission, UserToken, PendingRegistration } = await import('../entities');
|
|
106
|
-
const coreEntities = [
|
|
107
|
-
User,
|
|
108
|
-
UserToken,
|
|
109
|
-
PendingRegistration
|
|
110
|
-
];
|
|
111
|
-
const companyEntities = enable ? [
|
|
112
|
-
Company,
|
|
113
|
-
CompanyBranch,
|
|
114
|
-
UserCompanyPermission
|
|
115
|
-
] : [];
|
|
116
|
-
return [
|
|
117
|
-
...coreEntities,
|
|
118
|
-
...companyEntities
|
|
119
|
-
];
|
|
95
|
+
async getAuthEntities() {
|
|
96
|
+
const { getEntitiesByConfig } = await import('../entities');
|
|
97
|
+
return getEntitiesByConfig({
|
|
98
|
+
enableCompanyFeature: this.isCompanyFeatureEnabled(),
|
|
99
|
+
enableEmailVerification: this.isEmailVerificationEnabled()
|
|
100
|
+
});
|
|
120
101
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const currentTenant = this.getCurrentTenant();
|
|
124
|
-
const enableCompanyFeature = this.getEnableCompanyFeatureForTenant(currentTenant ?? undefined);
|
|
125
|
-
const entities = await this.getAuthEntities(enableCompanyFeature);
|
|
126
|
-
return super.createDataSourceFromConfig(config, entities);
|
|
102
|
+
async createDataSourceFromConfig(config) {
|
|
103
|
+
return super.createDataSourceFromConfig(config, await this.getAuthEntities());
|
|
127
104
|
}
|
|
128
105
|
constructor(authOptions, request){
|
|
129
106
|
super(AuthDataSourceProvider.buildParentOptions(authOptions), request), _define_property(this, "authOptions", void 0), _define_property(this, "logger", void 0), this.authOptions = authOptions, this.logger = new Logger(AuthDataSourceProvider.name);
|
|
130
107
|
}
|
|
131
108
|
}
|
|
132
|
-
// Override parent's static properties to have Auth-specific cache (isolated from IAM/Storage)
|
|
133
109
|
_define_property(AuthDataSourceProvider, "tenantConnections", new Map());
|
|
134
110
|
_define_property(AuthDataSourceProvider, "singleDataSource", null);
|
|
135
111
|
_define_property(AuthDataSourceProvider, "tenantsRegistry", new Map());
|