@flusys/nestjs-auth 1.0.0-beta → 1.0.0-rc
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 +274 -291
- package/cjs/config/auth.constants.js +12 -0
- package/cjs/controllers/authentication.controller.js +219 -10
- 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 +40 -25
- package/cjs/controllers/user.controller.js +211 -7
- package/cjs/dtos/authentication.dto.js +119 -13
- 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 +0 -6
- package/cjs/entities/user-token.entity.js +129 -0
- package/cjs/guards/auth-throttler.guard.js +53 -0
- package/cjs/interceptors/clear-token.interceptor.js +3 -6
- package/cjs/interceptors/set-token.interceptor.js +38 -31
- 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 +8 -20
- package/cjs/services/auth-config.service.js +23 -2
- package/cjs/services/auth-datasource.provider.js +5 -3
- package/cjs/services/auth-email.service.js +471 -0
- package/cjs/services/authentication.service.js +169 -77
- package/cjs/services/branch.service.js +6 -5
- package/cjs/services/company-selection-session.service.js +1 -1
- package/cjs/services/index.js +1 -0
- package/cjs/services/user-permission.service.js +0 -2
- package/cjs/services/user.service.js +213 -34
- package/cjs/validators/password.validator.js +45 -0
- package/config/auth.constants.d.ts +3 -0
- package/controllers/authentication.controller.d.ts +13 -9
- package/controllers/company-selection.controller.d.ts +6 -2
- package/controllers/user.controller.d.ts +33 -0
- package/dtos/authentication.dto.d.ts +21 -3
- package/dtos/company-branch.dto.d.ts +0 -1
- package/dtos/company.dto.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 +0 -2
- package/entities/user-token.entity.d.ts +15 -0
- package/fesm/config/auth.constants.js +6 -2
- package/fesm/controllers/authentication.controller.js +221 -12
- 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 +41 -26
- package/fesm/controllers/user.controller.js +214 -10
- package/fesm/dtos/authentication.dto.js +106 -14
- 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 +0 -6
- package/fesm/entities/user-token.entity.js +113 -0
- package/fesm/guards/auth-throttler.guard.js +43 -0
- package/fesm/interceptors/clear-token.interceptor.js +2 -5
- package/fesm/interceptors/set-token.interceptor.js +37 -30
- 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 +10 -22
- package/fesm/services/auth-config.service.js +24 -3
- package/fesm/services/auth-datasource.provider.js +6 -4
- package/fesm/services/auth-email.service.js +420 -0
- package/fesm/services/authentication.service.js +169 -77
- package/fesm/services/branch.service.js +6 -5
- package/fesm/services/company-selection-session.service.js +1 -1
- package/fesm/services/index.js +1 -0
- package/fesm/services/user-permission.service.js +1 -3
- package/fesm/services/user.service.js +215 -36
- package/fesm/validators/password.validator.js +48 -0
- package/guards/auth-throttler.guard.d.ts +7 -0
- package/interceptors/set-token.interceptor.d.ts +1 -0
- 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 +14 -0
- 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 +0 -1
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +5 -1
- package/services/auth-email.service.d.ts +51 -0
- package/services/authentication.service.d.ts +16 -11
- package/services/company-selection-session.service.d.ts +1 -1
- package/services/index.d.ts +1 -0
- package/services/user-permission.service.d.ts +0 -1
- package/services/user.service.d.ts +19 -3
- package/validators/password.validator.d.ts +10 -0
|
@@ -10,15 +10,14 @@ Object.defineProperty(exports, "AuthenticationService", {
|
|
|
10
10
|
});
|
|
11
11
|
const _common = require("@nestjs/common");
|
|
12
12
|
const _jwt = require("@nestjs/jwt");
|
|
13
|
-
const _typeorm = require("@nestjs/typeorm");
|
|
14
13
|
const _bcrypt = /*#__PURE__*/ _interop_require_wildcard(require("bcrypt"));
|
|
15
|
-
const _typeorm1 = require("typeorm");
|
|
16
14
|
const _utils = require("@flusys/nestjs-shared/utils");
|
|
17
15
|
const _authconfigservice = require("./auth-config.service");
|
|
18
16
|
const _authdatasourceprovider = require("./auth-datasource.provider");
|
|
19
17
|
const _enums = require("../enums");
|
|
20
18
|
const _config = require("../config");
|
|
21
19
|
const _classes = require("@flusys/nestjs-shared/classes");
|
|
20
|
+
const _authemailservice = require("./auth-email.service");
|
|
22
21
|
const _companybranchentity = require("../entities/company-branch.entity");
|
|
23
22
|
const _companyentity = require("../entities/company.entity");
|
|
24
23
|
const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
|
|
@@ -95,34 +94,22 @@ function _ts_param(paramIndex, decorator) {
|
|
|
95
94
|
let AuthenticationService = class AuthenticationService {
|
|
96
95
|
// Repository Getters
|
|
97
96
|
async getUserRepository() {
|
|
98
|
-
if (this.dataSourceProvider) {
|
|
99
|
-
|
|
97
|
+
if (!this.dataSourceProvider) {
|
|
98
|
+
throw new Error('User repository not available');
|
|
100
99
|
}
|
|
101
|
-
|
|
102
|
-
return this.injectedUserRepository;
|
|
103
|
-
}
|
|
104
|
-
throw new Error('User repository not available');
|
|
100
|
+
return this.dataSourceProvider.getRepository(_userentity.User);
|
|
105
101
|
}
|
|
106
102
|
async getPermissionRepository() {
|
|
107
|
-
if (!this.authConfig.isCompanyFeatureEnabled()) return null;
|
|
108
|
-
|
|
109
|
-
return this.dataSourceProvider.getRepository(_usercompanypermissionentity.UserCompanyPermission);
|
|
110
|
-
}
|
|
111
|
-
return this.injectedPermissionRepository ?? null;
|
|
103
|
+
if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
104
|
+
return this.dataSourceProvider.getRepository(_usercompanypermissionentity.UserCompanyPermission);
|
|
112
105
|
}
|
|
113
106
|
async getCompanyRepository() {
|
|
114
|
-
if (!this.authConfig.isCompanyFeatureEnabled()) return null;
|
|
115
|
-
|
|
116
|
-
return this.dataSourceProvider.getRepository(_companyentity.Company);
|
|
117
|
-
}
|
|
118
|
-
return this.injectedCompanyRepository ?? null;
|
|
107
|
+
if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
108
|
+
return this.dataSourceProvider.getRepository(_companyentity.Company);
|
|
119
109
|
}
|
|
120
110
|
async getBranchRepository() {
|
|
121
|
-
if (!this.authConfig.isCompanyFeatureEnabled()) return null;
|
|
122
|
-
|
|
123
|
-
return this.dataSourceProvider.getRepository(_companybranchentity.CompanyBranch);
|
|
124
|
-
}
|
|
125
|
-
return this.injectedBranchRepository ?? null;
|
|
111
|
+
if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
112
|
+
return this.dataSourceProvider.getRepository(_companybranchentity.CompanyBranch);
|
|
126
113
|
}
|
|
127
114
|
// Login
|
|
128
115
|
/** Login with email and password. Returns tokens or requires company/branch selection. */ async login(email, password) {
|
|
@@ -130,7 +117,14 @@ let AuthenticationService = class AuthenticationService {
|
|
|
130
117
|
if (!user.isActive) {
|
|
131
118
|
throw new _common.UnauthorizedException('User account is deactivated');
|
|
132
119
|
}
|
|
133
|
-
//
|
|
120
|
+
// Check email verification if email service is enabled
|
|
121
|
+
if (this.authEmailService?.isEmailEnabled() && !user.emailVerified) {
|
|
122
|
+
return {
|
|
123
|
+
requiresEmailVerification: true,
|
|
124
|
+
email: user.email,
|
|
125
|
+
message: 'Please verify your email address before logging in.'
|
|
126
|
+
};
|
|
127
|
+
}
|
|
134
128
|
if (!this.authConfig.isCompanyFeatureEnabled()) {
|
|
135
129
|
return this.generateLoginResponse(user);
|
|
136
130
|
}
|
|
@@ -187,10 +181,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
187
181
|
return await this.generateCompanySelectionResponse(user, companies, branches);
|
|
188
182
|
}
|
|
189
183
|
// Registration
|
|
190
|
-
/** Register a new user. If
|
|
184
|
+
/** Register a new user. If email enabled, creates pending registration. Otherwise creates user directly. */ async register(dto, verifyUrlBase) {
|
|
191
185
|
const userRepository = await this.getUserRepository();
|
|
192
|
-
// Check if user exists
|
|
193
|
-
// Note: Generic error message to prevent email enumeration attacks
|
|
194
186
|
const existingUser = await userRepository.findOne({
|
|
195
187
|
where: {
|
|
196
188
|
email: dto.email
|
|
@@ -199,7 +191,33 @@ let AuthenticationService = class AuthenticationService {
|
|
|
199
191
|
if (existingUser) {
|
|
200
192
|
throw new _common.BadRequestException('Registration failed. Please try again or contact support.');
|
|
201
193
|
}
|
|
202
|
-
//
|
|
194
|
+
// If email verification is enabled, create pending registration instead of user
|
|
195
|
+
if (this.authEmailService?.isEmailEnabled() && verifyUrlBase) {
|
|
196
|
+
const companyData = this.authConfig.isCompanyFeatureEnabled() ? {
|
|
197
|
+
companySlug: dto.companySlug,
|
|
198
|
+
branchSlug: dto.branchSlug,
|
|
199
|
+
newCompanyName: dto.newCompanyName,
|
|
200
|
+
newCompanyPhone: dto.newCompanyPhone,
|
|
201
|
+
newCompanyAddress: dto.newCompanyAddress
|
|
202
|
+
} : undefined;
|
|
203
|
+
const result = await this.authEmailService.createPendingRegistration({
|
|
204
|
+
email: dto.email,
|
|
205
|
+
name: dto.name,
|
|
206
|
+
phone: dto.phone,
|
|
207
|
+
password: dto.password,
|
|
208
|
+
companyData,
|
|
209
|
+
verifyUrlBase
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
requiresEmailVerification: true,
|
|
213
|
+
message: result.message
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// No email verification - create user directly
|
|
217
|
+
return this.createUserDirectly(dto);
|
|
218
|
+
}
|
|
219
|
+
/** Create user directly (no email verification) */ async createUserDirectly(dto) {
|
|
220
|
+
const userRepository = await this.getUserRepository();
|
|
203
221
|
const hashedPassword = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
|
|
204
222
|
const user = userRepository.create({
|
|
205
223
|
name: dto.name,
|
|
@@ -211,38 +229,68 @@ let AuthenticationService = class AuthenticationService {
|
|
|
211
229
|
phoneVerified: false
|
|
212
230
|
});
|
|
213
231
|
await userRepository.save(user);
|
|
214
|
-
// If company feature not enabled, return simple response
|
|
215
232
|
if (!this.authConfig.isCompanyFeatureEnabled()) {
|
|
216
|
-
return this.
|
|
233
|
+
return this.generateRegistrationResponse(user, false, false);
|
|
217
234
|
}
|
|
218
|
-
|
|
219
|
-
return this.handleCompanyRegistration(user, dto);
|
|
235
|
+
return this.handleCompanyRegistration(user, dto, false);
|
|
220
236
|
}
|
|
221
|
-
/**
|
|
237
|
+
/** Create user from pending registration (after email verification) */ async createUserFromPendingRegistration(pending) {
|
|
238
|
+
const userRepository = await this.getUserRepository();
|
|
239
|
+
// Check if user already exists (race condition protection)
|
|
240
|
+
const existingUser = await userRepository.findOne({
|
|
241
|
+
where: {
|
|
242
|
+
email: pending.email
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
if (existingUser) {
|
|
246
|
+
throw new _common.BadRequestException('This email has already been registered.');
|
|
247
|
+
}
|
|
248
|
+
// Create user with verified email
|
|
249
|
+
const user = userRepository.create({
|
|
250
|
+
name: pending.name,
|
|
251
|
+
email: pending.email,
|
|
252
|
+
phone: pending.phone,
|
|
253
|
+
password: pending.passwordHash,
|
|
254
|
+
isActive: true,
|
|
255
|
+
emailVerified: true,
|
|
256
|
+
phoneVerified: false
|
|
257
|
+
});
|
|
258
|
+
await userRepository.save(user);
|
|
259
|
+
// Handle company feature if enabled
|
|
260
|
+
if (this.authConfig.isCompanyFeatureEnabled() && pending.companyData) {
|
|
261
|
+
return this.handleCompanyRegistrationFromPending(user, pending.companyData);
|
|
262
|
+
}
|
|
263
|
+
return this.generateRegistrationResponse(user, this.authConfig.isCompanyFeatureEnabled(), false);
|
|
264
|
+
}
|
|
265
|
+
/** Handle company registration from pending registration data */ async handleCompanyRegistrationFromPending(user, companyData) {
|
|
266
|
+
return this.processCompanyRegistration(user, companyData, false);
|
|
267
|
+
}
|
|
268
|
+
/** Handle company-related registration logic */ async handleCompanyRegistration(user, dto, requiresEmailVerification) {
|
|
269
|
+
return this.processCompanyRegistration(user, dto, requiresEmailVerification);
|
|
270
|
+
}
|
|
271
|
+
/** Shared logic for company registration (join existing or create new) */ async processCompanyRegistration(user, data, requiresEmailVerification) {
|
|
222
272
|
const companyRepository = await this.getCompanyRepository();
|
|
223
273
|
const branchRepository = await this.getBranchRepository();
|
|
224
274
|
const permissionRepository = await this.getPermissionRepository();
|
|
225
275
|
if (!companyRepository || !branchRepository || !permissionRepository) {
|
|
226
|
-
return this.
|
|
276
|
+
return this.generateRegistrationResponse(user, true, requiresEmailVerification);
|
|
227
277
|
}
|
|
228
278
|
let company = null;
|
|
229
279
|
let branch = null;
|
|
230
|
-
|
|
231
|
-
if (dto.companySlug) {
|
|
280
|
+
if (data.companySlug) {
|
|
232
281
|
company = await companyRepository.findOne({
|
|
233
282
|
where: {
|
|
234
|
-
slug:
|
|
283
|
+
slug: data.companySlug,
|
|
235
284
|
isActive: true
|
|
236
285
|
}
|
|
237
286
|
});
|
|
238
287
|
if (!company) {
|
|
239
288
|
throw new _common.BadRequestException('Company not found or inactive');
|
|
240
289
|
}
|
|
241
|
-
|
|
242
|
-
if (dto.branchSlug) {
|
|
290
|
+
if (data.branchSlug) {
|
|
243
291
|
branch = await branchRepository.findOne({
|
|
244
292
|
where: {
|
|
245
|
-
slug:
|
|
293
|
+
slug: data.branchSlug,
|
|
246
294
|
companyId: company.id,
|
|
247
295
|
isActive: true
|
|
248
296
|
}
|
|
@@ -251,7 +299,6 @@ let AuthenticationService = class AuthenticationService {
|
|
|
251
299
|
throw new _common.BadRequestException('Branch not found or inactive');
|
|
252
300
|
}
|
|
253
301
|
} else {
|
|
254
|
-
// Get first active branch
|
|
255
302
|
branch = await branchRepository.findOne({
|
|
256
303
|
where: {
|
|
257
304
|
companyId: company.id,
|
|
@@ -263,9 +310,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
263
310
|
}
|
|
264
311
|
});
|
|
265
312
|
}
|
|
266
|
-
} else if (
|
|
267
|
-
const slug = this.generateSlug(
|
|
268
|
-
// Check if slug exists
|
|
313
|
+
} else if (data.newCompanyName) {
|
|
314
|
+
const slug = this.generateSlug(data.newCompanyName);
|
|
269
315
|
const existingCompany = await companyRepository.findOne({
|
|
270
316
|
where: {
|
|
271
317
|
slug
|
|
@@ -274,16 +320,14 @@ let AuthenticationService = class AuthenticationService {
|
|
|
274
320
|
if (existingCompany) {
|
|
275
321
|
throw new _common.BadRequestException('Company creation failed. Please try a different name.');
|
|
276
322
|
}
|
|
277
|
-
// Create company
|
|
278
323
|
company = companyRepository.create({
|
|
279
|
-
name:
|
|
324
|
+
name: data.newCompanyName,
|
|
280
325
|
slug,
|
|
281
|
-
phone:
|
|
282
|
-
address:
|
|
326
|
+
phone: data.newCompanyPhone,
|
|
327
|
+
address: data.newCompanyAddress,
|
|
283
328
|
isActive: true
|
|
284
329
|
});
|
|
285
330
|
await companyRepository.save(company);
|
|
286
|
-
// Create default branch
|
|
287
331
|
branch = branchRepository.create({
|
|
288
332
|
name: 'Main Branch',
|
|
289
333
|
slug: 'main-branch',
|
|
@@ -292,16 +336,13 @@ let AuthenticationService = class AuthenticationService {
|
|
|
292
336
|
});
|
|
293
337
|
await branchRepository.save(branch);
|
|
294
338
|
}
|
|
295
|
-
// Create permissions if company exists
|
|
296
339
|
if (company) {
|
|
297
|
-
// Create company permission
|
|
298
340
|
const companyPermission = permissionRepository.create({
|
|
299
341
|
userId: user.id,
|
|
300
342
|
permissionType: _enums.PermissionType.COMPANY,
|
|
301
343
|
targetId: company.id
|
|
302
344
|
});
|
|
303
345
|
await permissionRepository.save(companyPermission);
|
|
304
|
-
// Create branch permission if branch exists
|
|
305
346
|
if (branch) {
|
|
306
347
|
const branchPermission = permissionRepository.create({
|
|
307
348
|
userId: user.id,
|
|
@@ -310,10 +351,9 @@ let AuthenticationService = class AuthenticationService {
|
|
|
310
351
|
});
|
|
311
352
|
await permissionRepository.save(branchPermission);
|
|
312
353
|
}
|
|
313
|
-
return this.
|
|
354
|
+
return this.generateRegistrationResponseWithCompany(user, company, branch ?? undefined, requiresEmailVerification);
|
|
314
355
|
}
|
|
315
|
-
|
|
316
|
-
return this.generateLoginResponse(user, true);
|
|
356
|
+
return this.generateRegistrationResponse(user, true, requiresEmailVerification);
|
|
317
357
|
}
|
|
318
358
|
/** Generate URL-friendly slug from name */ generateSlug(name) {
|
|
319
359
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').substring(0, 100);
|
|
@@ -451,6 +491,11 @@ let AuthenticationService = class AuthenticationService {
|
|
|
451
491
|
const payload = this.jwtService.verify(refreshToken, {
|
|
452
492
|
secret: this.authConfig.getRefreshTokenSecret()
|
|
453
493
|
});
|
|
494
|
+
// Check if token has been revoked (user logged out after token was issued)
|
|
495
|
+
const isRevoked = await this.isTokenRevoked(payload.id, payload.iat);
|
|
496
|
+
if (isRevoked) {
|
|
497
|
+
throw new _common.UnauthorizedException('Token has been revoked');
|
|
498
|
+
}
|
|
454
499
|
const userRepository = await this.getUserRepository();
|
|
455
500
|
const user = await userRepository.findOne({
|
|
456
501
|
where: {
|
|
@@ -531,8 +576,9 @@ let AuthenticationService = class AuthenticationService {
|
|
|
531
576
|
}
|
|
532
577
|
/** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
|
|
533
578
|
if (!this.cacheManager) {
|
|
534
|
-
// Cache
|
|
535
|
-
|
|
579
|
+
// Cache is required for secure logout - tokens cannot be revoked without it
|
|
580
|
+
this.logger.error(`SECURITY: Cache not available for logout (userId: ${userId}). ` + 'Token revocation failed - tokens will remain valid until expiry. ' + 'Configure cache (Redis) to enable proper token revocation.');
|
|
581
|
+
throw new _common.BadRequestException('Logout service temporarily unavailable. Please try again later.');
|
|
536
582
|
}
|
|
537
583
|
const revokedAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
|
|
538
584
|
const cacheKey = `${_config.TOKEN_REVOKED_PREFIX}:${userId}`;
|
|
@@ -540,6 +586,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
540
586
|
const refreshTokenExpiry = this.authConfig.getRefreshTokenExpiration();
|
|
541
587
|
const ttlMs = this.parseExpiryToMs(refreshTokenExpiry);
|
|
542
588
|
await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
|
|
589
|
+
this.logger.log(`User ${userId} logged out - all tokens revoked`);
|
|
543
590
|
}
|
|
544
591
|
/** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
|
|
545
592
|
if (!this.cacheManager || !tokenIssuedAt) {
|
|
@@ -666,6 +713,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
666
713
|
id: user.id,
|
|
667
714
|
email: user.email,
|
|
668
715
|
name: user.name ?? undefined,
|
|
716
|
+
phone: user.phone ?? undefined,
|
|
669
717
|
profilePictureId: user.profilePictureId ?? undefined
|
|
670
718
|
}
|
|
671
719
|
};
|
|
@@ -752,6 +800,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
752
800
|
id: user.id,
|
|
753
801
|
email: user.email,
|
|
754
802
|
name: user.name ?? undefined,
|
|
803
|
+
phone: user.phone ?? null,
|
|
755
804
|
profilePictureId: user.profilePictureId ?? null
|
|
756
805
|
},
|
|
757
806
|
companyFeatureEnabled
|
|
@@ -787,6 +836,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
787
836
|
id: user.id,
|
|
788
837
|
email: user.email,
|
|
789
838
|
name: user.name ?? undefined,
|
|
839
|
+
phone: user.phone ?? null,
|
|
790
840
|
profilePictureId: user.profilePictureId ?? null
|
|
791
841
|
},
|
|
792
842
|
company: {
|
|
@@ -832,32 +882,83 @@ let AuthenticationService = class AuthenticationService {
|
|
|
832
882
|
id: user.id,
|
|
833
883
|
email: user.email,
|
|
834
884
|
name: user.name ?? undefined,
|
|
885
|
+
phone: user.phone ?? null,
|
|
835
886
|
profilePictureId: user.profilePictureId ?? null
|
|
836
887
|
},
|
|
837
888
|
companies: companiesWithBranches
|
|
838
889
|
};
|
|
839
890
|
}
|
|
891
|
+
/** Generate registration response - tokens included only if email verification not required */ generateRegistrationResponse(user, companyFeatureEnabled, requiresEmailVerification) {
|
|
892
|
+
const userInfo = {
|
|
893
|
+
id: user.id,
|
|
894
|
+
email: user.email,
|
|
895
|
+
name: user.name ?? undefined,
|
|
896
|
+
phone: user.phone ?? null,
|
|
897
|
+
profilePictureId: user.profilePictureId ?? null
|
|
898
|
+
};
|
|
899
|
+
if (requiresEmailVerification) {
|
|
900
|
+
return {
|
|
901
|
+
user: userInfo,
|
|
902
|
+
companyFeatureEnabled,
|
|
903
|
+
requiresEmailVerification: true
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
const loginResponse = this.generateLoginResponse(user, companyFeatureEnabled);
|
|
907
|
+
return {
|
|
908
|
+
...loginResponse,
|
|
909
|
+
requiresEmailVerification: false
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
/** Generate registration response with company - tokens included only if email verification not required */ generateRegistrationResponseWithCompany(user, company, branch, requiresEmailVerification = false) {
|
|
913
|
+
const userInfo = {
|
|
914
|
+
id: user.id,
|
|
915
|
+
email: user.email,
|
|
916
|
+
name: user.name ?? undefined,
|
|
917
|
+
phone: user.phone ?? null,
|
|
918
|
+
profilePictureId: user.profilePictureId ?? null
|
|
919
|
+
};
|
|
920
|
+
const companyInfo = {
|
|
921
|
+
id: company.id,
|
|
922
|
+
name: company.name,
|
|
923
|
+
slug: company.slug,
|
|
924
|
+
logoId: company.logoId ?? null
|
|
925
|
+
};
|
|
926
|
+
const branchInfo = branch ? {
|
|
927
|
+
id: branch.id,
|
|
928
|
+
name: branch.name,
|
|
929
|
+
slug: branch.slug,
|
|
930
|
+
logoId: branch.logoId ?? null
|
|
931
|
+
} : undefined;
|
|
932
|
+
if (requiresEmailVerification) {
|
|
933
|
+
return {
|
|
934
|
+
user: userInfo,
|
|
935
|
+
company: companyInfo,
|
|
936
|
+
branch: branchInfo,
|
|
937
|
+
companyFeatureEnabled: true,
|
|
938
|
+
requiresEmailVerification: true
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
const loginResponse = this.generateLoginResponseWithCompany(user, company, branch);
|
|
942
|
+
return {
|
|
943
|
+
...loginResponse,
|
|
944
|
+
requiresEmailVerification: false
|
|
945
|
+
};
|
|
946
|
+
}
|
|
840
947
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
841
|
-
constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService,
|
|
948
|
+
constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService){
|
|
842
949
|
_define_property(this, "jwtService", void 0);
|
|
843
950
|
_define_property(this, "authConfig", void 0);
|
|
844
951
|
_define_property(this, "cacheManager", void 0);
|
|
845
952
|
_define_property(this, "dataSourceProvider", void 0);
|
|
846
953
|
_define_property(this, "sessionService", void 0);
|
|
847
|
-
_define_property(this, "
|
|
848
|
-
_define_property(this, "injectedPermissionRepository", void 0);
|
|
849
|
-
_define_property(this, "injectedCompanyRepository", void 0);
|
|
850
|
-
_define_property(this, "injectedBranchRepository", void 0);
|
|
954
|
+
_define_property(this, "authEmailService", void 0);
|
|
851
955
|
_define_property(this, "logger", void 0);
|
|
852
956
|
this.jwtService = jwtService;
|
|
853
957
|
this.authConfig = authConfig;
|
|
854
958
|
this.cacheManager = cacheManager;
|
|
855
959
|
this.dataSourceProvider = dataSourceProvider;
|
|
856
960
|
this.sessionService = sessionService;
|
|
857
|
-
this.
|
|
858
|
-
this.injectedPermissionRepository = injectedPermissionRepository;
|
|
859
|
-
this.injectedCompanyRepository = injectedCompanyRepository;
|
|
860
|
-
this.injectedBranchRepository = injectedBranchRepository;
|
|
961
|
+
this.authEmailService = authEmailService;
|
|
861
962
|
this.logger = new _common.Logger(AuthenticationService.name);
|
|
862
963
|
}
|
|
863
964
|
};
|
|
@@ -874,13 +975,7 @@ AuthenticationService = _ts_decorate([
|
|
|
874
975
|
_ts_param(4, (0, _common.Optional)()),
|
|
875
976
|
_ts_param(4, (0, _common.Inject)(_companyselectionsessionservice.CompanySelectionSessionService)),
|
|
876
977
|
_ts_param(5, (0, _common.Optional)()),
|
|
877
|
-
_ts_param(5, (0,
|
|
878
|
-
_ts_param(6, (0, _common.Optional)()),
|
|
879
|
-
_ts_param(6, (0, _typeorm.InjectRepository)(_usercompanypermissionentity.UserCompanyPermission)),
|
|
880
|
-
_ts_param(7, (0, _common.Optional)()),
|
|
881
|
-
_ts_param(7, (0, _typeorm.InjectRepository)(_companyentity.Company)),
|
|
882
|
-
_ts_param(8, (0, _common.Optional)()),
|
|
883
|
-
_ts_param(8, (0, _typeorm.InjectRepository)(_companybranchentity.CompanyBranch)),
|
|
978
|
+
_ts_param(5, (0, _common.Inject)(_authemailservice.AuthEmailService)),
|
|
884
979
|
_ts_metadata("design:type", Function),
|
|
885
980
|
_ts_metadata("design:paramtypes", [
|
|
886
981
|
typeof _jwt.JwtService === "undefined" ? Object : _jwt.JwtService,
|
|
@@ -888,9 +983,6 @@ AuthenticationService = _ts_decorate([
|
|
|
888
983
|
typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
|
|
889
984
|
typeof _authdatasourceprovider.AuthDataSourceProvider === "undefined" ? Object : _authdatasourceprovider.AuthDataSourceProvider,
|
|
890
985
|
typeof _companyselectionsessionservice.CompanySelectionSessionService === "undefined" ? Object : _companyselectionsessionservice.CompanySelectionSessionService,
|
|
891
|
-
typeof
|
|
892
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
893
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
894
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository
|
|
986
|
+
typeof _authemailservice.AuthEmailService === "undefined" ? Object : _authemailservice.AuthEmailService
|
|
895
987
|
])
|
|
896
988
|
], AuthenticationService);
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "BranchService", {
|
|
|
10
10
|
});
|
|
11
11
|
const _classes = require("@flusys/nestjs-shared/classes");
|
|
12
12
|
const _modules = require("@flusys/nestjs-shared/modules");
|
|
13
|
+
const _utils = require("@flusys/nestjs-shared/utils");
|
|
13
14
|
const _common = require("@nestjs/common");
|
|
14
15
|
const _companybranchentity = require("../entities/company-branch.entity");
|
|
15
16
|
const _authconfigservice = require("./auth-config.service");
|
|
@@ -76,11 +77,11 @@ let BranchService = class BranchService extends _classes.RequestScopedApiService
|
|
|
76
77
|
}
|
|
77
78
|
async getExtraManipulateQuery(query, filterDto, user) {
|
|
78
79
|
const result = await super.getExtraManipulateQuery(query, filterDto, user);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
80
|
+
(0, _utils.applyCompanyFilter)(query, {
|
|
81
|
+
isCompanyFeatureEnabled: this.authConfig.isCompanyFeatureEnabled(),
|
|
82
|
+
entityAlias: 'company_branch',
|
|
83
|
+
columnName: 'company_id'
|
|
84
|
+
}, user);
|
|
84
85
|
return result;
|
|
85
86
|
}
|
|
86
87
|
constructor(cacheManager, utilsService, dataSourceProvider, authConfig){
|
|
@@ -43,7 +43,7 @@ const SESSION_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
|
43
43
|
let CompanySelectionSessionService = class CompanySelectionSessionService {
|
|
44
44
|
/**
|
|
45
45
|
* Create a new session for company/branch selection
|
|
46
|
-
*/ async createSession(userId
|
|
46
|
+
*/ async createSession(userId) {
|
|
47
47
|
const sessionId = (0, _crypto.randomUUID)();
|
|
48
48
|
const now = new Date();
|
|
49
49
|
const expiresAt = new Date(now.getTime() + SESSION_TTL_MS);
|
package/cjs/services/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
_export_star(require("./authentication.service"), exports);
|
|
6
|
+
_export_star(require("./auth-email.service"), exports);
|
|
6
7
|
_export_star(require("./company-selection-session.service"), exports);
|
|
7
8
|
_export_star(require("./user.service"), exports);
|
|
8
9
|
_export_star(require("./company.service"), exports);
|
|
@@ -150,10 +150,8 @@ let UserPermissionService = class UserPermissionService {
|
|
|
150
150
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
151
151
|
constructor(dataSourceProvider){
|
|
152
152
|
_define_property(this, "dataSourceProvider", void 0);
|
|
153
|
-
_define_property(this, "logger", void 0);
|
|
154
153
|
_define_property(this, "_repository", void 0);
|
|
155
154
|
this.dataSourceProvider = dataSourceProvider;
|
|
156
|
-
this.logger = new _common.Logger(UserPermissionService.name);
|
|
157
155
|
this._repository = null;
|
|
158
156
|
}
|
|
159
157
|
};
|