@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
|
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "ClearToken", {
|
|
|
8
8
|
return ClearToken;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _utils = require("@flusys/nestjs-shared/utils");
|
|
11
12
|
const _common = require("@nestjs/common");
|
|
12
13
|
const _rxjs = require("rxjs");
|
|
14
|
+
const _config = require("../config");
|
|
13
15
|
const _authconfigservice = require("../services/auth-config.service");
|
|
14
16
|
function _define_property(obj, key, value) {
|
|
15
17
|
if (key in obj) {
|
|
@@ -38,39 +40,24 @@ function _ts_param(paramIndex, decorator) {
|
|
|
38
40
|
decorator(target, key, paramIndex);
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
|
-
const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
|
|
42
43
|
let ClearToken = class ClearToken {
|
|
43
44
|
get cookieName() {
|
|
44
|
-
return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
|
|
45
|
+
return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
|
|
45
46
|
}
|
|
46
47
|
intercept(context, next) {
|
|
47
48
|
const req = context.switchToHttp().getRequest();
|
|
48
49
|
const res = context.switchToHttp().getResponse();
|
|
49
50
|
return next.handle().pipe((0, _rxjs.map)((value)=>{
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if ((0, _utils.isBrowserRequest)(req)) {
|
|
52
|
+
res.clearCookie(this.cookieName, {
|
|
53
|
+
httpOnly: true,
|
|
54
|
+
path: '/',
|
|
55
|
+
...(0, _utils.buildCookieOptions)(req)
|
|
56
|
+
});
|
|
57
|
+
}
|
|
52
58
|
return value;
|
|
53
59
|
}));
|
|
54
60
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Clear refresh token cookie
|
|
57
|
-
*/ clearRefreshTokenCookie(req, res) {
|
|
58
|
-
const origin = req.headers.origin || '';
|
|
59
|
-
const hostname = req.hostname || '';
|
|
60
|
-
const isHttps = origin.startsWith('https://') || req.secure;
|
|
61
|
-
let cookieDomain = hostname;
|
|
62
|
-
const domainParts = hostname.split('.');
|
|
63
|
-
if (domainParts.length > 2) {
|
|
64
|
-
cookieDomain = '.' + domainParts.slice(-2).join('.');
|
|
65
|
-
}
|
|
66
|
-
res.clearCookie(this.cookieName, {
|
|
67
|
-
httpOnly: true,
|
|
68
|
-
secure: isHttps,
|
|
69
|
-
sameSite: isHttps ? 'strict' : 'lax',
|
|
70
|
-
domain: cookieDomain,
|
|
71
|
-
path: '/'
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
61
|
constructor(authConfig){
|
|
75
62
|
_define_property(this, "authConfig", void 0);
|
|
76
63
|
this.authConfig = authConfig;
|
|
@@ -8,9 +8,11 @@ Object.defineProperty(exports, "SetToken", {
|
|
|
8
8
|
return SetToken;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _utils = require("@flusys/nestjs-shared/utils");
|
|
11
12
|
const _common = require("@nestjs/common");
|
|
12
13
|
const _buffer = require("buffer");
|
|
13
14
|
const _rxjs = require("rxjs");
|
|
15
|
+
const _config = require("../config");
|
|
14
16
|
const _authconfigservice = require("../services/auth-config.service");
|
|
15
17
|
function _define_property(obj, key, value) {
|
|
16
18
|
if (key in obj) {
|
|
@@ -39,80 +41,37 @@ function _ts_param(paramIndex, decorator) {
|
|
|
39
41
|
decorator(target, key, paramIndex);
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
|
-
const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
|
|
43
|
-
const MAX_COOKIE_BYTES = 3500;
|
|
44
44
|
let SetToken = class SetToken {
|
|
45
45
|
get cookieName() {
|
|
46
|
-
return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
|
|
46
|
+
return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
|
|
47
|
+
}
|
|
48
|
+
get maxAgeMs() {
|
|
49
|
+
return (0, _utils.parseDurationToMs)(this.authConfig?.getRefreshTokenExpiration() ?? '7d');
|
|
47
50
|
}
|
|
48
51
|
intercept(context, next) {
|
|
49
52
|
const req = context.switchToHttp().getRequest();
|
|
50
53
|
const res = context.switchToHttp().getResponse();
|
|
51
54
|
return next.handle().pipe((0, _rxjs.map)((value)=>{
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
const isBrowser = this.isBrowserRequest(req);
|
|
57
|
-
const tokenValue = value.refreshToken;
|
|
58
|
-
if (isBrowser) {
|
|
59
|
-
// Browser: Set cookie and remove from response body
|
|
60
|
-
this.setRefreshTokenCookie(req, res, tokenValue);
|
|
61
|
-
// Return response without refreshToken for browsers
|
|
55
|
+
if (!value?.refreshToken) return value;
|
|
56
|
+
if ((0, _utils.isBrowserRequest)(req)) {
|
|
57
|
+
this.setRefreshTokenCookie(req, res, value.refreshToken);
|
|
62
58
|
const { refreshToken, ...responseWithoutToken } = value;
|
|
63
59
|
return responseWithoutToken;
|
|
64
60
|
}
|
|
65
|
-
// API/Mobile: Keep refreshToken in response body
|
|
66
61
|
return value;
|
|
67
62
|
}), (0, _rxjs.catchError)((err)=>(0, _rxjs.throwError)(()=>err)));
|
|
68
63
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* Checks Accept header and custom X-Client-Type header
|
|
72
|
-
*/ isBrowserRequest(req) {
|
|
73
|
-
// Check custom header first (allows explicit client identification)
|
|
74
|
-
const clientType = req.headers['x-client-type'];
|
|
75
|
-
if (clientType) {
|
|
76
|
-
return clientType.toLowerCase() === 'browser' || clientType.toLowerCase() === 'web';
|
|
77
|
-
}
|
|
78
|
-
// Check Accept header - browsers typically include text/html
|
|
79
|
-
const accept = req.headers['accept'] || '';
|
|
80
|
-
if (accept.includes('text/html')) {
|
|
81
|
-
return true;
|
|
82
|
-
}
|
|
83
|
-
// Check User-Agent for common browsers
|
|
84
|
-
const userAgent = req.headers['user-agent'] || '';
|
|
85
|
-
const browserPatterns = /mozilla|chrome|safari|firefox|edge|opera|msie/i;
|
|
86
|
-
if (browserPatterns.test(userAgent) && !userAgent.includes('Postman')) {
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Set refresh token in HTTP-only cookie
|
|
93
|
-
*/ setRefreshTokenCookie(req, res, tokenValue) {
|
|
94
|
-
const origin = req.headers.origin || '';
|
|
95
|
-
const hostname = req.hostname || '';
|
|
96
|
-
const isHttps = origin.startsWith('https://') || req.secure;
|
|
97
|
-
let cookieDomain = hostname;
|
|
98
|
-
const domainParts = hostname.split('.');
|
|
99
|
-
if (domainParts.length > 2) {
|
|
100
|
-
cookieDomain = '.' + domainParts.slice(-2).join('.');
|
|
101
|
-
}
|
|
102
|
-
// Check cookie size
|
|
103
|
-
const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly; Domain=${cookieDomain}`;
|
|
64
|
+
setRefreshTokenCookie(req, res, tokenValue) {
|
|
65
|
+
const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly`;
|
|
104
66
|
const estimatedBytes = _buffer.Buffer.byteLength(rawCookieString, 'utf8');
|
|
105
|
-
if (estimatedBytes > MAX_COOKIE_BYTES) {
|
|
67
|
+
if (estimatedBytes > _config.MAX_COOKIE_BYTES) {
|
|
106
68
|
throw new _common.PayloadTooLargeException(`Refresh token too large (≈${estimatedBytes} bytes)`);
|
|
107
69
|
}
|
|
108
|
-
// Set HTTP-only secure cookie
|
|
109
70
|
res.cookie(this.cookieName, tokenValue, {
|
|
110
71
|
httpOnly: true,
|
|
111
|
-
secure: isHttps,
|
|
112
|
-
sameSite: isHttps ? 'strict' : 'lax',
|
|
113
|
-
domain: cookieDomain,
|
|
114
72
|
path: '/',
|
|
115
|
-
maxAge:
|
|
73
|
+
maxAge: this.maxAgeMs,
|
|
74
|
+
...(0, _utils.buildCookieOptions)(req)
|
|
116
75
|
});
|
|
117
76
|
}
|
|
118
77
|
constructor(authConfig){
|
|
@@ -123,6 +82,7 @@ let SetToken = class SetToken {
|
|
|
123
82
|
SetToken = _ts_decorate([
|
|
124
83
|
(0, _common.Injectable)(),
|
|
125
84
|
_ts_param(0, (0, _common.Optional)()),
|
|
85
|
+
_ts_param(0, (0, _common.Inject)(_authconfigservice.AuthConfigService)),
|
|
126
86
|
_ts_metadata("design:type", Function),
|
|
127
87
|
_ts_metadata("design:paramtypes", [
|
|
128
88
|
typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService
|
|
@@ -12,16 +12,15 @@ const _modules = require("@flusys/nestjs-shared/modules");
|
|
|
12
12
|
const _common = require("@nestjs/common");
|
|
13
13
|
const _jwt = require("@nestjs/jwt");
|
|
14
14
|
const _passport = require("@nestjs/passport");
|
|
15
|
-
const
|
|
16
|
-
const _authconfigservice = require("../services/auth-config.service");
|
|
17
|
-
const _authdatasourceprovider = require("../services/auth-datasource.provider");
|
|
15
|
+
const _guards = require("@flusys/nestjs-shared/guards");
|
|
18
16
|
const _authconstants = require("../config/auth.constants");
|
|
19
17
|
const _controllers = require("../controllers");
|
|
20
18
|
const _entities = require("../entities");
|
|
21
|
-
const _guards = require("@flusys/nestjs-shared/guards");
|
|
22
19
|
const _cleartokeninterceptor = require("../interceptors/clear-token.interceptor");
|
|
23
20
|
const _settokeninterceptor = require("../interceptors/set-token.interceptor");
|
|
24
21
|
const _services = require("../services");
|
|
22
|
+
const _authconfigservice = require("../services/auth-config.service");
|
|
23
|
+
const _authdatasourceprovider = require("../services/auth-datasource.provider");
|
|
25
24
|
const _jwtstrategy = require("../strategies/jwt.strategy");
|
|
26
25
|
function _ts_decorate(decorators, target, key, desc) {
|
|
27
26
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -31,82 +30,48 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
31
30
|
}
|
|
32
31
|
let AuthModule = class AuthModule {
|
|
33
32
|
static forRoot(options) {
|
|
34
|
-
|
|
33
|
+
const optionsProvider = {
|
|
34
|
+
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
35
|
+
useValue: options
|
|
36
|
+
};
|
|
37
|
+
return this.buildModule(options, [
|
|
38
|
+
optionsProvider,
|
|
39
|
+
...options.providers ?? []
|
|
40
|
+
]);
|
|
35
41
|
}
|
|
36
|
-
static forRootAsync(
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
// Build imports
|
|
40
|
-
const imports = [
|
|
41
|
-
...externalImports,
|
|
42
|
-
_passport.PassportModule.register({
|
|
43
|
-
defaultStrategy: 'jwt'
|
|
44
|
-
}),
|
|
45
|
-
_jwt.JwtModule.register({}),
|
|
46
|
-
_modules.CacheModule,
|
|
47
|
-
_modules.UtilsModule
|
|
48
|
-
];
|
|
49
|
-
// Build controllers based on configuration
|
|
50
|
-
const controllers = [];
|
|
51
|
-
if (includeController) {
|
|
52
|
-
// Core authentication controller (always included)
|
|
53
|
-
controllers.push(_controllers.AuthenticationController);
|
|
54
|
-
// User controller (always included)
|
|
55
|
-
controllers.push(_controllers.UserController);
|
|
56
|
-
// Company feature controllers (conditional)
|
|
57
|
-
if (enableCompanyFeature) {
|
|
58
|
-
controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// Build providers
|
|
62
|
-
const providers = [
|
|
42
|
+
static forRootAsync(options) {
|
|
43
|
+
const asyncProviders = this.createAsyncProviders(options);
|
|
44
|
+
return this.buildModule(options, [
|
|
63
45
|
...asyncProviders,
|
|
64
|
-
...
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
_guards.JwtAuthGuard,
|
|
71
|
-
_services.AuthenticationService,
|
|
72
|
-
_services.AuthEmailService,
|
|
73
|
-
// Interceptors
|
|
74
|
-
_settokeninterceptor.SetToken,
|
|
75
|
-
_cleartokeninterceptor.ClearToken,
|
|
76
|
-
// Core services (always included)
|
|
77
|
-
_services.UserService
|
|
78
|
-
];
|
|
79
|
-
// Company feature services (conditional)
|
|
80
|
-
if (enableCompanyFeature) {
|
|
81
|
-
providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
82
|
-
}
|
|
83
|
-
// Build exports
|
|
84
|
-
const exports1 = [
|
|
85
|
-
_passport.PassportModule,
|
|
86
|
-
_authconstants.AUTH_MODULE_OPTIONS,
|
|
87
|
-
_authconfigservice.AuthConfigService,
|
|
88
|
-
_authdatasourceprovider.AuthDataSourceProvider,
|
|
89
|
-
_jwtstrategy.JwtStrategy,
|
|
90
|
-
_guards.JwtAuthGuard,
|
|
91
|
-
_services.AuthenticationService,
|
|
92
|
-
_services.AuthEmailService,
|
|
93
|
-
_services.UserService
|
|
94
|
-
];
|
|
95
|
-
if (enableCompanyFeature) {
|
|
96
|
-
exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
97
|
-
}
|
|
46
|
+
...options.providers ?? []
|
|
47
|
+
], options.imports);
|
|
48
|
+
}
|
|
49
|
+
static buildModule(options, providers, externalImports = []) {
|
|
50
|
+
const { global = false, includeController = true, bootstrapAppConfig } = options;
|
|
51
|
+
const featureFlags = this.getFeatureFlags(bootstrapAppConfig);
|
|
98
52
|
return {
|
|
99
53
|
module: AuthModule,
|
|
100
54
|
global,
|
|
101
|
-
imports
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
55
|
+
imports: [
|
|
56
|
+
...externalImports,
|
|
57
|
+
...this.buildImports()
|
|
58
|
+
],
|
|
59
|
+
controllers: this.buildControllers(includeController, featureFlags),
|
|
60
|
+
providers: [
|
|
61
|
+
...providers,
|
|
62
|
+
...this.buildProviders(featureFlags)
|
|
63
|
+
],
|
|
64
|
+
exports: this.buildExports(featureFlags)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
static getFeatureFlags(bootstrapAppConfig) {
|
|
68
|
+
return {
|
|
69
|
+
enableCompanyFeature: bootstrapAppConfig?.enableCompanyFeature ?? false,
|
|
70
|
+
enableEmailVerification: bootstrapAppConfig?.enableEmailVerification ?? true
|
|
105
71
|
};
|
|
106
72
|
}
|
|
107
|
-
static
|
|
108
|
-
|
|
109
|
-
const imports = [
|
|
73
|
+
static buildImports() {
|
|
74
|
+
return [
|
|
110
75
|
_passport.PassportModule.register({
|
|
111
76
|
defaultStrategy: 'jwt'
|
|
112
77
|
}),
|
|
@@ -114,42 +79,41 @@ let AuthModule = class AuthModule {
|
|
|
114
79
|
_modules.CacheModule,
|
|
115
80
|
_modules.UtilsModule
|
|
116
81
|
];
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (includeController)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
|
|
127
|
-
}
|
|
82
|
+
}
|
|
83
|
+
static buildControllers(includeController, flags) {
|
|
84
|
+
if (!includeController) return [];
|
|
85
|
+
const controllers = [
|
|
86
|
+
_controllers.AuthenticationController,
|
|
87
|
+
_controllers.UserController
|
|
88
|
+
];
|
|
89
|
+
if (flags.enableEmailVerification) {
|
|
90
|
+
controllers.push(_controllers.EmailVerificationController);
|
|
128
91
|
}
|
|
92
|
+
if (flags.enableCompanyFeature) {
|
|
93
|
+
controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
|
|
94
|
+
}
|
|
95
|
+
return controllers;
|
|
96
|
+
}
|
|
97
|
+
static buildProviders(flags) {
|
|
129
98
|
const providers = [
|
|
130
|
-
{
|
|
131
|
-
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
132
|
-
useValue: options
|
|
133
|
-
},
|
|
134
|
-
...additionalProviders,
|
|
135
|
-
// Config & Infrastructure
|
|
136
99
|
_authconfigservice.AuthConfigService,
|
|
137
100
|
_authdatasourceprovider.AuthDataSourceProvider,
|
|
138
|
-
// Auth core
|
|
139
101
|
_jwtstrategy.JwtStrategy,
|
|
140
102
|
_guards.JwtAuthGuard,
|
|
141
103
|
_services.AuthenticationService,
|
|
142
|
-
_services.AuthEmailService,
|
|
143
|
-
// Interceptors
|
|
144
104
|
_settokeninterceptor.SetToken,
|
|
145
105
|
_cleartokeninterceptor.ClearToken,
|
|
146
|
-
// Core services (always included)
|
|
147
106
|
_services.UserService
|
|
148
107
|
];
|
|
149
|
-
|
|
150
|
-
|
|
108
|
+
if (flags.enableEmailVerification) {
|
|
109
|
+
providers.push(_services.AuthEmailService);
|
|
110
|
+
}
|
|
111
|
+
if (flags.enableCompanyFeature) {
|
|
151
112
|
providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
152
113
|
}
|
|
114
|
+
return providers;
|
|
115
|
+
}
|
|
116
|
+
static buildExports(flags) {
|
|
153
117
|
const exports1 = [
|
|
154
118
|
_passport.PassportModule,
|
|
155
119
|
_authconstants.AUTH_MODULE_OPTIONS,
|
|
@@ -158,20 +122,15 @@ let AuthModule = class AuthModule {
|
|
|
158
122
|
_jwtstrategy.JwtStrategy,
|
|
159
123
|
_guards.JwtAuthGuard,
|
|
160
124
|
_services.AuthenticationService,
|
|
161
|
-
_services.AuthEmailService,
|
|
162
125
|
_services.UserService
|
|
163
126
|
];
|
|
164
|
-
if (
|
|
127
|
+
if (flags.enableEmailVerification) {
|
|
128
|
+
exports1.push(_services.AuthEmailService);
|
|
129
|
+
}
|
|
130
|
+
if (flags.enableCompanyFeature) {
|
|
165
131
|
exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
166
132
|
}
|
|
167
|
-
return
|
|
168
|
-
module: AuthModule,
|
|
169
|
-
global,
|
|
170
|
-
imports,
|
|
171
|
-
controllers,
|
|
172
|
-
providers,
|
|
173
|
-
exports: exports1
|
|
174
|
-
};
|
|
133
|
+
return exports1;
|
|
175
134
|
}
|
|
176
135
|
static createAsyncProviders(options) {
|
|
177
136
|
const staticOptions = {
|
|
@@ -183,13 +142,10 @@ let AuthModule = class AuthModule {
|
|
|
183
142
|
return [
|
|
184
143
|
{
|
|
185
144
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
186
|
-
useFactory: async (...args)=>{
|
|
187
|
-
const config = await options.useFactory(...args);
|
|
188
|
-
return {
|
|
145
|
+
useFactory: async (...args)=>({
|
|
189
146
|
...staticOptions,
|
|
190
|
-
config
|
|
191
|
-
}
|
|
192
|
-
},
|
|
147
|
+
config: await options.useFactory(...args)
|
|
148
|
+
}),
|
|
193
149
|
inject: options.inject || []
|
|
194
150
|
}
|
|
195
151
|
];
|
|
@@ -202,13 +158,10 @@ let AuthModule = class AuthModule {
|
|
|
202
158
|
},
|
|
203
159
|
{
|
|
204
160
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
205
|
-
useFactory: async (factory)=>{
|
|
206
|
-
const config = await factory.createAuthOptions();
|
|
207
|
-
return {
|
|
161
|
+
useFactory: async (factory)=>({
|
|
208
162
|
...staticOptions,
|
|
209
|
-
config
|
|
210
|
-
}
|
|
211
|
-
},
|
|
163
|
+
config: await factory.createAuthOptions()
|
|
164
|
+
}),
|
|
212
165
|
inject: [
|
|
213
166
|
options.useClass
|
|
214
167
|
]
|
|
@@ -219,13 +172,10 @@ let AuthModule = class AuthModule {
|
|
|
219
172
|
return [
|
|
220
173
|
{
|
|
221
174
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
222
|
-
useFactory: async (factory)=>{
|
|
223
|
-
const config = await factory.createAuthOptions();
|
|
224
|
-
return {
|
|
175
|
+
useFactory: async (factory)=>({
|
|
225
176
|
...staticOptions,
|
|
226
|
-
config
|
|
227
|
-
}
|
|
228
|
-
},
|
|
177
|
+
config: await factory.createAuthOptions()
|
|
178
|
+
}),
|
|
229
179
|
inject: [
|
|
230
180
|
options.useExisting
|
|
231
181
|
]
|
|
@@ -239,36 +189,11 @@ let AuthModule = class AuthModule {
|
|
|
239
189
|
}
|
|
240
190
|
];
|
|
241
191
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const entities = this.getEntities(enableCompanyFeature);
|
|
248
|
-
return entities.map((entity)=>({
|
|
249
|
-
provide: (0, _typeorm.getRepositoryToken)(entity),
|
|
250
|
-
scope: _common.Scope.REQUEST,
|
|
251
|
-
useFactory: async (dataSourceProvider)=>{
|
|
252
|
-
return await dataSourceProvider.getRepository(entity);
|
|
253
|
-
},
|
|
254
|
-
inject: [
|
|
255
|
-
_authdatasourceprovider.AuthDataSourceProvider
|
|
256
|
-
]
|
|
257
|
-
}));
|
|
258
|
-
}
|
|
259
|
-
static getEntities(enableCompanyFeature = false) {
|
|
260
|
-
const coreEntities = [
|
|
261
|
-
_entities.User
|
|
262
|
-
];
|
|
263
|
-
const companyEntities = enableCompanyFeature ? [
|
|
264
|
-
_entities.Company,
|
|
265
|
-
_entities.CompanyBranch,
|
|
266
|
-
_entities.UserCompanyPermission
|
|
267
|
-
] : [];
|
|
268
|
-
return [
|
|
269
|
-
...coreEntities,
|
|
270
|
-
...companyEntities
|
|
271
|
-
];
|
|
192
|
+
static getEntities(config) {
|
|
193
|
+
return (0, _entities.getEntitiesByConfig)({
|
|
194
|
+
enableCompanyFeature: config.enableCompanyFeature ?? false,
|
|
195
|
+
enableEmailVerification: config.enableEmailVerification ?? true
|
|
196
|
+
});
|
|
272
197
|
}
|
|
273
198
|
};
|
|
274
199
|
AuthModule = _ts_decorate([
|
|
@@ -8,9 +8,10 @@ Object.defineProperty(exports, "AuthConfigService", {
|
|
|
8
8
|
return AuthConfigService;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _config = require("@flusys/nestjs-core/config");
|
|
11
12
|
const _common = require("@nestjs/common");
|
|
12
|
-
const _authmoduleoptionsinterface = require("../interfaces/auth-module-options.interface");
|
|
13
13
|
const _authconstants = require("../config/auth.constants");
|
|
14
|
+
const _authmoduleoptionsinterface = require("../interfaces/auth-module-options.interface");
|
|
14
15
|
function _define_property(obj, key, value) {
|
|
15
16
|
if (key in obj) {
|
|
16
17
|
Object.defineProperty(obj, key, {
|
|
@@ -39,61 +40,58 @@ function _ts_param(paramIndex, decorator) {
|
|
|
39
40
|
};
|
|
40
41
|
}
|
|
41
42
|
let AuthConfigService = class AuthConfigService {
|
|
42
|
-
// Database Mode
|
|
43
|
-
|
|
43
|
+
// Database Mode (required by IModuleConfigService)
|
|
44
|
+
getDatabaseMode() {
|
|
44
45
|
return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
+
isMultiTenant() {
|
|
47
48
|
return this.getDatabaseMode() === 'multi-tenant';
|
|
48
49
|
}
|
|
49
50
|
// Feature Flags
|
|
50
|
-
|
|
51
|
+
isCompanyFeatureEnabled() {
|
|
51
52
|
return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
52
53
|
}
|
|
54
|
+
isEmailVerificationEnabled() {
|
|
55
|
+
return this.options.bootstrapAppConfig?.enableEmailVerification ?? true;
|
|
56
|
+
}
|
|
53
57
|
// JWT Configuration
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
getJwtSecret() {
|
|
59
|
+
if (!this.config.jwtSecret) {
|
|
60
|
+
throw new _common.InternalServerErrorException('[AuthModule] JWT_SECRET is required - set via environment or module config');
|
|
61
|
+
}
|
|
62
|
+
return this.config.jwtSecret;
|
|
56
63
|
}
|
|
57
|
-
|
|
64
|
+
getJwtExpiration() {
|
|
58
65
|
return this.config.jwtExpiration ?? '1h';
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
getRefreshTokenSecret() {
|
|
68
|
+
if (this.config.refreshTokenSecret) {
|
|
69
|
+
return this.config.refreshTokenSecret;
|
|
70
|
+
}
|
|
71
|
+
if (_config.envConfig.isProduction()) {
|
|
72
|
+
throw new _common.InternalServerErrorException('[AuthModule] REFRESH_TOKEN_SECRET is required in production - ' + 'using the same secret for access and refresh tokens is a security risk');
|
|
73
|
+
}
|
|
74
|
+
if (!this.refreshTokenSecretWarned) {
|
|
75
|
+
this.refreshTokenSecretWarned = true;
|
|
76
|
+
this.logger.warn('REFRESH_TOKEN_SECRET not configured - using JWT_SECRET as fallback. ' + 'For better security, configure a separate refresh token secret.');
|
|
77
|
+
}
|
|
78
|
+
return this.getJwtSecret();
|
|
79
|
+
}
|
|
80
|
+
getRefreshTokenExpiration() {
|
|
64
81
|
return this.config.refreshTokenExpiration ?? '7d';
|
|
65
82
|
}
|
|
66
|
-
|
|
83
|
+
getRefreshTokenCookieName() {
|
|
67
84
|
return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
|
|
68
85
|
}
|
|
69
86
|
// Frontend Configuration
|
|
70
|
-
|
|
87
|
+
getFrontendUrl() {
|
|
71
88
|
return this.config.frontendUrl;
|
|
72
89
|
}
|
|
73
|
-
// Database Configuration
|
|
74
|
-
/** Get default database config */ getDefaultDatabaseConfig() {
|
|
75
|
-
return this.config.defaultDatabaseConfig ?? this.config.tenantDefaultDatabaseConfig;
|
|
76
|
-
}
|
|
77
|
-
/** Get tenant default database config (for multi-tenant) */ getTenantDefaultDatabaseConfig() {
|
|
78
|
-
return this.config.tenantDefaultDatabaseConfig;
|
|
79
|
-
}
|
|
80
|
-
/** Get registered tenants */ getTenants() {
|
|
81
|
-
return this.config.tenants ?? [];
|
|
82
|
-
}
|
|
83
|
-
// Raw Options
|
|
84
|
-
/** Get full module options */ getOptions() {
|
|
85
|
-
return {
|
|
86
|
-
...this.options
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
/** Get runtime config */ getConfig() {
|
|
90
|
-
return {
|
|
91
|
-
...this.config
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
90
|
constructor(injectedOptions){
|
|
91
|
+
_define_property(this, "logger", new _common.Logger(AuthConfigService.name));
|
|
95
92
|
_define_property(this, "options", void 0);
|
|
96
93
|
_define_property(this, "config", void 0);
|
|
94
|
+
_define_property(this, "refreshTokenSecretWarned", false);
|
|
97
95
|
this.options = injectedOptions ?? {
|
|
98
96
|
global: false,
|
|
99
97
|
includeController: true
|