@flusys/nestjs-auth 3.0.0-rc → 3.0.1
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 +610 -95
- package/cjs/controllers/authentication.controller.js +2 -173
- package/cjs/controllers/email-verification.controller.js +220 -0
- package/cjs/controllers/index.js +1 -0
- package/cjs/dtos/authentication.dto.js +12 -2
- package/cjs/entities/index.js +16 -17
- package/cjs/entities/pending-registration.entity.js +9 -0
- package/cjs/modules/auth.module.js +33 -24
- package/cjs/services/auth-config.service.js +11 -7
- package/cjs/services/auth-datasource.provider.js +15 -27
- package/cjs/services/auth-email.service.js +8 -33
- package/cjs/services/authentication.service.js +155 -110
- package/cjs/services/user.service.js +28 -83
- package/controllers/authentication.controller.d.ts +2 -10
- package/controllers/email-verification.controller.d.ts +20 -0
- package/controllers/index.d.ts +1 -0
- package/dtos/authentication.dto.d.ts +1 -0
- package/entities/index.d.ts +5 -10
- package/entities/pending-registration.entity.d.ts +1 -0
- package/fesm/controllers/authentication.controller.js +3 -174
- package/fesm/controllers/email-verification.controller.js +210 -0
- package/fesm/controllers/index.js +1 -0
- package/fesm/dtos/authentication.dto.js +32 -25
- package/fesm/entities/index.js +17 -9
- package/fesm/entities/pending-registration.entity.js +9 -0
- package/fesm/interfaces/user-enricher.interface.js +2 -24
- package/fesm/modules/auth.module.js +35 -26
- package/fesm/services/auth-config.service.js +11 -7
- package/fesm/services/auth-datasource.provider.js +15 -27
- package/fesm/services/auth-email.service.js +8 -33
- package/fesm/services/authentication.service.js +145 -100
- package/fesm/services/user.service.js +28 -83
- package/interfaces/user-enricher.interface.d.ts +3 -2
- package/modules/auth.module.d.ts +3 -1
- package/package.json +3 -3
- package/services/auth-config.service.d.ts +1 -0
- package/services/auth-datasource.provider.d.ts +1 -0
- package/services/auth-email.service.d.ts +1 -0
- package/services/authentication.service.d.ts +7 -1
- package/services/user.service.d.ts +5 -0
|
@@ -46,23 +46,17 @@ export class UserService extends RequestScopedApiService {
|
|
|
46
46
|
}
|
|
47
47
|
async ensureRepositoryInitialized() {
|
|
48
48
|
await super.ensureRepositoryInitialized();
|
|
49
|
-
// Initialize permission repository if company feature is enabled
|
|
50
49
|
const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
|
|
51
50
|
if (isCompanyFeatureEnabled && !this.permissionRepository) {
|
|
52
51
|
[this.permissionRepository] = await this.initializeAdditionalRepositories([
|
|
53
52
|
UserCompanyPermission
|
|
54
53
|
]);
|
|
55
54
|
}
|
|
56
|
-
// Initialize DataSource for transaction support
|
|
57
55
|
if (!this.dataSource) {
|
|
58
56
|
this.dataSource = await this.getDataSourceForService();
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Validate profile ownership, ensure repository initialized, and fetch user.
|
|
64
|
-
* Throws ForbiddenException if not owner, NotFoundException if user not found.
|
|
65
|
-
*/ async getUserForProfile(userId, user) {
|
|
59
|
+
async getUserForProfile(userId, user) {
|
|
66
60
|
if (userId !== user.id) {
|
|
67
61
|
throw new ForbiddenException('Cannot access another user\'s profile');
|
|
68
62
|
}
|
|
@@ -77,38 +71,32 @@ export class UserService extends RequestScopedApiService {
|
|
|
77
71
|
}
|
|
78
72
|
return userEntity;
|
|
79
73
|
}
|
|
80
|
-
|
|
81
|
-
// Ensure repository is initialized for custom method
|
|
74
|
+
async verifyEmail(id) {
|
|
82
75
|
await this.ensureRepositoryInitialized();
|
|
83
76
|
await this.repository.update(id, {
|
|
84
77
|
emailVerified: true
|
|
85
78
|
});
|
|
86
|
-
// Clear cache for this user
|
|
87
79
|
await this.clearCacheForId([
|
|
88
80
|
{
|
|
89
81
|
id
|
|
90
82
|
}
|
|
91
83
|
]);
|
|
92
84
|
}
|
|
93
|
-
|
|
94
|
-
// Ensure repository is initialized for custom method
|
|
85
|
+
async verifyPhone(id) {
|
|
95
86
|
await this.ensureRepositoryInitialized();
|
|
96
87
|
await this.repository.update(id, {
|
|
97
88
|
phoneVerified: true
|
|
98
89
|
});
|
|
99
|
-
// Clear cache for this user
|
|
100
90
|
await this.clearCacheForId([
|
|
101
91
|
{
|
|
102
92
|
id
|
|
103
93
|
}
|
|
104
94
|
]);
|
|
105
95
|
}
|
|
106
|
-
|
|
107
|
-
// Ensure repository is initialized for custom method
|
|
96
|
+
async updateStatus(id, isActive, user) {
|
|
108
97
|
await this.ensureRepositoryInitialized();
|
|
109
98
|
const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
|
|
110
99
|
if (isCompanyFeatureEnabled && user?.companyId && this.permissionRepository) {
|
|
111
|
-
// Company feature enabled - update permission isActive
|
|
112
100
|
const permission = await this.permissionRepository.findOne({
|
|
113
101
|
where: {
|
|
114
102
|
userId: id,
|
|
@@ -122,36 +110,30 @@ export class UserService extends RequestScopedApiService {
|
|
|
122
110
|
permission.isActive = isActive;
|
|
123
111
|
await this.permissionRepository.save(permission);
|
|
124
112
|
} else {
|
|
125
|
-
// Company feature disabled - update User.isActive directly
|
|
126
113
|
await this.repository.update(id, {
|
|
127
114
|
isActive
|
|
128
115
|
});
|
|
129
116
|
}
|
|
130
|
-
// Clear cache for this user
|
|
131
117
|
await this.clearCacheForId([
|
|
132
118
|
{
|
|
133
119
|
id
|
|
134
120
|
}
|
|
135
121
|
]);
|
|
136
122
|
}
|
|
137
|
-
|
|
138
|
-
/** Convert DTO to entity (hash password before saving) */ async convertSingleDtoToEntity(dto, user) {
|
|
139
|
-
// Repository initialization is handled automatically by RequestScopedApiService
|
|
123
|
+
async convertSingleDtoToEntity(dto, user) {
|
|
140
124
|
const entity = await super.convertSingleDtoToEntity(dto, user);
|
|
141
|
-
// Hash password if provided (CreateUserDto has password field)
|
|
142
125
|
if ('password' in dto && dto.password) {
|
|
143
126
|
entity.password = await bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
|
|
144
127
|
}
|
|
145
128
|
return entity;
|
|
146
129
|
}
|
|
147
|
-
|
|
130
|
+
convertEntityToResponseDto(entity, isRaw) {
|
|
148
131
|
if (isRaw) {
|
|
149
132
|
return this.convertRawToResponseDto(entity);
|
|
150
133
|
}
|
|
151
134
|
return this.convertEntityToDto(entity);
|
|
152
135
|
}
|
|
153
|
-
|
|
154
|
-
// When raw mode is used with company feature, isActive comes from computed field
|
|
136
|
+
convertRawToResponseDto(raw) {
|
|
155
137
|
const isActive = raw.user_companyIsActive !== undefined ? Boolean(raw.user_companyIsActive) : raw.user_is_active;
|
|
156
138
|
return {
|
|
157
139
|
id: raw.user_id,
|
|
@@ -172,7 +154,7 @@ export class UserService extends RequestScopedApiService {
|
|
|
172
154
|
deletedById: raw.user_deleted_by_id
|
|
173
155
|
};
|
|
174
156
|
}
|
|
175
|
-
|
|
157
|
+
convertEntityToDto(entity) {
|
|
176
158
|
return {
|
|
177
159
|
id: entity.id,
|
|
178
160
|
name: entity.name,
|
|
@@ -192,10 +174,10 @@ export class UserService extends RequestScopedApiService {
|
|
|
192
174
|
deletedById: entity.deletedById
|
|
193
175
|
};
|
|
194
176
|
}
|
|
195
|
-
|
|
177
|
+
convertEntityListToResponseListDto(entities, isRaw) {
|
|
196
178
|
return entities.map((entity)=>this.convertEntityToResponseDto(entity, isRaw));
|
|
197
179
|
}
|
|
198
|
-
|
|
180
|
+
async getGlobalSearchQuery(query, search, _user) {
|
|
199
181
|
query.andWhere('(user.name LIKE :search OR user.email LIKE :search OR user.phone LIKE :search)', {
|
|
200
182
|
search: `%${search}%`
|
|
201
183
|
});
|
|
@@ -204,26 +186,16 @@ export class UserService extends RequestScopedApiService {
|
|
|
204
186
|
isRaw: false
|
|
205
187
|
};
|
|
206
188
|
}
|
|
207
|
-
|
|
208
|
-
// Repository initialization is handled automatically by RequestScopedApiService
|
|
189
|
+
async getExtraManipulateQuery(query, filterAndPaginationDto, user) {
|
|
209
190
|
let result = await super.getExtraManipulateQuery(query, filterAndPaginationDto, user);
|
|
210
|
-
// Apply user enricher query modifications if available
|
|
211
191
|
if (this.userEnricher?.enrichListQuery) {
|
|
212
192
|
await this.userEnricher.enrichListQuery(query, user);
|
|
213
193
|
}
|
|
214
|
-
// Only apply company filtering if:
|
|
215
|
-
// 1. Company feature is enabled at bootstrap
|
|
216
|
-
// 2. User has company context
|
|
217
|
-
// 3. Permission repository is available
|
|
218
194
|
const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
|
|
219
195
|
if (!isCompanyFeatureEnabled) {
|
|
220
|
-
// Company feature disabled - return without any company-related modifications
|
|
221
|
-
// isActive will come from User entity directly
|
|
222
196
|
return result;
|
|
223
197
|
}
|
|
224
|
-
// Company feature is enabled - apply company-based filtering
|
|
225
198
|
if (user?.companyId && this.permissionRepository) {
|
|
226
|
-
// Add computed isActive field from permission table
|
|
227
199
|
query.addSelect(`(SELECT perm.is_active FROM user_company_permissions perm
|
|
228
200
|
WHERE perm.user_id = user.id
|
|
229
201
|
AND perm.permission_type = :permissionType
|
|
@@ -231,7 +203,6 @@ export class UserService extends RequestScopedApiService {
|
|
|
231
203
|
LIMIT 1)`, 'user_companyIsActive');
|
|
232
204
|
query.setParameter('permissionType', PermissionType.COMPANY);
|
|
233
205
|
query.setParameter('companyId', user.companyId);
|
|
234
|
-
// Add filter for isActive if provided (filters by permission isActive)
|
|
235
206
|
if (filterAndPaginationDto.filter?.isActive !== undefined) {
|
|
236
207
|
query.andWhere(`EXISTS (
|
|
237
208
|
SELECT 1 FROM user_company_permissions perm
|
|
@@ -245,7 +216,6 @@ export class UserService extends RequestScopedApiService {
|
|
|
245
216
|
isActiveValue: filterAndPaginationDto.filter.isActive
|
|
246
217
|
});
|
|
247
218
|
}
|
|
248
|
-
// Filter users to only show those with company permission
|
|
249
219
|
query.andWhere(`EXISTS (
|
|
250
220
|
SELECT 1 FROM user_company_permissions perm
|
|
251
221
|
WHERE perm.user_id = user.id
|
|
@@ -255,7 +225,6 @@ export class UserService extends RequestScopedApiService {
|
|
|
255
225
|
permissionType: PermissionType.COMPANY,
|
|
256
226
|
companyId: user.companyId
|
|
257
227
|
});
|
|
258
|
-
// Return with isRaw: true to get the computed field
|
|
259
228
|
return {
|
|
260
229
|
query,
|
|
261
230
|
isRaw: true
|
|
@@ -263,11 +232,8 @@ export class UserService extends RequestScopedApiService {
|
|
|
263
232
|
}
|
|
264
233
|
return result;
|
|
265
234
|
}
|
|
266
|
-
|
|
267
|
-
// Repository initialization is handled automatically by RequestScopedApiService
|
|
268
|
-
// Check if company feature is enabled
|
|
235
|
+
async insert(dto, user) {
|
|
269
236
|
const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
|
|
270
|
-
// If company feature is disabled OR missing dependencies, use parent implementation
|
|
271
237
|
if (!isCompanyFeatureEnabled || !this.dataSource || !user?.companyId || !this.permissionRepository) {
|
|
272
238
|
return super.insert(dto, user);
|
|
273
239
|
}
|
|
@@ -275,11 +241,8 @@ export class UserService extends RequestScopedApiService {
|
|
|
275
241
|
await queryRunner.connect();
|
|
276
242
|
await queryRunner.startTransaction();
|
|
277
243
|
try {
|
|
278
|
-
// First, insert the user using parent method logic
|
|
279
244
|
const userEntity = await this.convertSingleDtoToEntity(dto, user);
|
|
280
245
|
const savedUser = await queryRunner.manager.save(this.repository.target, userEntity);
|
|
281
|
-
// Create company permission (repository is guaranteed to exist due to check above)
|
|
282
|
-
// Check if permission already exists
|
|
283
246
|
const existingPermission = await queryRunner.manager.findOne(this.permissionRepository.target, {
|
|
284
247
|
where: {
|
|
285
248
|
userId: savedUser.id,
|
|
@@ -296,7 +259,6 @@ export class UserService extends RequestScopedApiService {
|
|
|
296
259
|
});
|
|
297
260
|
await queryRunner.manager.save(this.permissionRepository.target, permission);
|
|
298
261
|
}
|
|
299
|
-
// Also create branch permission if user has branch context
|
|
300
262
|
if (user.branchId) {
|
|
301
263
|
const existingBranchPermission = await queryRunner.manager.findOne(this.permissionRepository.target, {
|
|
302
264
|
where: {
|
|
@@ -330,13 +292,9 @@ export class UserService extends RequestScopedApiService {
|
|
|
330
292
|
await queryRunner.release();
|
|
331
293
|
}
|
|
332
294
|
}
|
|
333
|
-
|
|
334
|
-
* Get user profile with extras from enricher
|
|
335
|
-
* Returns base user data plus any extra data provided by enricher (roles, permissions, etc.)
|
|
336
|
-
*/ async getProfileWithExtras(userId, user) {
|
|
295
|
+
async getProfileWithExtras(userId, user) {
|
|
337
296
|
const userEntity = await this.getUserForProfile(userId, user);
|
|
338
297
|
const userData = this.convertEntityToResponseDto(userEntity, false);
|
|
339
|
-
// Get extras from enricher if available
|
|
340
298
|
let extras;
|
|
341
299
|
if (this.userEnricher?.getProfileExtras) {
|
|
342
300
|
extras = await this.userEnricher.getProfileExtras(userId, user);
|
|
@@ -346,38 +304,34 @@ export class UserService extends RequestScopedApiService {
|
|
|
346
304
|
extras
|
|
347
305
|
};
|
|
348
306
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
307
|
+
async getAll(search, filterAndPaginationDto, user) {
|
|
308
|
+
const result = await super.getAll(search, filterAndPaginationDto, user);
|
|
309
|
+
const enrichedData = await this.getEnrichedList(result.data, user);
|
|
310
|
+
return {
|
|
311
|
+
data: enrichedData,
|
|
312
|
+
total: result.total
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
async getEnrichedList(users, user) {
|
|
353
316
|
if (this.userEnricher?.enrichListItems) {
|
|
354
317
|
return this.userEnricher.enrichListItems(users, user);
|
|
355
318
|
}
|
|
356
319
|
return users;
|
|
357
320
|
}
|
|
358
|
-
|
|
359
|
-
// Multi-Step Profile Methods (via Enricher)
|
|
360
|
-
// ============================================
|
|
361
|
-
/**
|
|
362
|
-
* Get profile section definitions from enricher
|
|
363
|
-
*/ async getProfileSections() {
|
|
321
|
+
async getProfileSections() {
|
|
364
322
|
if (this.userEnricher?.getProfileSections) {
|
|
365
323
|
return this.userEnricher.getProfileSections();
|
|
366
324
|
}
|
|
367
325
|
return [];
|
|
368
326
|
}
|
|
369
|
-
|
|
370
|
-
* Get specific profile section data
|
|
371
|
-
*/ async getProfileSectionData(userId, sectionId, user) {
|
|
327
|
+
async getProfileSectionData(userId, sectionId, user) {
|
|
372
328
|
await this.getUserForProfile(userId, user);
|
|
373
329
|
if (this.userEnricher?.getProfileSectionData) {
|
|
374
330
|
return this.userEnricher.getProfileSectionData(userId, sectionId, user);
|
|
375
331
|
}
|
|
376
332
|
return null;
|
|
377
333
|
}
|
|
378
|
-
|
|
379
|
-
* Update specific profile section
|
|
380
|
-
*/ async updateProfileSection(userId, sectionId, data, user) {
|
|
334
|
+
async updateProfileSection(userId, sectionId, data, user) {
|
|
381
335
|
const userEntity = await this.getUserForProfile(userId, user);
|
|
382
336
|
if (!this.dataSource) {
|
|
383
337
|
throw new BadRequestException('DataSource not available');
|
|
@@ -405,23 +359,19 @@ export class UserService extends RequestScopedApiService {
|
|
|
405
359
|
await queryRunner.release();
|
|
406
360
|
}
|
|
407
361
|
}
|
|
408
|
-
|
|
409
|
-
* Get profile completion percentage
|
|
410
|
-
*/ async getProfileCompletion(userId, user) {
|
|
362
|
+
async getProfileCompletion(userId, user) {
|
|
411
363
|
await this.getUserForProfile(userId, user);
|
|
412
364
|
if (this.userEnricher?.calculateProfileCompletion) {
|
|
413
365
|
return this.userEnricher.calculateProfileCompletion(userId, user);
|
|
414
366
|
}
|
|
415
|
-
return 100;
|
|
367
|
+
return 100;
|
|
416
368
|
}
|
|
417
|
-
|
|
418
|
-
// Ensure repository and dataSource are initialized
|
|
369
|
+
async profile(dto, user) {
|
|
419
370
|
await this.ensureRepositoryInitialized();
|
|
420
371
|
if (!this.dataSource) {
|
|
421
372
|
throw new BadRequestException('DataSource not available');
|
|
422
373
|
}
|
|
423
374
|
const userId = dto.id ?? user.id;
|
|
424
|
-
// Validate extras if enricher provides validation
|
|
425
375
|
if (dto.extras && this.userEnricher?.validateProfileExtras) {
|
|
426
376
|
await this.userEnricher.validateProfileExtras(userId, dto.extras, user);
|
|
427
377
|
}
|
|
@@ -437,9 +387,7 @@ export class UserService extends RequestScopedApiService {
|
|
|
437
387
|
if (!findUser) {
|
|
438
388
|
throw new NotFoundException('User not found');
|
|
439
389
|
}
|
|
440
|
-
// Handle password update
|
|
441
390
|
if (dto.password) {
|
|
442
|
-
// If updating own profile, require old password verification
|
|
443
391
|
const isOwnProfile = !dto.id || dto.id === user.id;
|
|
444
392
|
if (isOwnProfile) {
|
|
445
393
|
if (!dto.oldPassword) {
|
|
@@ -452,12 +400,9 @@ export class UserService extends RequestScopedApiService {
|
|
|
452
400
|
}
|
|
453
401
|
findUser.password = await bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
|
|
454
402
|
}
|
|
455
|
-
// Merge other fields (excluding password, oldPassword, extras, and sensitive flags)
|
|
456
|
-
// Users cannot self-modify emailVerified, phoneVerified, or isActive via profile update
|
|
457
403
|
const { password, oldPassword, extras, emailVerified, phoneVerified, isActive, ...restDto } = dto;
|
|
458
404
|
Object.assign(findUser, restDto);
|
|
459
405
|
await queryRunner.manager.save(this.repository.target, findUser);
|
|
460
|
-
// Handle extras update via enricher
|
|
461
406
|
if (extras && this.userEnricher?.updateProfileExtras) {
|
|
462
407
|
await this.userEnricher.updateProfileExtras(userId, extras, queryRunner);
|
|
463
408
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
1
|
+
import { ILoggedUserInfo, IPermissionLogic } from '@flusys/nestjs-shared/interfaces';
|
|
2
2
|
import { QueryRunner, SelectQueryBuilder } from 'typeorm';
|
|
3
3
|
import { User } from '../entities/user.entity';
|
|
4
4
|
import { IUser } from './user.interface';
|
|
@@ -9,7 +9,7 @@ export interface IProfileSection {
|
|
|
9
9
|
icon?: string;
|
|
10
10
|
required?: boolean;
|
|
11
11
|
hasFileUpload?: boolean;
|
|
12
|
-
editPermission?:
|
|
12
|
+
editPermission?: IPermissionLogic;
|
|
13
13
|
}
|
|
14
14
|
export interface IProfileSectionData {
|
|
15
15
|
sectionId: string;
|
|
@@ -61,4 +61,5 @@ export interface IUserEnricher {
|
|
|
61
61
|
}, queryRunner: QueryRunner): Promise<IProfileFile>;
|
|
62
62
|
handleSectionFileDelete?(userId: string, sectionId: string, field: string, fileId: string, queryRunner: QueryRunner): Promise<void>;
|
|
63
63
|
calculateProfileCompletion?(userId: string, user: ILoggedUserInfo): Promise<number>;
|
|
64
|
+
onUserCreated?(userId: string, additionalFields: Record<string, any> | null, queryRunner: QueryRunner): Promise<void>;
|
|
64
65
|
}
|
package/modules/auth.module.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { IBootstrapAppConfig } from '@flusys/nestjs-core';
|
|
1
2
|
import { DynamicModule } from '@nestjs/common';
|
|
2
3
|
import { AuthModuleAsyncOptions, AuthModuleOptions } from '../interfaces/auth-module-options.interface';
|
|
3
4
|
export declare class AuthModule {
|
|
4
5
|
static forRoot(options: AuthModuleOptions): DynamicModule;
|
|
5
6
|
static forRootAsync(options: AuthModuleAsyncOptions): DynamicModule;
|
|
6
7
|
private static buildModule;
|
|
8
|
+
private static getFeatureFlags;
|
|
7
9
|
private static buildImports;
|
|
8
10
|
private static buildControllers;
|
|
9
11
|
private static buildProviders;
|
|
10
12
|
private static buildExports;
|
|
11
13
|
private static createAsyncProviders;
|
|
12
|
-
static getEntities(
|
|
14
|
+
static getEntities(config: IBootstrapAppConfig): any[];
|
|
13
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-auth",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Authentication and authorization infrastructure for NestJS applications",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "fesm/index.js",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"typeorm": "^0.3.0"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@flusys/nestjs-core": "3.0.
|
|
95
|
-
"@flusys/nestjs-shared": "3.0.
|
|
94
|
+
"@flusys/nestjs-core": "3.0.1",
|
|
95
|
+
"@flusys/nestjs-shared": "3.0.1"
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -10,6 +10,7 @@ export declare class AuthConfigService implements IModuleConfigService {
|
|
|
10
10
|
getDatabaseMode(): DatabaseMode;
|
|
11
11
|
isMultiTenant(): boolean;
|
|
12
12
|
isCompanyFeatureEnabled(): boolean;
|
|
13
|
+
isEmailVerificationEnabled(): boolean;
|
|
13
14
|
getJwtSecret(): string;
|
|
14
15
|
getJwtExpiration(): string;
|
|
15
16
|
getRefreshTokenSecret(): string;
|
|
@@ -18,6 +18,7 @@ export declare class AuthDataSourceProvider extends MultiTenantDataSourceService
|
|
|
18
18
|
protected getOrCreateTenantConnection(tenant: ITenantDatabaseConfig): Promise<DataSource>;
|
|
19
19
|
private static buildParentOptions;
|
|
20
20
|
isCompanyFeatureEnabled(tenant?: ITenantDatabaseConfig): boolean;
|
|
21
|
+
isEmailVerificationEnabled(tenant?: ITenantDatabaseConfig): boolean;
|
|
21
22
|
getAuthEntities(): Promise<any[]>;
|
|
22
23
|
protected createDataSourceFromConfig(config: IDatabaseConfig): Promise<DataSource>;
|
|
23
24
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { HybridCache } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { INotificationAdapter } from '@flusys/nestjs-shared/interfaces';
|
|
2
3
|
import { JwtService } from '@nestjs/jwt';
|
|
4
|
+
import { IUserEnricher } from '../interfaces/user-enricher.interface';
|
|
3
5
|
import { RegistrationDto } from '../dtos/authentication.dto';
|
|
4
6
|
import { CompanyBranch } from '../entities/company-branch.entity';
|
|
5
7
|
import { Company } from '../entities/company.entity';
|
|
@@ -16,9 +18,12 @@ export declare class AuthenticationService {
|
|
|
16
18
|
private readonly dataSourceProvider?;
|
|
17
19
|
private readonly sessionService?;
|
|
18
20
|
private readonly authEmailService?;
|
|
21
|
+
private readonly userEnricher?;
|
|
22
|
+
private readonly notificationAdapter?;
|
|
19
23
|
private readonly logger;
|
|
20
|
-
constructor(jwtService: JwtService, authConfig: AuthConfigService, cacheManager?: HybridCache, dataSourceProvider?: AuthDataSourceProvider, sessionService?: CompanySelectionSessionService, authEmailService?: AuthEmailService);
|
|
24
|
+
constructor(jwtService: JwtService, authConfig: AuthConfigService, cacheManager?: HybridCache, dataSourceProvider?: AuthDataSourceProvider, sessionService?: CompanySelectionSessionService, authEmailService?: AuthEmailService, userEnricher?: IUserEnricher, notificationAdapter?: INotificationAdapter);
|
|
21
25
|
private isCompanyFeatureEnabled;
|
|
26
|
+
private isEmailVerificationEnabled;
|
|
22
27
|
private getUserRepository;
|
|
23
28
|
private getPermissionRepository;
|
|
24
29
|
private getCompanyRepository;
|
|
@@ -59,6 +64,7 @@ export declare class AuthenticationService {
|
|
|
59
64
|
private generateTokens;
|
|
60
65
|
private generateLoginResponse;
|
|
61
66
|
private generateLoginResponseWithCompany;
|
|
67
|
+
private sendLoginNotification;
|
|
62
68
|
private generateCompanySelectionResponse;
|
|
63
69
|
private generateRegistrationResponse;
|
|
64
70
|
private generateRegistrationResponseWithCompany;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
|
|
2
3
|
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
3
4
|
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
4
5
|
import { EntityTarget, Repository } from 'typeorm';
|
|
@@ -42,6 +43,10 @@ export declare class UserService extends RequestScopedApiService<CreateUserDto,
|
|
|
42
43
|
user: IUser;
|
|
43
44
|
extras?: IProfileExtras;
|
|
44
45
|
}>;
|
|
46
|
+
getAll(search: string, filterAndPaginationDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
|
|
47
|
+
data: Array<IUser>;
|
|
48
|
+
total: number;
|
|
49
|
+
}>;
|
|
45
50
|
getEnrichedList(users: IUser[], user: ILoggedUserInfo | null): Promise<IEnrichedUser[]>;
|
|
46
51
|
getProfileSections(): Promise<IProfileSection[]>;
|
|
47
52
|
getProfileSectionData(userId: string, sectionId: string, user: ILoggedUserInfo): Promise<IProfileSectionData | null>;
|