@flusys/nestjs-auth 1.1.0-beta → 2.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 +8 -0
- package/cjs/controllers/authentication.controller.js +218 -39
- 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 +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/user-company-permission.entity.js +0 -6
- 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 +63 -147
- package/cjs/services/auth-config.service.js +22 -28
- package/cjs/services/auth-datasource.provider.js +9 -21
- package/cjs/services/auth-email.service.js +89 -85
- package/cjs/services/authentication.service.js +225 -396
- 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 +5 -3
- package/controllers/company-selection.controller.d.ts +6 -2
- 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 +3 -3
- package/entities/user-company-permission.entity.d.ts +0 -2
- package/fesm/config/auth.constants.js +6 -13
- package/fesm/controllers/authentication.controller.js +221 -42
- 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 +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/user-company-permission.entity.js +0 -6
- 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 +64 -148
- package/fesm/services/auth-config.service.js +23 -29
- package/fesm/services/auth-datasource.provider.js +10 -22
- package/fesm/services/auth-email.service.js +90 -86
- package/fesm/services/authentication.service.js +225 -396
- 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 +6 -3
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +6 -8
- package/services/auth-datasource.provider.d.ts +2 -4
- package/services/auth-email.service.d.ts +8 -4
- package/services/authentication.service.d.ts +15 -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,22 +8,20 @@ Object.defineProperty(exports, "AuthenticationService", {
|
|
|
8
8
|
return AuthenticationService;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _classes = require("@flusys/nestjs-shared/classes");
|
|
12
|
+
const _utils = require("@flusys/nestjs-shared/utils");
|
|
11
13
|
const _common = require("@nestjs/common");
|
|
12
14
|
const _jwt = require("@nestjs/jwt");
|
|
13
|
-
const _typeorm = require("@nestjs/typeorm");
|
|
14
15
|
const _bcrypt = /*#__PURE__*/ _interop_require_wildcard(require("bcrypt"));
|
|
15
|
-
const _typeorm1 = require("typeorm");
|
|
16
|
-
const _utils = require("@flusys/nestjs-shared/utils");
|
|
17
|
-
const _authconfigservice = require("./auth-config.service");
|
|
18
|
-
const _authdatasourceprovider = require("./auth-datasource.provider");
|
|
19
|
-
const _enums = require("../enums");
|
|
20
16
|
const _config = require("../config");
|
|
21
|
-
const _classes = require("@flusys/nestjs-shared/classes");
|
|
22
|
-
const _authemailservice = require("./auth-email.service");
|
|
23
17
|
const _companybranchentity = require("../entities/company-branch.entity");
|
|
24
18
|
const _companyentity = require("../entities/company.entity");
|
|
25
19
|
const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
|
|
26
20
|
const _userentity = require("../entities/user.entity");
|
|
21
|
+
const _enums = require("../enums");
|
|
22
|
+
const _authconfigservice = require("./auth-config.service");
|
|
23
|
+
const _authdatasourceprovider = require("./auth-datasource.provider");
|
|
24
|
+
const _authemailservice = require("./auth-email.service");
|
|
27
25
|
const _companyselectionsessionservice = require("./company-selection-session.service");
|
|
28
26
|
function _define_property(obj, key, value) {
|
|
29
27
|
if (key in obj) {
|
|
@@ -94,44 +92,43 @@ function _ts_param(paramIndex, decorator) {
|
|
|
94
92
|
};
|
|
95
93
|
}
|
|
96
94
|
let AuthenticationService = class AuthenticationService {
|
|
95
|
+
// Feature Flags
|
|
96
|
+
/** Check if company feature is enabled (tenant-aware with global fallback) */ isCompanyFeatureEnabled() {
|
|
97
|
+
return this.dataSourceProvider?.isCompanyFeatureEnabled() ?? this.authConfig.isCompanyFeatureEnabled();
|
|
98
|
+
}
|
|
97
99
|
// Repository Getters
|
|
98
100
|
async getUserRepository() {
|
|
99
|
-
if (this.dataSourceProvider) {
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
if (this.injectedUserRepository) {
|
|
103
|
-
return this.injectedUserRepository;
|
|
101
|
+
if (!this.dataSourceProvider) {
|
|
102
|
+
throw new Error('User repository not available');
|
|
104
103
|
}
|
|
105
|
-
|
|
104
|
+
return this.dataSourceProvider.getRepository(_userentity.User);
|
|
106
105
|
}
|
|
107
106
|
async getPermissionRepository() {
|
|
108
|
-
if (!this.
|
|
109
|
-
|
|
110
|
-
return this.dataSourceProvider.getRepository(_usercompanypermissionentity.UserCompanyPermission);
|
|
111
|
-
}
|
|
112
|
-
return this.injectedPermissionRepository ?? null;
|
|
107
|
+
if (!this.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
108
|
+
return this.dataSourceProvider.getRepository(_usercompanypermissionentity.UserCompanyPermission);
|
|
113
109
|
}
|
|
114
110
|
async getCompanyRepository() {
|
|
115
|
-
if (!this.
|
|
116
|
-
|
|
117
|
-
return this.dataSourceProvider.getRepository(_companyentity.Company);
|
|
118
|
-
}
|
|
119
|
-
return this.injectedCompanyRepository ?? null;
|
|
111
|
+
if (!this.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
112
|
+
return this.dataSourceProvider.getRepository(_companyentity.Company);
|
|
120
113
|
}
|
|
121
114
|
async getBranchRepository() {
|
|
122
|
-
if (!this.
|
|
123
|
-
|
|
124
|
-
return this.dataSourceProvider.getRepository(_companybranchentity.CompanyBranch);
|
|
125
|
-
}
|
|
126
|
-
return this.injectedBranchRepository ?? null;
|
|
115
|
+
if (!this.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
|
|
116
|
+
return this.dataSourceProvider.getRepository(_companybranchentity.CompanyBranch);
|
|
127
117
|
}
|
|
128
118
|
// Login
|
|
129
|
-
|
|
119
|
+
async login(email, password) {
|
|
120
|
+
// Check for pending registration first (user registered but hasn't verified email yet)
|
|
121
|
+
if (await this.authEmailService?.hasPendingRegistration(email)) {
|
|
122
|
+
return {
|
|
123
|
+
requiresEmailVerification: true,
|
|
124
|
+
email,
|
|
125
|
+
message: 'Please verify your email address to complete registration.'
|
|
126
|
+
};
|
|
127
|
+
}
|
|
130
128
|
const user = await this.validateUser(email, password);
|
|
131
129
|
if (!user.isActive) {
|
|
132
130
|
throw new _common.UnauthorizedException('User account is deactivated');
|
|
133
131
|
}
|
|
134
|
-
// Check email verification if email service is enabled
|
|
135
132
|
if (this.authEmailService?.isEmailEnabled() && !user.emailVerified) {
|
|
136
133
|
return {
|
|
137
134
|
requiresEmailVerification: true,
|
|
@@ -139,7 +136,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
139
136
|
message: 'Please verify your email address before logging in.'
|
|
140
137
|
};
|
|
141
138
|
}
|
|
142
|
-
if (!this.
|
|
139
|
+
if (!this.isCompanyFeatureEnabled()) {
|
|
143
140
|
return this.generateLoginResponse(user);
|
|
144
141
|
}
|
|
145
142
|
return this.handleCompanyBasedLogin(user);
|
|
@@ -171,7 +168,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
171
168
|
// If user has no company assignments yet, return simple login response
|
|
172
169
|
// This allows users to login and be assigned to companies later
|
|
173
170
|
if (companies.length === 0) {
|
|
174
|
-
return this.generateLoginResponse(user
|
|
171
|
+
return this.generateLoginResponse(user);
|
|
175
172
|
}
|
|
176
173
|
// Get branch permissions
|
|
177
174
|
const branchPermissions = await permissionRepository.find({
|
|
@@ -202,12 +199,17 @@ let AuthenticationService = class AuthenticationService {
|
|
|
202
199
|
email: dto.email
|
|
203
200
|
}
|
|
204
201
|
});
|
|
202
|
+
// When company feature is enabled and user exists, allow joining/creating company
|
|
203
|
+
if (existingUser && this.isCompanyFeatureEnabled()) {
|
|
204
|
+
return this.handleExistingUserCompanyRegistration(existingUser, dto);
|
|
205
|
+
}
|
|
206
|
+
// User exists but company feature is off - email must be unique
|
|
205
207
|
if (existingUser) {
|
|
206
|
-
throw new _common.BadRequestException('Registration failed. Please try again or contact support.');
|
|
208
|
+
throw new _common.BadRequestException('Registration failed due to email exists. Please try again or contact support.');
|
|
207
209
|
}
|
|
208
210
|
// If email verification is enabled, create pending registration instead of user
|
|
209
211
|
if (this.authEmailService?.isEmailEnabled() && verifyUrlBase) {
|
|
210
|
-
const companyData = this.
|
|
212
|
+
const companyData = this.isCompanyFeatureEnabled() ? {
|
|
211
213
|
companySlug: dto.companySlug,
|
|
212
214
|
branchSlug: dto.branchSlug,
|
|
213
215
|
newCompanyName: dto.newCompanyName,
|
|
@@ -230,6 +232,38 @@ let AuthenticationService = class AuthenticationService {
|
|
|
230
232
|
// No email verification - create user directly
|
|
231
233
|
return this.createUserDirectly(dto);
|
|
232
234
|
}
|
|
235
|
+
/** Handle registration for existing user when company feature is enabled */ async handleExistingUserCompanyRegistration(existingUser, dto) {
|
|
236
|
+
if (!dto.companySlug && !dto.newCompanyName) {
|
|
237
|
+
throw new _common.BadRequestException('Email already registered. Please login or provide a company to join/create.');
|
|
238
|
+
}
|
|
239
|
+
const permissionRepository = await this.getPermissionRepository();
|
|
240
|
+
const companyRepository = await this.getCompanyRepository();
|
|
241
|
+
if (!permissionRepository || !companyRepository) {
|
|
242
|
+
throw new _common.BadRequestException('Company feature repositories not available');
|
|
243
|
+
}
|
|
244
|
+
// For existing users joining a company, check if already assigned
|
|
245
|
+
if (dto.companySlug) {
|
|
246
|
+
const company = await companyRepository.findOne({
|
|
247
|
+
where: {
|
|
248
|
+
slug: dto.companySlug,
|
|
249
|
+
isActive: true
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
if (company) {
|
|
253
|
+
const existingPermission = await permissionRepository.findOne({
|
|
254
|
+
where: {
|
|
255
|
+
userId: existingUser.id,
|
|
256
|
+
permissionType: _enums.PermissionType.COMPANY,
|
|
257
|
+
targetId: company.id
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
if (existingPermission) {
|
|
261
|
+
throw new _common.BadRequestException('You are already assigned to this company. Please login.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return this.processCompanyRegistration(existingUser, dto, true);
|
|
266
|
+
}
|
|
233
267
|
/** Create user directly (no email verification) */ async createUserDirectly(dto) {
|
|
234
268
|
const userRepository = await this.getUserRepository();
|
|
235
269
|
const hashedPassword = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
|
|
@@ -243,14 +277,13 @@ let AuthenticationService = class AuthenticationService {
|
|
|
243
277
|
phoneVerified: false
|
|
244
278
|
});
|
|
245
279
|
await userRepository.save(user);
|
|
246
|
-
if (!this.
|
|
247
|
-
return this.generateRegistrationResponse(user
|
|
280
|
+
if (!this.isCompanyFeatureEnabled()) {
|
|
281
|
+
return this.generateRegistrationResponse(user);
|
|
248
282
|
}
|
|
249
|
-
return this.
|
|
283
|
+
return this.processCompanyRegistration(user, dto);
|
|
250
284
|
}
|
|
251
285
|
/** Create user from pending registration (after email verification) */ async createUserFromPendingRegistration(pending) {
|
|
252
286
|
const userRepository = await this.getUserRepository();
|
|
253
|
-
// Check if user already exists (race condition protection)
|
|
254
287
|
const existingUser = await userRepository.findOne({
|
|
255
288
|
where: {
|
|
256
289
|
email: pending.email
|
|
@@ -259,7 +292,6 @@ let AuthenticationService = class AuthenticationService {
|
|
|
259
292
|
if (existingUser) {
|
|
260
293
|
throw new _common.BadRequestException('This email has already been registered.');
|
|
261
294
|
}
|
|
262
|
-
// Create user with verified email
|
|
263
295
|
const user = userRepository.create({
|
|
264
296
|
name: pending.name,
|
|
265
297
|
email: pending.email,
|
|
@@ -270,107 +302,103 @@ let AuthenticationService = class AuthenticationService {
|
|
|
270
302
|
phoneVerified: false
|
|
271
303
|
});
|
|
272
304
|
await userRepository.save(user);
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
return this.handleCompanyRegistrationFromPending(user, pending.companyData);
|
|
305
|
+
if (this.isCompanyFeatureEnabled() && pending.companyData) {
|
|
306
|
+
return this.processCompanyRegistration(user, pending.companyData);
|
|
276
307
|
}
|
|
277
|
-
return this.generateRegistrationResponse(user
|
|
308
|
+
return this.generateRegistrationResponse(user);
|
|
278
309
|
}
|
|
279
|
-
/**
|
|
280
|
-
return this.processCompanyRegistration(user, companyData, false);
|
|
281
|
-
}
|
|
282
|
-
/** Handle company-related registration logic */ async handleCompanyRegistration(user, dto, requiresEmailVerification) {
|
|
283
|
-
return this.processCompanyRegistration(user, dto, requiresEmailVerification);
|
|
284
|
-
}
|
|
285
|
-
/** Shared logic for company registration (join existing or create new) */ async processCompanyRegistration(user, data, requiresEmailVerification) {
|
|
310
|
+
/** Process company registration (join existing or create new) */ async processCompanyRegistration(user, data, throwOnUnavailable = false) {
|
|
286
311
|
const companyRepository = await this.getCompanyRepository();
|
|
287
312
|
const branchRepository = await this.getBranchRepository();
|
|
288
313
|
const permissionRepository = await this.getPermissionRepository();
|
|
289
314
|
if (!companyRepository || !branchRepository || !permissionRepository) {
|
|
290
|
-
|
|
315
|
+
if (throwOnUnavailable) throw new _common.BadRequestException('Company feature repositories not available');
|
|
316
|
+
return this.generateRegistrationResponse(user);
|
|
317
|
+
}
|
|
318
|
+
const { company, branch } = await this.findOrCreateCompanyAndBranch(data, companyRepository, branchRepository);
|
|
319
|
+
if (company) {
|
|
320
|
+
await this.assignUserPermissions(user.id, company.id, branch?.id, permissionRepository);
|
|
321
|
+
return this.generateRegistrationResponseWithCompany(user, company, branch ?? undefined);
|
|
291
322
|
}
|
|
292
|
-
|
|
293
|
-
|
|
323
|
+
return this.generateRegistrationResponse(user);
|
|
324
|
+
}
|
|
325
|
+
/** Find existing company/branch or create new ones */ async findOrCreateCompanyAndBranch(data, companyRepo, branchRepo) {
|
|
294
326
|
if (data.companySlug) {
|
|
295
|
-
company = await
|
|
327
|
+
const company = await companyRepo.findOne({
|
|
296
328
|
where: {
|
|
297
329
|
slug: data.companySlug,
|
|
298
330
|
isActive: true
|
|
299
331
|
}
|
|
300
332
|
});
|
|
301
|
-
if (!company)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
slug: data.branchSlug,
|
|
308
|
-
companyId: company.id,
|
|
309
|
-
isActive: true
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
if (!branch) {
|
|
313
|
-
throw new _common.BadRequestException('Branch not found or inactive');
|
|
333
|
+
if (!company) throw new _common.BadRequestException('Company not found or inactive');
|
|
334
|
+
const branch = data.branchSlug ? await branchRepo.findOne({
|
|
335
|
+
where: {
|
|
336
|
+
slug: data.branchSlug,
|
|
337
|
+
companyId: company.id,
|
|
338
|
+
isActive: true
|
|
314
339
|
}
|
|
315
|
-
}
|
|
316
|
-
branch = await branchRepository.findOne({
|
|
317
|
-
where: {
|
|
318
|
-
companyId: company.id,
|
|
319
|
-
isActive: true
|
|
320
|
-
},
|
|
321
|
-
order: {
|
|
322
|
-
serial: 'ASC',
|
|
323
|
-
createdAt: 'ASC'
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
} else if (data.newCompanyName) {
|
|
328
|
-
const slug = this.generateSlug(data.newCompanyName);
|
|
329
|
-
const existingCompany = await companyRepository.findOne({
|
|
340
|
+
}) : await branchRepo.findOne({
|
|
330
341
|
where: {
|
|
331
|
-
|
|
342
|
+
companyId: company.id,
|
|
343
|
+
isActive: true
|
|
344
|
+
},
|
|
345
|
+
order: {
|
|
346
|
+
serial: 'ASC',
|
|
347
|
+
createdAt: 'ASC'
|
|
332
348
|
}
|
|
333
349
|
});
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
350
|
+
if (data.branchSlug && !branch) throw new _common.BadRequestException('Branch not found or inactive');
|
|
351
|
+
return {
|
|
352
|
+
company,
|
|
353
|
+
branch
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
if (data.newCompanyName) {
|
|
357
|
+
const slug = await (0, _utils.generateUniqueSlug)(data.newCompanyName, async (baseSlug)=>{
|
|
358
|
+
const rows = await companyRepo.createQueryBuilder('c').select('c.slug').where('c.slug = :base OR c.slug LIKE :pattern', {
|
|
359
|
+
base: baseSlug,
|
|
360
|
+
pattern: `${baseSlug}-%`
|
|
361
|
+
}).getMany();
|
|
362
|
+
return rows.map((r)=>r.slug);
|
|
363
|
+
});
|
|
364
|
+
const company = companyRepo.create({
|
|
338
365
|
name: data.newCompanyName,
|
|
339
366
|
slug,
|
|
340
367
|
phone: data.newCompanyPhone,
|
|
341
368
|
address: data.newCompanyAddress,
|
|
342
369
|
isActive: true
|
|
343
370
|
});
|
|
344
|
-
await
|
|
345
|
-
branch =
|
|
371
|
+
await companyRepo.save(company);
|
|
372
|
+
const branch = branchRepo.create({
|
|
346
373
|
name: 'Main Branch',
|
|
347
374
|
slug: 'main-branch',
|
|
348
375
|
companyId: company.id,
|
|
349
376
|
isActive: true
|
|
350
377
|
});
|
|
351
|
-
await
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
permissionType: _enums.PermissionType.COMPANY,
|
|
357
|
-
targetId: company.id
|
|
358
|
-
});
|
|
359
|
-
await permissionRepository.save(companyPermission);
|
|
360
|
-
if (branch) {
|
|
361
|
-
const branchPermission = permissionRepository.create({
|
|
362
|
-
userId: user.id,
|
|
363
|
-
permissionType: _enums.PermissionType.BRANCH,
|
|
364
|
-
targetId: branch.id
|
|
365
|
-
});
|
|
366
|
-
await permissionRepository.save(branchPermission);
|
|
367
|
-
}
|
|
368
|
-
return this.generateRegistrationResponseWithCompany(user, company, branch ?? undefined, requiresEmailVerification);
|
|
378
|
+
await branchRepo.save(branch);
|
|
379
|
+
return {
|
|
380
|
+
company,
|
|
381
|
+
branch
|
|
382
|
+
};
|
|
369
383
|
}
|
|
370
|
-
return
|
|
384
|
+
return {
|
|
385
|
+
company: null,
|
|
386
|
+
branch: null
|
|
387
|
+
};
|
|
371
388
|
}
|
|
372
|
-
/**
|
|
373
|
-
|
|
389
|
+
/** Assign user to company and optionally branch */ async assignUserPermissions(userId, companyId, branchId, permissionRepo) {
|
|
390
|
+
await permissionRepo.save(permissionRepo.create({
|
|
391
|
+
userId,
|
|
392
|
+
permissionType: _enums.PermissionType.COMPANY,
|
|
393
|
+
targetId: companyId
|
|
394
|
+
}));
|
|
395
|
+
if (branchId) {
|
|
396
|
+
await permissionRepo.save(permissionRepo.create({
|
|
397
|
+
userId,
|
|
398
|
+
permissionType: _enums.PermissionType.BRANCH,
|
|
399
|
+
targetId: branchId
|
|
400
|
+
}));
|
|
401
|
+
}
|
|
374
402
|
}
|
|
375
403
|
// Company/Branch Selection
|
|
376
404
|
/** Select company and branch (step 2 of login). Frontend receives all options and user selects both. */ async select(sessionId, companyId, branchId) {
|
|
@@ -382,66 +410,13 @@ let AuthenticationService = class AuthenticationService {
|
|
|
382
410
|
if (!session) {
|
|
383
411
|
throw new _common.UnauthorizedException('Invalid or expired session');
|
|
384
412
|
}
|
|
385
|
-
|
|
386
|
-
const user = await userRepository.findOne({
|
|
387
|
-
where: {
|
|
388
|
-
id: session.userId
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
if (!user) {
|
|
392
|
-
throw new _common.NotFoundException('User not found');
|
|
393
|
-
}
|
|
394
|
-
const permissionRepository = await this.getPermissionRepository();
|
|
395
|
-
const companyRepository = await this.getCompanyRepository();
|
|
396
|
-
const branchRepository = await this.getBranchRepository();
|
|
397
|
-
if (!permissionRepository || !companyRepository || !branchRepository) {
|
|
398
|
-
throw new _common.BadRequestException('Repositories not available');
|
|
399
|
-
}
|
|
400
|
-
// Validate company access
|
|
401
|
-
const companyPermission = await permissionRepository.findOne({
|
|
402
|
-
where: {
|
|
403
|
-
userId: user.id,
|
|
404
|
-
permissionType: _enums.PermissionType.COMPANY,
|
|
405
|
-
targetId: companyId
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
if (!companyPermission) {
|
|
409
|
-
throw new _common.UnauthorizedException('No access to this company');
|
|
410
|
-
}
|
|
411
|
-
const company = await companyRepository.findOne({
|
|
412
|
-
where: {
|
|
413
|
-
id: companyId,
|
|
414
|
-
isActive: true
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
if (!company) {
|
|
418
|
-
throw new _common.UnauthorizedException('Company not found or inactive');
|
|
419
|
-
}
|
|
420
|
-
// Validate branch access
|
|
421
|
-
const branchPermission = await permissionRepository.findOne({
|
|
422
|
-
where: {
|
|
423
|
-
userId: user.id,
|
|
424
|
-
permissionType: _enums.PermissionType.BRANCH,
|
|
425
|
-
targetId: branchId
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
if (!branchPermission) {
|
|
429
|
-
throw new _common.UnauthorizedException('No access to this branch');
|
|
430
|
-
}
|
|
431
|
-
const branch = await branchRepository.findOne({
|
|
432
|
-
where: {
|
|
433
|
-
id: branchId,
|
|
434
|
-
companyId,
|
|
435
|
-
isActive: true
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
if (!branch) {
|
|
439
|
-
throw new _common.UnauthorizedException('Branch not found or inactive');
|
|
440
|
-
}
|
|
441
|
-
return this.generateLoginResponseWithCompany(user, company, branch);
|
|
413
|
+
return this.validateAndLoginWithCompany(session.userId, companyId, branchId);
|
|
442
414
|
}
|
|
443
415
|
/** Switch company/branch after login */ async switchCompany(userId, companyId, branchId) {
|
|
444
416
|
this.ensureCompanyFeatureEnabled();
|
|
417
|
+
return this.validateAndLoginWithCompany(userId, companyId, branchId);
|
|
418
|
+
}
|
|
419
|
+
/** Shared: Validate user access to company/branch and generate login response */ async validateAndLoginWithCompany(userId, companyId, branchId) {
|
|
445
420
|
const userRepository = await this.getUserRepository();
|
|
446
421
|
const user = await userRepository.findOne({
|
|
447
422
|
where: {
|
|
@@ -458,14 +433,14 @@ let AuthenticationService = class AuthenticationService {
|
|
|
458
433
|
throw new _common.BadRequestException('Repositories not available');
|
|
459
434
|
}
|
|
460
435
|
// Validate company access
|
|
461
|
-
const
|
|
436
|
+
const hasCompanyAccess = await permissionRepository.findOne({
|
|
462
437
|
where: {
|
|
463
438
|
userId,
|
|
464
439
|
permissionType: _enums.PermissionType.COMPANY,
|
|
465
440
|
targetId: companyId
|
|
466
441
|
}
|
|
467
442
|
});
|
|
468
|
-
if (!
|
|
443
|
+
if (!hasCompanyAccess) {
|
|
469
444
|
throw new _common.UnauthorizedException('No access to this company');
|
|
470
445
|
}
|
|
471
446
|
const company = await companyRepository.findOne({
|
|
@@ -477,14 +452,15 @@ let AuthenticationService = class AuthenticationService {
|
|
|
477
452
|
if (!company) {
|
|
478
453
|
throw new _common.UnauthorizedException('Company not found or inactive');
|
|
479
454
|
}
|
|
480
|
-
|
|
455
|
+
// Validate branch access
|
|
456
|
+
const hasBranchAccess = await permissionRepository.findOne({
|
|
481
457
|
where: {
|
|
482
458
|
userId,
|
|
483
459
|
permissionType: _enums.PermissionType.BRANCH,
|
|
484
460
|
targetId: branchId
|
|
485
461
|
}
|
|
486
462
|
});
|
|
487
|
-
if (!
|
|
463
|
+
if (!hasBranchAccess) {
|
|
488
464
|
throw new _common.UnauthorizedException('No access to this branch');
|
|
489
465
|
}
|
|
490
466
|
const branch = await branchRepository.findOne({
|
|
@@ -505,6 +481,9 @@ let AuthenticationService = class AuthenticationService {
|
|
|
505
481
|
const payload = this.jwtService.verify(refreshToken, {
|
|
506
482
|
secret: this.authConfig.getRefreshTokenSecret()
|
|
507
483
|
});
|
|
484
|
+
if (await this.isTokenRevoked(payload.id, payload.iat)) {
|
|
485
|
+
throw new _common.UnauthorizedException('Token has been revoked');
|
|
486
|
+
}
|
|
508
487
|
const userRepository = await this.getUserRepository();
|
|
509
488
|
const user = await userRepository.findOne({
|
|
510
489
|
where: {
|
|
@@ -514,7 +493,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
514
493
|
if (!user || !user.isActive) {
|
|
515
494
|
throw new _common.UnauthorizedException('Invalid refresh token');
|
|
516
495
|
}
|
|
517
|
-
|
|
496
|
+
return this.generateTokens({
|
|
518
497
|
id: user.id,
|
|
519
498
|
email: user.email,
|
|
520
499
|
type: 'access',
|
|
@@ -524,44 +503,9 @@ let AuthenticationService = class AuthenticationService {
|
|
|
524
503
|
},
|
|
525
504
|
...payload.branchId && {
|
|
526
505
|
branchId: payload.branchId
|
|
527
|
-
},
|
|
528
|
-
...payload.companyLogoId && {
|
|
529
|
-
companyLogoId: payload.companyLogoId
|
|
530
|
-
},
|
|
531
|
-
...payload.branchLogoId && {
|
|
532
|
-
branchLogoId: payload.branchLogoId
|
|
533
506
|
}
|
|
534
|
-
};
|
|
535
|
-
const refreshPayload = {
|
|
536
|
-
id: user.id,
|
|
537
|
-
email: user.email,
|
|
538
|
-
type: 'refresh',
|
|
539
|
-
profilePictureId: user.profilePictureId ?? undefined,
|
|
540
|
-
...payload.companyId && {
|
|
541
|
-
companyId: payload.companyId
|
|
542
|
-
},
|
|
543
|
-
...payload.branchId && {
|
|
544
|
-
branchId: payload.branchId
|
|
545
|
-
},
|
|
546
|
-
...payload.companyLogoId && {
|
|
547
|
-
companyLogoId: payload.companyLogoId
|
|
548
|
-
},
|
|
549
|
-
...payload.branchLogoId && {
|
|
550
|
-
branchLogoId: payload.branchLogoId
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
return {
|
|
554
|
-
accessToken: this.jwtService.sign(accessPayload, {
|
|
555
|
-
secret: this.authConfig.getJwtSecret(),
|
|
556
|
-
expiresIn: this.authConfig.getJwtExpiration()
|
|
557
|
-
}),
|
|
558
|
-
refreshToken: this.jwtService.sign(refreshPayload, {
|
|
559
|
-
secret: this.authConfig.getRefreshTokenSecret(),
|
|
560
|
-
expiresIn: this.authConfig.getRefreshTokenExpiration()
|
|
561
|
-
})
|
|
562
|
-
};
|
|
507
|
+
});
|
|
563
508
|
} catch (error) {
|
|
564
|
-
// Log error details for debugging (not exposed to client)
|
|
565
509
|
_utils.ErrorHandler.logError(this.logger, error, 'refreshToken');
|
|
566
510
|
throw new _common.UnauthorizedException('Invalid or expired refresh token');
|
|
567
511
|
}
|
|
@@ -573,11 +517,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
573
517
|
id: userId
|
|
574
518
|
}
|
|
575
519
|
});
|
|
576
|
-
if (!user)
|
|
577
|
-
|
|
578
|
-
}
|
|
579
|
-
const isPasswordValid = await _bcrypt.compare(currentPassword, user.password || '');
|
|
580
|
-
if (!isPasswordValid) {
|
|
520
|
+
if (!user) throw new _common.UnauthorizedException('User not found');
|
|
521
|
+
if (!await _bcrypt.compare(currentPassword, user.password || '')) {
|
|
581
522
|
throw new _common.UnauthorizedException('Current password is incorrect');
|
|
582
523
|
}
|
|
583
524
|
user.password = await _bcrypt.hash(newPassword, _config.BCRYPT_SALT_ROUNDS);
|
|
@@ -585,8 +526,9 @@ let AuthenticationService = class AuthenticationService {
|
|
|
585
526
|
}
|
|
586
527
|
/** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
|
|
587
528
|
if (!this.cacheManager) {
|
|
588
|
-
// Cache
|
|
589
|
-
|
|
529
|
+
// Cache is required for secure logout - tokens cannot be revoked without it
|
|
530
|
+
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.');
|
|
531
|
+
throw new _common.BadRequestException('Logout service temporarily unavailable. Please try again later.');
|
|
590
532
|
}
|
|
591
533
|
const revokedAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
|
|
592
534
|
const cacheKey = `${_config.TOKEN_REVOKED_PREFIX}:${userId}`;
|
|
@@ -594,6 +536,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
594
536
|
const refreshTokenExpiry = this.authConfig.getRefreshTokenExpiration();
|
|
595
537
|
const ttlMs = this.parseExpiryToMs(refreshTokenExpiry);
|
|
596
538
|
await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
|
|
539
|
+
this.logger.log(`User ${userId} logged out - all tokens revoked`);
|
|
597
540
|
}
|
|
598
541
|
/** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
|
|
599
542
|
if (!this.cacheManager || !tokenIssuedAt) {
|
|
@@ -711,54 +654,28 @@ let AuthenticationService = class AuthenticationService {
|
|
|
711
654
|
id: userId
|
|
712
655
|
}
|
|
713
656
|
});
|
|
714
|
-
if (!user)
|
|
715
|
-
throw new _common.UnauthorizedException('User not found');
|
|
716
|
-
}
|
|
717
|
-
// Build response (no tokens)
|
|
657
|
+
if (!user) throw new _common.UnauthorizedException('User not found');
|
|
718
658
|
const response = {
|
|
719
|
-
user:
|
|
720
|
-
id: user.id,
|
|
721
|
-
email: user.email,
|
|
722
|
-
name: user.name ?? undefined,
|
|
723
|
-
phone: user.phone ?? undefined,
|
|
724
|
-
profilePictureId: user.profilePictureId ?? undefined
|
|
725
|
-
}
|
|
659
|
+
user: this.toUserInfo(user)
|
|
726
660
|
};
|
|
727
|
-
|
|
728
|
-
if (this.authConfig.isCompanyFeatureEnabled()) {
|
|
729
|
-
// When company feature is enabled, companyId MUST be present
|
|
661
|
+
if (this.isCompanyFeatureEnabled()) {
|
|
730
662
|
if (!companyId) {
|
|
731
|
-
throw new _common.UnauthorizedException('Company feature is enabled but user has no company assigned.
|
|
663
|
+
throw new _common.UnauthorizedException('Company feature is enabled but user has no company assigned.');
|
|
732
664
|
}
|
|
733
665
|
const company = await this.getCompanyById(companyId);
|
|
734
|
-
if (!company)
|
|
735
|
-
|
|
736
|
-
}
|
|
737
|
-
response.company = {
|
|
738
|
-
id: company.id,
|
|
739
|
-
name: company.name,
|
|
740
|
-
slug: company.slug,
|
|
741
|
-
logoId: company.logoId ?? null
|
|
742
|
-
};
|
|
743
|
-
// Branch is optional in some configurations, but if provided it must exist
|
|
666
|
+
if (!company) throw new _common.UnauthorizedException('Company not found.');
|
|
667
|
+
response.company = this.toCompanyInfo(company);
|
|
744
668
|
if (branchId) {
|
|
745
669
|
const branch = await this.getBranchById(branchId);
|
|
746
|
-
if (!branch)
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
response.branch = {
|
|
750
|
-
id: branch.id,
|
|
751
|
-
name: branch.name,
|
|
752
|
-
slug: branch.slug,
|
|
753
|
-
logoId: branch.logoId ?? null
|
|
754
|
-
};
|
|
670
|
+
if (!branch) throw new _common.UnauthorizedException('Branch not found.');
|
|
671
|
+
response.branch = this.toBranchInfo(branch);
|
|
755
672
|
}
|
|
756
673
|
}
|
|
757
674
|
return response;
|
|
758
675
|
}
|
|
759
676
|
// Helper Methods
|
|
760
677
|
ensureCompanyFeatureEnabled() {
|
|
761
|
-
if (!this.
|
|
678
|
+
if (!this.isCompanyFeatureEnabled()) {
|
|
762
679
|
throw new _common.BadRequestException('Company feature is not enabled');
|
|
763
680
|
}
|
|
764
681
|
}
|
|
@@ -769,11 +686,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
769
686
|
email
|
|
770
687
|
}
|
|
771
688
|
});
|
|
772
|
-
if (!user) {
|
|
773
|
-
throw new _common.UnauthorizedException('Invalid credentials');
|
|
774
|
-
}
|
|
775
|
-
const isPasswordValid = await _bcrypt.compare(password, user.password || '');
|
|
776
|
-
if (!isPasswordValid) {
|
|
689
|
+
if (!user || !await _bcrypt.compare(password, user.password || '')) {
|
|
777
690
|
throw new _common.UnauthorizedException('Invalid credentials');
|
|
778
691
|
}
|
|
779
692
|
user.lastLoginAt = new Date();
|
|
@@ -781,84 +694,77 @@ let AuthenticationService = class AuthenticationService {
|
|
|
781
694
|
return user;
|
|
782
695
|
}
|
|
783
696
|
// Response Generators
|
|
784
|
-
|
|
785
|
-
|
|
697
|
+
/** Create user info object */ toUserInfo(user) {
|
|
698
|
+
return {
|
|
786
699
|
id: user.id,
|
|
787
700
|
email: user.email,
|
|
788
|
-
|
|
701
|
+
name: user.name ?? undefined,
|
|
702
|
+
phone: user.phone ?? null,
|
|
703
|
+
profilePictureId: user.profilePictureId ?? null
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
/** Create company info object */ toCompanyInfo(company) {
|
|
707
|
+
return {
|
|
708
|
+
id: company.id,
|
|
709
|
+
name: company.name,
|
|
710
|
+
slug: company.slug,
|
|
711
|
+
logoId: company.logoId ?? null
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
/** Create branch info object */ toBranchInfo(branch) {
|
|
715
|
+
return {
|
|
716
|
+
id: branch.id,
|
|
717
|
+
name: branch.name,
|
|
718
|
+
slug: branch.slug,
|
|
719
|
+
logoId: branch.logoId ?? null
|
|
789
720
|
};
|
|
790
|
-
|
|
721
|
+
}
|
|
722
|
+
/** Generate JWT tokens */ generateTokens(payload) {
|
|
723
|
+
const accessToken = this.jwtService.sign({
|
|
724
|
+
...payload,
|
|
725
|
+
type: 'access'
|
|
726
|
+
}, {
|
|
791
727
|
secret: this.authConfig.getJwtSecret(),
|
|
792
728
|
expiresIn: this.authConfig.getJwtExpiration()
|
|
793
729
|
});
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
email: user.email,
|
|
730
|
+
const refreshToken = this.jwtService.sign({
|
|
731
|
+
...payload,
|
|
797
732
|
type: 'refresh'
|
|
798
|
-
}
|
|
799
|
-
const refreshToken = this.jwtService.sign(refreshPayload, {
|
|
733
|
+
}, {
|
|
800
734
|
secret: this.authConfig.getRefreshTokenSecret(),
|
|
801
735
|
expiresIn: this.authConfig.getRefreshTokenExpiration()
|
|
802
736
|
});
|
|
803
737
|
return {
|
|
804
738
|
accessToken,
|
|
805
|
-
refreshToken
|
|
806
|
-
user: {
|
|
807
|
-
id: user.id,
|
|
808
|
-
email: user.email,
|
|
809
|
-
name: user.name ?? undefined,
|
|
810
|
-
phone: user.phone ?? null,
|
|
811
|
-
profilePictureId: user.profilePictureId ?? null
|
|
812
|
-
},
|
|
813
|
-
companyFeatureEnabled
|
|
739
|
+
refreshToken
|
|
814
740
|
};
|
|
815
741
|
}
|
|
816
|
-
|
|
817
|
-
const
|
|
742
|
+
generateLoginResponse(user) {
|
|
743
|
+
const { accessToken, refreshToken } = this.generateTokens({
|
|
818
744
|
id: user.id,
|
|
819
745
|
email: user.email,
|
|
820
|
-
type: 'access'
|
|
821
|
-
companyId: company.id,
|
|
822
|
-
branchId: branch?.id
|
|
823
|
-
};
|
|
824
|
-
const accessToken = this.jwtService.sign(payload, {
|
|
825
|
-
secret: this.authConfig.getJwtSecret(),
|
|
826
|
-
expiresIn: this.authConfig.getJwtExpiration()
|
|
746
|
+
type: 'access'
|
|
827
747
|
});
|
|
828
|
-
|
|
748
|
+
return {
|
|
749
|
+
accessToken,
|
|
750
|
+
refreshToken,
|
|
751
|
+
user: this.toUserInfo(user)
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
generateLoginResponseWithCompany(user, company, branch) {
|
|
755
|
+
const { accessToken, refreshToken } = this.generateTokens({
|
|
829
756
|
id: user.id,
|
|
830
757
|
email: user.email,
|
|
831
|
-
type: '
|
|
758
|
+
type: 'access',
|
|
832
759
|
companyId: company.id,
|
|
833
760
|
branchId: branch?.id
|
|
834
|
-
};
|
|
835
|
-
const refreshToken = this.jwtService.sign(refreshPayload, {
|
|
836
|
-
secret: this.authConfig.getRefreshTokenSecret(),
|
|
837
|
-
expiresIn: this.authConfig.getRefreshTokenExpiration()
|
|
838
761
|
});
|
|
839
762
|
return {
|
|
840
763
|
accessToken,
|
|
841
764
|
refreshToken,
|
|
842
|
-
user:
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
name: user.name ?? undefined,
|
|
846
|
-
phone: user.phone ?? null,
|
|
847
|
-
profilePictureId: user.profilePictureId ?? null
|
|
848
|
-
},
|
|
849
|
-
company: {
|
|
850
|
-
id: company.id,
|
|
851
|
-
name: company.name,
|
|
852
|
-
slug: company.slug,
|
|
853
|
-
logoId: company.logoId ?? null
|
|
854
|
-
},
|
|
855
|
-
branch: branch ? {
|
|
856
|
-
id: branch.id,
|
|
857
|
-
name: branch.name,
|
|
858
|
-
slug: branch.slug,
|
|
859
|
-
logoId: branch.logoId ?? null
|
|
860
|
-
} : undefined,
|
|
861
|
-
companyFeatureEnabled: true
|
|
765
|
+
user: this.toUserInfo(user),
|
|
766
|
+
company: this.toCompanyInfo(company),
|
|
767
|
+
branch: branch ? this.toBranchInfo(branch) : undefined
|
|
862
768
|
};
|
|
863
769
|
}
|
|
864
770
|
async generateCompanySelectionResponse(user, companies, branches) {
|
|
@@ -866,103 +772,42 @@ let AuthenticationService = class AuthenticationService {
|
|
|
866
772
|
throw new _common.BadRequestException('Session service not available');
|
|
867
773
|
}
|
|
868
774
|
const sessionId = await this.sessionService.createSession(user.id);
|
|
869
|
-
// Build companies with their branches
|
|
870
775
|
const companiesWithBranches = companies.map((company)=>({
|
|
871
|
-
|
|
872
|
-
name: company.name,
|
|
873
|
-
slug: company.slug,
|
|
776
|
+
...this.toCompanyInfo(company),
|
|
874
777
|
isActive: company.isActive,
|
|
875
|
-
logoId: company.logoId ?? null,
|
|
876
778
|
branches: branches.filter((b)=>b.companyId === company.id).map((b)=>({
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
slug: b.slug,
|
|
880
|
-
isActive: b.isActive,
|
|
881
|
-
logoId: b.logoId ?? null
|
|
779
|
+
...this.toBranchInfo(b),
|
|
780
|
+
isActive: b.isActive
|
|
882
781
|
}))
|
|
883
782
|
}));
|
|
884
783
|
return {
|
|
885
784
|
requiresSelection: true,
|
|
886
785
|
sessionId,
|
|
887
786
|
expiresAt: new Date(Date.now() + 5 * 60 * 1000),
|
|
888
|
-
user:
|
|
889
|
-
id: user.id,
|
|
890
|
-
email: user.email,
|
|
891
|
-
name: user.name ?? undefined,
|
|
892
|
-
phone: user.phone ?? null,
|
|
893
|
-
profilePictureId: user.profilePictureId ?? null
|
|
894
|
-
},
|
|
787
|
+
user: this.toUserInfo(user),
|
|
895
788
|
companies: companiesWithBranches
|
|
896
789
|
};
|
|
897
790
|
}
|
|
898
|
-
|
|
899
|
-
const userInfo = {
|
|
900
|
-
id: user.id,
|
|
901
|
-
email: user.email,
|
|
902
|
-
name: user.name ?? undefined,
|
|
903
|
-
phone: user.phone ?? null,
|
|
904
|
-
profilePictureId: user.profilePictureId ?? null
|
|
905
|
-
};
|
|
906
|
-
if (requiresEmailVerification) {
|
|
907
|
-
return {
|
|
908
|
-
user: userInfo,
|
|
909
|
-
companyFeatureEnabled,
|
|
910
|
-
requiresEmailVerification: true
|
|
911
|
-
};
|
|
912
|
-
}
|
|
913
|
-
const loginResponse = this.generateLoginResponse(user, companyFeatureEnabled);
|
|
791
|
+
generateRegistrationResponse(user) {
|
|
914
792
|
return {
|
|
915
|
-
...
|
|
793
|
+
...this.generateLoginResponse(user),
|
|
916
794
|
requiresEmailVerification: false
|
|
917
795
|
};
|
|
918
796
|
}
|
|
919
|
-
|
|
920
|
-
const userInfo = {
|
|
921
|
-
id: user.id,
|
|
922
|
-
email: user.email,
|
|
923
|
-
name: user.name ?? undefined,
|
|
924
|
-
phone: user.phone ?? null,
|
|
925
|
-
profilePictureId: user.profilePictureId ?? null
|
|
926
|
-
};
|
|
927
|
-
const companyInfo = {
|
|
928
|
-
id: company.id,
|
|
929
|
-
name: company.name,
|
|
930
|
-
slug: company.slug,
|
|
931
|
-
logoId: company.logoId ?? null
|
|
932
|
-
};
|
|
933
|
-
const branchInfo = branch ? {
|
|
934
|
-
id: branch.id,
|
|
935
|
-
name: branch.name,
|
|
936
|
-
slug: branch.slug,
|
|
937
|
-
logoId: branch.logoId ?? null
|
|
938
|
-
} : undefined;
|
|
939
|
-
if (requiresEmailVerification) {
|
|
940
|
-
return {
|
|
941
|
-
user: userInfo,
|
|
942
|
-
company: companyInfo,
|
|
943
|
-
branch: branchInfo,
|
|
944
|
-
companyFeatureEnabled: true,
|
|
945
|
-
requiresEmailVerification: true
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
const loginResponse = this.generateLoginResponseWithCompany(user, company, branch);
|
|
797
|
+
generateRegistrationResponseWithCompany(user, company, branch) {
|
|
949
798
|
return {
|
|
950
|
-
...
|
|
799
|
+
...this.generateLoginResponseWithCompany(user, company, branch),
|
|
951
800
|
requiresEmailVerification: false
|
|
952
801
|
};
|
|
953
802
|
}
|
|
954
803
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
955
|
-
constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService
|
|
804
|
+
constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService){
|
|
956
805
|
_define_property(this, "jwtService", void 0);
|
|
957
806
|
_define_property(this, "authConfig", void 0);
|
|
958
807
|
_define_property(this, "cacheManager", void 0);
|
|
959
808
|
_define_property(this, "dataSourceProvider", void 0);
|
|
960
809
|
_define_property(this, "sessionService", void 0);
|
|
961
810
|
_define_property(this, "authEmailService", void 0);
|
|
962
|
-
_define_property(this, "injectedUserRepository", void 0);
|
|
963
|
-
_define_property(this, "injectedPermissionRepository", void 0);
|
|
964
|
-
_define_property(this, "injectedCompanyRepository", void 0);
|
|
965
|
-
_define_property(this, "injectedBranchRepository", void 0);
|
|
966
811
|
_define_property(this, "logger", void 0);
|
|
967
812
|
this.jwtService = jwtService;
|
|
968
813
|
this.authConfig = authConfig;
|
|
@@ -970,10 +815,6 @@ let AuthenticationService = class AuthenticationService {
|
|
|
970
815
|
this.dataSourceProvider = dataSourceProvider;
|
|
971
816
|
this.sessionService = sessionService;
|
|
972
817
|
this.authEmailService = authEmailService;
|
|
973
|
-
this.injectedUserRepository = injectedUserRepository;
|
|
974
|
-
this.injectedPermissionRepository = injectedPermissionRepository;
|
|
975
|
-
this.injectedCompanyRepository = injectedCompanyRepository;
|
|
976
|
-
this.injectedBranchRepository = injectedBranchRepository;
|
|
977
818
|
this.logger = new _common.Logger(AuthenticationService.name);
|
|
978
819
|
}
|
|
979
820
|
};
|
|
@@ -991,14 +832,6 @@ AuthenticationService = _ts_decorate([
|
|
|
991
832
|
_ts_param(4, (0, _common.Inject)(_companyselectionsessionservice.CompanySelectionSessionService)),
|
|
992
833
|
_ts_param(5, (0, _common.Optional)()),
|
|
993
834
|
_ts_param(5, (0, _common.Inject)(_authemailservice.AuthEmailService)),
|
|
994
|
-
_ts_param(6, (0, _common.Optional)()),
|
|
995
|
-
_ts_param(6, (0, _typeorm.InjectRepository)(_userentity.User)),
|
|
996
|
-
_ts_param(7, (0, _common.Optional)()),
|
|
997
|
-
_ts_param(7, (0, _typeorm.InjectRepository)(_usercompanypermissionentity.UserCompanyPermission)),
|
|
998
|
-
_ts_param(8, (0, _common.Optional)()),
|
|
999
|
-
_ts_param(8, (0, _typeorm.InjectRepository)(_companyentity.Company)),
|
|
1000
|
-
_ts_param(9, (0, _common.Optional)()),
|
|
1001
|
-
_ts_param(9, (0, _typeorm.InjectRepository)(_companybranchentity.CompanyBranch)),
|
|
1002
835
|
_ts_metadata("design:type", Function),
|
|
1003
836
|
_ts_metadata("design:paramtypes", [
|
|
1004
837
|
typeof _jwt.JwtService === "undefined" ? Object : _jwt.JwtService,
|
|
@@ -1006,10 +839,6 @@ AuthenticationService = _ts_decorate([
|
|
|
1006
839
|
typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
|
|
1007
840
|
typeof _authdatasourceprovider.AuthDataSourceProvider === "undefined" ? Object : _authdatasourceprovider.AuthDataSourceProvider,
|
|
1008
841
|
typeof _companyselectionsessionservice.CompanySelectionSessionService === "undefined" ? Object : _companyselectionsessionservice.CompanySelectionSessionService,
|
|
1009
|
-
typeof _authemailservice.AuthEmailService === "undefined" ? Object : _authemailservice.AuthEmailService
|
|
1010
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
1011
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
1012
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
1013
|
-
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository
|
|
842
|
+
typeof _authemailservice.AuthEmailService === "undefined" ? Object : _authemailservice.AuthEmailService
|
|
1014
843
|
])
|
|
1015
844
|
], AuthenticationService);
|