@flusys/nestjs-auth 1.0.0-beta → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +590 -473
- package/cjs/config/auth.constants.js +12 -0
- package/cjs/controllers/authentication.controller.js +365 -24
- 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/user-permission.controller.js +82 -154
- package/cjs/controllers/user.controller.js +211 -7
- package/cjs/docs/auth-swagger.config.js +14 -7
- package/cjs/dtos/authentication.dto.js +114 -38
- 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 +5 -1
- package/cjs/entities/pending-registration.entity.js +125 -0
- package/cjs/entities/user-company-permission.entity.js +3 -9
- package/cjs/entities/user-token.entity.js +129 -0
- 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 +45 -0
- package/cjs/interfaces/index.js +2 -0
- package/cjs/interfaces/user-enricher.interface.js +4 -0
- package/cjs/modules/auth.module.js +65 -143
- package/cjs/services/auth-config.service.js +25 -27
- package/cjs/services/auth-datasource.provider.js +13 -23
- package/cjs/services/auth-email.service.js +456 -0
- package/cjs/services/authentication.service.js +297 -349
- package/cjs/services/branch.service.js +9 -4
- package/cjs/services/company-selection-session.service.js +1 -1
- package/cjs/services/index.js +1 -0
- package/cjs/services/user-permission.service.js +43 -73
- package/cjs/services/user.service.js +184 -34
- package/cjs/strategies/jwt.strategy.js +44 -44
- package/cjs/validators/password.validator.js +45 -0
- package/config/auth.constants.d.ts +3 -0
- package/controllers/authentication.controller.d.ts +16 -10
- package/controllers/company-selection.controller.d.ts +6 -2
- package/controllers/user-permission.controller.d.ts +5 -4
- package/controllers/user.controller.d.ts +33 -0
- package/dtos/authentication.dto.d.ts +20 -6
- 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 -2
- package/entities/index.d.ts +7 -3
- package/entities/pending-registration.entity.d.ts +17 -0
- package/entities/user-company-permission.entity.d.ts +1 -3
- package/entities/user-token.entity.d.ts +15 -0
- package/fesm/config/auth.constants.js +6 -2
- package/fesm/controllers/authentication.controller.js +368 -27
- 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/user-permission.controller.js +84 -156
- package/fesm/controllers/user.controller.js +214 -10
- package/fesm/docs/auth-swagger.config.js +14 -7
- package/fesm/dtos/authentication.dto.js +101 -39
- 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 +7 -1
- package/fesm/entities/pending-registration.entity.js +115 -0
- package/fesm/entities/user-company-permission.entity.js +3 -9
- package/fesm/entities/user-token.entity.js +113 -0
- 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 +38 -0
- package/fesm/interfaces/authentication.interface.js +1 -1
- package/fesm/interfaces/index.js +2 -0
- package/fesm/interfaces/user-enricher.interface.js +26 -0
- package/fesm/modules/auth.module.js +67 -145
- package/fesm/services/auth-config.service.js +26 -28
- package/fesm/services/auth-datasource.provider.js +14 -24
- package/fesm/services/auth-email.service.js +405 -0
- package/fesm/services/authentication.service.js +297 -349
- package/fesm/services/branch.service.js +9 -4
- package/fesm/services/company-selection-session.service.js +1 -1
- package/fesm/services/index.js +1 -0
- package/fesm/services/user-permission.service.js +44 -74
- package/fesm/services/user.service.js +186 -36
- 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/auth-email-provider.interface.d.ts +6 -0
- package/interfaces/auth-module-options.interface.d.ts +4 -1
- package/interfaces/authentication.interface.d.ts +13 -3
- package/interfaces/index.d.ts +2 -0
- package/interfaces/user-enricher.interface.d.ts +64 -0
- package/interfaces/user.interface.d.ts +1 -0
- package/modules/auth.module.d.ts +6 -3
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +7 -8
- package/services/auth-datasource.provider.d.ts +2 -4
- package/services/auth-email.service.d.ts +54 -0
- package/services/authentication.service.d.ts +27 -16
- package/services/company-selection-session.service.d.ts +1 -1
- package/services/index.d.ts +1 -0
- package/services/user-permission.service.d.ts +6 -9
- package/services/user.service.d.ts +19 -3
- 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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get TokenType () {
|
|
13
|
+
return TokenType;
|
|
14
|
+
},
|
|
15
|
+
get UserToken () {
|
|
16
|
+
return UserToken;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _typeorm = require("typeorm");
|
|
20
|
+
function _define_property(obj, key, value) {
|
|
21
|
+
if (key in obj) {
|
|
22
|
+
Object.defineProperty(obj, key, {
|
|
23
|
+
value: value,
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
obj[key] = value;
|
|
30
|
+
}
|
|
31
|
+
return obj;
|
|
32
|
+
}
|
|
33
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
34
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
35
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
36
|
+
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;
|
|
37
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
38
|
+
}
|
|
39
|
+
function _ts_metadata(k, v) {
|
|
40
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
41
|
+
}
|
|
42
|
+
var TokenType = /*#__PURE__*/ function(TokenType) {
|
|
43
|
+
TokenType["PASSWORD_RESET"] = "password_reset";
|
|
44
|
+
TokenType["EMAIL_VERIFICATION"] = "email_verification";
|
|
45
|
+
TokenType["EMAIL_CHANGE"] = "email_change";
|
|
46
|
+
return TokenType;
|
|
47
|
+
}({});
|
|
48
|
+
let UserToken = class UserToken {
|
|
49
|
+
constructor(){
|
|
50
|
+
_define_property(this, "id", void 0);
|
|
51
|
+
_define_property(this, "userId", void 0);
|
|
52
|
+
_define_property(this, "type", void 0);
|
|
53
|
+
_define_property(this, "token", void 0);
|
|
54
|
+
_define_property(this, "expiresAt", void 0);
|
|
55
|
+
_define_property(this, "usedAt", void 0);
|
|
56
|
+
_define_property(this, "metadata", void 0);
|
|
57
|
+
_define_property(this, "createdAt", void 0);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
_ts_decorate([
|
|
61
|
+
(0, _typeorm.PrimaryGeneratedColumn)('uuid'),
|
|
62
|
+
_ts_metadata("design:type", String)
|
|
63
|
+
], UserToken.prototype, "id", void 0);
|
|
64
|
+
_ts_decorate([
|
|
65
|
+
(0, _typeorm.Column)({
|
|
66
|
+
type: 'uuid',
|
|
67
|
+
name: 'user_id'
|
|
68
|
+
}),
|
|
69
|
+
_ts_metadata("design:type", String)
|
|
70
|
+
], UserToken.prototype, "userId", void 0);
|
|
71
|
+
_ts_decorate([
|
|
72
|
+
(0, _typeorm.Column)({
|
|
73
|
+
type: 'varchar',
|
|
74
|
+
length: 32
|
|
75
|
+
}),
|
|
76
|
+
_ts_metadata("design:type", String)
|
|
77
|
+
], UserToken.prototype, "type", void 0);
|
|
78
|
+
_ts_decorate([
|
|
79
|
+
(0, _typeorm.Column)({
|
|
80
|
+
type: 'varchar',
|
|
81
|
+
length: 64
|
|
82
|
+
}),
|
|
83
|
+
_ts_metadata("design:type", String)
|
|
84
|
+
], UserToken.prototype, "token", void 0);
|
|
85
|
+
_ts_decorate([
|
|
86
|
+
(0, _typeorm.Column)({
|
|
87
|
+
type: 'timestamp',
|
|
88
|
+
name: 'expires_at'
|
|
89
|
+
}),
|
|
90
|
+
_ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
|
|
91
|
+
], UserToken.prototype, "expiresAt", void 0);
|
|
92
|
+
_ts_decorate([
|
|
93
|
+
(0, _typeorm.Column)({
|
|
94
|
+
type: 'timestamp',
|
|
95
|
+
name: 'used_at',
|
|
96
|
+
nullable: true
|
|
97
|
+
}),
|
|
98
|
+
_ts_metadata("design:type", Object)
|
|
99
|
+
], UserToken.prototype, "usedAt", void 0);
|
|
100
|
+
_ts_decorate([
|
|
101
|
+
(0, _typeorm.Column)({
|
|
102
|
+
type: 'varchar',
|
|
103
|
+
length: 255,
|
|
104
|
+
nullable: true
|
|
105
|
+
}),
|
|
106
|
+
_ts_metadata("design:type", Object)
|
|
107
|
+
], UserToken.prototype, "metadata", void 0);
|
|
108
|
+
_ts_decorate([
|
|
109
|
+
(0, _typeorm.CreateDateColumn)({
|
|
110
|
+
type: 'timestamp',
|
|
111
|
+
name: 'created_at'
|
|
112
|
+
}),
|
|
113
|
+
_ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
|
|
114
|
+
], UserToken.prototype, "createdAt", void 0);
|
|
115
|
+
UserToken = _ts_decorate([
|
|
116
|
+
(0, _typeorm.Entity)('user_tokens'),
|
|
117
|
+
(0, _typeorm.Index)('IDX_user_token_token', [
|
|
118
|
+
'token'
|
|
119
|
+
], {
|
|
120
|
+
unique: true
|
|
121
|
+
}),
|
|
122
|
+
(0, _typeorm.Index)('IDX_user_token_user_type', [
|
|
123
|
+
'userId',
|
|
124
|
+
'type'
|
|
125
|
+
]),
|
|
126
|
+
(0, _typeorm.Index)('IDX_user_token_expires', [
|
|
127
|
+
'expiresAt'
|
|
128
|
+
])
|
|
129
|
+
], UserToken);
|
|
@@ -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
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Email Provider Interface
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the contract for email sending in the auth module.
|
|
5
|
+
* It allows auth to work independently of the email module.
|
|
6
|
+
*
|
|
7
|
+
* To use email features in auth:
|
|
8
|
+
* 1. Provide AUTH_EMAIL_PROVIDER in your app module
|
|
9
|
+
* 2. Implement IAuthEmailProvider using EmailSendService from nestjs-email
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // In app.module.ts or a provider file
|
|
14
|
+
* {
|
|
15
|
+
* provide: AUTH_EMAIL_PROVIDER,
|
|
16
|
+
* useFactory: (emailSendService: EmailSendService) => ({
|
|
17
|
+
* sendPasswordResetEmail: async (email, token, resetUrl) => {
|
|
18
|
+
* await emailSendService.sendTemplateEmail({
|
|
19
|
+
* templateSlug: 'password-reset',
|
|
20
|
+
* to: email,
|
|
21
|
+
* variables: { resetUrl, token },
|
|
22
|
+
* });
|
|
23
|
+
* },
|
|
24
|
+
* sendVerificationEmail: async (email, token, verifyUrl) => {
|
|
25
|
+
* await emailSendService.sendTemplateEmail({
|
|
26
|
+
* templateSlug: 'email-verification',
|
|
27
|
+
* to: email,
|
|
28
|
+
* variables: { verifyUrl, token },
|
|
29
|
+
* });
|
|
30
|
+
* },
|
|
31
|
+
* }),
|
|
32
|
+
* inject: [EmailSendService],
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/ "use strict";
|
|
36
|
+
Object.defineProperty(exports, "__esModule", {
|
|
37
|
+
value: true
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(exports, "AUTH_EMAIL_PROVIDER", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get: function() {
|
|
42
|
+
return AUTH_EMAIL_PROVIDER;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const AUTH_EMAIL_PROVIDER = 'AUTH_EMAIL_PROVIDER';
|
package/cjs/interfaces/index.js
CHANGED
|
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
_export_star(require("./authentication.interface"), exports);
|
|
6
|
+
_export_star(require("./auth-email-provider.interface"), exports);
|
|
6
7
|
_export_star(require("./company-branch.interface"), exports);
|
|
7
8
|
_export_star(require("./company.interface"), exports);
|
|
8
9
|
_export_star(require("./user.interface"), exports);
|
|
10
|
+
_export_star(require("./user-enricher.interface"), exports);
|
|
9
11
|
_export_star(require("./auth-module-options.interface"), exports);
|
|
10
12
|
function _export_star(from, to) {
|
|
11
13
|
Object.keys(from).forEach(function(k) {
|
|
@@ -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,79 +30,42 @@ 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
|
-
_services.AuthenticationService,
|
|
71
|
-
// Interceptors
|
|
72
|
-
_settokeninterceptor.SetToken,
|
|
73
|
-
_cleartokeninterceptor.ClearToken,
|
|
74
|
-
// Core services (always included)
|
|
75
|
-
_services.UserService
|
|
76
|
-
];
|
|
77
|
-
// Company feature services (conditional)
|
|
78
|
-
if (enableCompanyFeature) {
|
|
79
|
-
providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
80
|
-
}
|
|
81
|
-
// Build exports
|
|
82
|
-
const exports1 = [
|
|
83
|
-
_passport.PassportModule,
|
|
84
|
-
_authconstants.AUTH_MODULE_OPTIONS,
|
|
85
|
-
_authconfigservice.AuthConfigService,
|
|
86
|
-
_authdatasourceprovider.AuthDataSourceProvider,
|
|
87
|
-
_jwtstrategy.JwtStrategy,
|
|
88
|
-
_guards.JwtAuthGuard,
|
|
89
|
-
_services.AuthenticationService,
|
|
90
|
-
_services.UserService
|
|
91
|
-
];
|
|
92
|
-
if (enableCompanyFeature) {
|
|
93
|
-
exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
94
|
-
}
|
|
46
|
+
...options.providers ?? []
|
|
47
|
+
], options.imports);
|
|
48
|
+
}
|
|
49
|
+
/** Build the dynamic module with shared logic */ static buildModule(options, providers, externalImports = []) {
|
|
50
|
+
const { global = false, includeController = true, bootstrapAppConfig } = options;
|
|
51
|
+
const enableCompanyFeature = bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
95
52
|
return {
|
|
96
53
|
module: AuthModule,
|
|
97
54
|
global,
|
|
98
|
-
imports
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
55
|
+
imports: [
|
|
56
|
+
...externalImports,
|
|
57
|
+
...this.buildImports()
|
|
58
|
+
],
|
|
59
|
+
controllers: this.buildControllers(includeController, enableCompanyFeature),
|
|
60
|
+
providers: [
|
|
61
|
+
...providers,
|
|
62
|
+
...this.buildProviders(enableCompanyFeature)
|
|
63
|
+
],
|
|
64
|
+
exports: this.buildExports(enableCompanyFeature)
|
|
102
65
|
};
|
|
103
66
|
}
|
|
104
|
-
static
|
|
105
|
-
|
|
106
|
-
const imports = [
|
|
67
|
+
/** Common module imports */ static buildImports() {
|
|
68
|
+
return [
|
|
107
69
|
_passport.PassportModule.register({
|
|
108
70
|
defaultStrategy: 'jwt'
|
|
109
71
|
}),
|
|
@@ -111,40 +73,36 @@ let AuthModule = class AuthModule {
|
|
|
111
73
|
_modules.CacheModule,
|
|
112
74
|
_modules.UtilsModule
|
|
113
75
|
];
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (includeController)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
|
|
124
|
-
}
|
|
76
|
+
}
|
|
77
|
+
/** Build controllers based on feature flags */ static buildControllers(includeController, enableCompanyFeature) {
|
|
78
|
+
if (!includeController) return [];
|
|
79
|
+
const controllers = [
|
|
80
|
+
_controllers.AuthenticationController,
|
|
81
|
+
_controllers.UserController
|
|
82
|
+
];
|
|
83
|
+
if (enableCompanyFeature) {
|
|
84
|
+
controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
|
|
125
85
|
}
|
|
86
|
+
return controllers;
|
|
87
|
+
}
|
|
88
|
+
/** Core providers (without AUTH_MODULE_OPTIONS - that's added separately) */ static buildProviders(enableCompanyFeature) {
|
|
126
89
|
const providers = [
|
|
127
|
-
{
|
|
128
|
-
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
129
|
-
useValue: options
|
|
130
|
-
},
|
|
131
|
-
// Config & Infrastructure
|
|
132
90
|
_authconfigservice.AuthConfigService,
|
|
133
91
|
_authdatasourceprovider.AuthDataSourceProvider,
|
|
134
|
-
// Auth core
|
|
135
92
|
_jwtstrategy.JwtStrategy,
|
|
136
93
|
_guards.JwtAuthGuard,
|
|
137
94
|
_services.AuthenticationService,
|
|
138
|
-
|
|
95
|
+
_services.AuthEmailService,
|
|
139
96
|
_settokeninterceptor.SetToken,
|
|
140
97
|
_cleartokeninterceptor.ClearToken,
|
|
141
|
-
// Core services (always included)
|
|
142
98
|
_services.UserService
|
|
143
99
|
];
|
|
144
|
-
// Company feature services (conditional)
|
|
145
100
|
if (enableCompanyFeature) {
|
|
146
101
|
providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
147
102
|
}
|
|
103
|
+
return providers;
|
|
104
|
+
}
|
|
105
|
+
/** Build module exports */ static buildExports(enableCompanyFeature) {
|
|
148
106
|
const exports1 = [
|
|
149
107
|
_passport.PassportModule,
|
|
150
108
|
_authconstants.AUTH_MODULE_OPTIONS,
|
|
@@ -153,21 +111,15 @@ let AuthModule = class AuthModule {
|
|
|
153
111
|
_jwtstrategy.JwtStrategy,
|
|
154
112
|
_guards.JwtAuthGuard,
|
|
155
113
|
_services.AuthenticationService,
|
|
114
|
+
_services.AuthEmailService,
|
|
156
115
|
_services.UserService
|
|
157
116
|
];
|
|
158
117
|
if (enableCompanyFeature) {
|
|
159
118
|
exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
|
|
160
119
|
}
|
|
161
|
-
return
|
|
162
|
-
module: AuthModule,
|
|
163
|
-
global,
|
|
164
|
-
imports,
|
|
165
|
-
controllers,
|
|
166
|
-
providers,
|
|
167
|
-
exports: exports1
|
|
168
|
-
};
|
|
120
|
+
return exports1;
|
|
169
121
|
}
|
|
170
|
-
static createAsyncProviders(options) {
|
|
122
|
+
/** Create async providers for forRootAsync */ static createAsyncProviders(options) {
|
|
171
123
|
const staticOptions = {
|
|
172
124
|
global: options.global,
|
|
173
125
|
includeController: options.includeController,
|
|
@@ -177,13 +129,10 @@ let AuthModule = class AuthModule {
|
|
|
177
129
|
return [
|
|
178
130
|
{
|
|
179
131
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
180
|
-
useFactory: async (...args)=>{
|
|
181
|
-
const config = await options.useFactory(...args);
|
|
182
|
-
return {
|
|
132
|
+
useFactory: async (...args)=>({
|
|
183
133
|
...staticOptions,
|
|
184
|
-
config
|
|
185
|
-
}
|
|
186
|
-
},
|
|
134
|
+
config: await options.useFactory(...args)
|
|
135
|
+
}),
|
|
187
136
|
inject: options.inject || []
|
|
188
137
|
}
|
|
189
138
|
];
|
|
@@ -196,13 +145,10 @@ let AuthModule = class AuthModule {
|
|
|
196
145
|
},
|
|
197
146
|
{
|
|
198
147
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
199
|
-
useFactory: async (factory)=>{
|
|
200
|
-
const config = await factory.createAuthOptions();
|
|
201
|
-
return {
|
|
148
|
+
useFactory: async (factory)=>({
|
|
202
149
|
...staticOptions,
|
|
203
|
-
config
|
|
204
|
-
}
|
|
205
|
-
},
|
|
150
|
+
config: await factory.createAuthOptions()
|
|
151
|
+
}),
|
|
206
152
|
inject: [
|
|
207
153
|
options.useClass
|
|
208
154
|
]
|
|
@@ -213,13 +159,10 @@ let AuthModule = class AuthModule {
|
|
|
213
159
|
return [
|
|
214
160
|
{
|
|
215
161
|
provide: _authconstants.AUTH_MODULE_OPTIONS,
|
|
216
|
-
useFactory: async (factory)=>{
|
|
217
|
-
const config = await factory.createAuthOptions();
|
|
218
|
-
return {
|
|
162
|
+
useFactory: async (factory)=>({
|
|
219
163
|
...staticOptions,
|
|
220
|
-
config
|
|
221
|
-
}
|
|
222
|
-
},
|
|
164
|
+
config: await factory.createAuthOptions()
|
|
165
|
+
}),
|
|
223
166
|
inject: [
|
|
224
167
|
options.useExisting
|
|
225
168
|
]
|
|
@@ -233,35 +176,14 @@ let AuthModule = class AuthModule {
|
|
|
233
176
|
}
|
|
234
177
|
];
|
|
235
178
|
}
|
|
236
|
-
/**
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* Note: Must be REQUEST-scoped since AuthDataSourceProvider is REQUEST-scoped
|
|
240
|
-
*/ static getRepositoryProviders(enableCompanyFeature) {
|
|
241
|
-
const entities = this.getEntities(enableCompanyFeature);
|
|
242
|
-
return entities.map((entity)=>({
|
|
243
|
-
provide: (0, _typeorm.getRepositoryToken)(entity),
|
|
244
|
-
scope: _common.Scope.REQUEST,
|
|
245
|
-
useFactory: async (dataSourceProvider)=>{
|
|
246
|
-
return await dataSourceProvider.getRepository(entity);
|
|
247
|
-
},
|
|
248
|
-
inject: [
|
|
249
|
-
_authdatasourceprovider.AuthDataSourceProvider
|
|
250
|
-
]
|
|
251
|
-
}));
|
|
252
|
-
}
|
|
253
|
-
static getEntities(enableCompanyFeature = false) {
|
|
254
|
-
const coreEntities = [
|
|
255
|
-
_entities.User
|
|
256
|
-
];
|
|
257
|
-
const companyEntities = enableCompanyFeature ? [
|
|
179
|
+
/** Get auth entities based on feature flags */ static getEntities(enableCompanyFeature = false) {
|
|
180
|
+
return enableCompanyFeature ? [
|
|
181
|
+
_entities.User,
|
|
258
182
|
_entities.Company,
|
|
259
183
|
_entities.CompanyBranch,
|
|
260
184
|
_entities.UserCompanyPermission
|
|
261
|
-
] : [
|
|
262
|
-
|
|
263
|
-
...coreEntities,
|
|
264
|
-
...companyEntities
|
|
185
|
+
] : [
|
|
186
|
+
_entities.User
|
|
265
187
|
];
|
|
266
188
|
}
|
|
267
189
|
};
|