@drax/identity-back 0.39.0 → 0.40.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.
@@ -19,6 +19,38 @@ class UserController extends AbstractFastifyController {
19
19
  this.tenantFilter = true;
20
20
  this.entityName = 'User';
21
21
  }
22
+ async onUserLoggedIn(request, user, session) {
23
+ const eventData = {
24
+ action: 'loggedIn',
25
+ entity: this.entityName,
26
+ resourceId: user._id.toString(),
27
+ postItem: null,
28
+ preItem: null,
29
+ detail: `User ${user.username} logged in.`,
30
+ timestamp: new Date(),
31
+ ip: request.ip,
32
+ userAgent: request.headers['user-agent'],
33
+ requestId: request.id,
34
+ user: {
35
+ id: user._id.toString(),
36
+ username: user.username,
37
+ role: {
38
+ id: user?.role?._id.toString(),
39
+ name: user?.role?.name,
40
+ },
41
+ tenant: {
42
+ id: user?.tenant?._id.toString(),
43
+ name: user?.tenant?.name,
44
+ },
45
+ apiKey: {
46
+ id: null,
47
+ name: null,
48
+ },
49
+ session: session,
50
+ }
51
+ };
52
+ this.eventEmitter.emitCrudEvent(eventData);
53
+ }
22
54
  async auth(request, reply) {
23
55
  try {
24
56
  const username = request.body.username;
@@ -26,7 +58,9 @@ class UserController extends AbstractFastifyController {
26
58
  const userAgent = request.headers['user-agent'];
27
59
  const ip = request.ip;
28
60
  const userService = UserServiceFactory();
29
- return await userService.auth(username, password, { userAgent, ip });
61
+ const { user, accessToken, session } = await userService.auth(username, password, { userAgent, ip });
62
+ this.onUserLoggedIn(request, user, session);
63
+ return { accessToken };
30
64
  }
31
65
  catch (e) {
32
66
  console.error('/api/auth error', e);
@@ -92,7 +126,8 @@ class UserController extends AbstractFastifyController {
92
126
  const tenantName = tenant?.name;
93
127
  const userService = UserServiceFactory();
94
128
  let { accessToken } = await userService.switchTenant(request.token, tenantId, tenantName);
95
- const detail = `Switched to tenant "${tenantName}" (ID: ${tenantId})`;
129
+ const username = request.rbac.username;
130
+ const detail = `User ${username} switched to tenant "${tenantName}" (ID: ${tenantId})`;
96
131
  this.onUserEvent(request, 'switchTenant', request.rbac.userId, detail);
97
132
  return { accessToken };
98
133
  }
package/dist/rbac/Rbac.js CHANGED
@@ -21,31 +21,31 @@ class Rbac {
21
21
  };
22
22
  }
23
23
  get username() {
24
- return this.authUser.username;
24
+ return this?.authUser?.username;
25
25
  }
26
26
  get userId() {
27
- return this.authUser?.id.toString();
27
+ return this?.authUser?.id.toString();
28
28
  }
29
29
  get session() {
30
- return this.authUser?.session;
30
+ return this?.authUser?.session;
31
31
  }
32
32
  get apiKeyId() {
33
- return this.authUser?.apiKeyId?.toString();
33
+ return this?.authUser?.apiKeyId?.toString();
34
34
  }
35
35
  get apiKeyName() {
36
- return this.authUser?.apiKeyName;
36
+ return this?.authUser?.apiKeyName;
37
37
  }
38
38
  get roleId() {
39
- return this.authUser?.roleId?.toString();
39
+ return this?.authUser?.roleId?.toString();
40
40
  }
41
41
  get roleName() {
42
- return this.authUser?.roleName;
42
+ return this?.authUser?.roleName;
43
43
  }
44
44
  get tenantId() {
45
- return this.authUser?.tenantId?.toString();
45
+ return this?.authUser?.tenantId?.toString();
46
46
  }
47
47
  get tenantName() {
48
- return this.authUser?.tenantName ?? undefined;
48
+ return this?.authUser?.tenantName ?? undefined;
49
49
  }
50
50
  assertAuthenticated() {
51
51
  if (!this.authUser) {
@@ -28,7 +28,8 @@ class UserService extends AbstractService {
28
28
  session: sessionUUID
29
29
  };
30
30
  const accessToken = AuthUtils.generateToken(tokenPayload);
31
- return { accessToken: accessToken };
31
+ delete user.password;
32
+ return { accessToken: accessToken, user: user, session: sessionUUID };
32
33
  }
33
34
  else {
34
35
  const userLoginFailService = UserLoginFailServiceFactory();
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.39.0",
6
+ "version": "0.40.0",
7
7
  "description": "Identity module for user management, authentication and authorization.",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -28,11 +28,11 @@
28
28
  "author": "Cristian Incarnato & Drax Team",
29
29
  "license": "ISC",
30
30
  "dependencies": {
31
- "@drax/common-back": "^0.39.0",
32
- "@drax/crud-back": "^0.39.0",
33
- "@drax/crud-share": "^0.39.0",
34
- "@drax/email-back": "^0.39.0",
35
- "@drax/identity-share": "^0.39.0",
31
+ "@drax/common-back": "^0.40.0",
32
+ "@drax/crud-back": "^0.40.0",
33
+ "@drax/crud-share": "^0.40.0",
34
+ "@drax/email-back": "^0.40.0",
35
+ "@drax/identity-share": "^0.40.0",
36
36
  "bcryptjs": "^2.4.3",
37
37
  "graphql": "^16.8.2",
38
38
  "jsonwebtoken": "^9.0.2"
@@ -63,5 +63,5 @@
63
63
  "debug": "0"
64
64
  }
65
65
  },
66
- "gitHead": "b019c40f954cf60e4ff61c53e27d5bafaea6f16c"
66
+ "gitHead": "269ec7921d83364dfba091cd74bd3f45a8135c26"
67
67
  }
@@ -37,6 +37,39 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
37
37
  this.entityName = 'User'
38
38
  }
39
39
 
40
+ async onUserLoggedIn(request: CustomRequest, user: IUser, session: string) {
41
+ const eventData: IDraxCrudEvent = {
42
+ action: 'loggedIn',
43
+ entity: this.entityName,
44
+ resourceId: user._id.toString(),
45
+ postItem: null,
46
+ preItem: null,
47
+ detail: `User ${user.username} logged in.`,
48
+ timestamp: new Date(),
49
+ ip: request.ip,
50
+ userAgent: request.headers['user-agent'],
51
+ requestId: request.id,
52
+ user: {
53
+ id: user._id.toString(),
54
+ username: user.username,
55
+ role:{
56
+ id: user?.role?._id.toString(),
57
+ name: user?.role?.name,
58
+ },
59
+ tenant: {
60
+ id: user?.tenant?._id.toString(),
61
+ name: user?.tenant?.name,
62
+ },
63
+ apiKey: {
64
+ id: null,
65
+ name: null,
66
+ },
67
+ session: session,
68
+ }
69
+ }
70
+ this.eventEmitter.emitCrudEvent(eventData)
71
+ }
72
+
40
73
  async auth(request, reply) {
41
74
  try {
42
75
  const username = request.body.username
@@ -44,8 +77,9 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
44
77
  const userAgent = request.headers['user-agent'];
45
78
  const ip = request.ip;
46
79
  const userService = UserServiceFactory()
47
-
48
- return await userService.auth(username, password,{userAgent, ip})
80
+ const {user, accessToken, session} = await userService.auth(username, password, {userAgent, ip})
81
+ this.onUserLoggedIn(request, user, session)
82
+ return {accessToken}
49
83
  } catch (e) {
50
84
  console.error('/api/auth error', e)
51
85
  if (e instanceof BadCredentialsError) {
@@ -66,10 +100,10 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
66
100
  delete user.password
67
101
 
68
102
  //handle SwitchTenant setted in accessToken
69
- if(request.authUser.tenantId != user?.tenant?._id){
103
+ if (request.authUser.tenantId != user?.tenant?._id) {
70
104
  const tenantService = TenantServiceFactory()
71
105
  const tenant = await tenantService.findById(request.authUser.tenantId)
72
- if(tenant){
106
+ if (tenant) {
73
107
  user.tenant = tenant
74
108
  }
75
109
  }
@@ -81,13 +115,13 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
81
115
 
82
116
  }
83
117
  } catch (e) {
84
- this.handleError(e,reply)
118
+ this.handleError(e, reply)
85
119
  }
86
120
  }
87
121
 
88
122
  async onUserEvent(request: CustomRequest, action: string, resourceId: string = null, detail: string = null) {
89
123
  const requestData = this.extractRequestData(request)
90
- const eventData : IDraxCrudEvent = {
124
+ const eventData: IDraxCrudEvent = {
91
125
  action: action,
92
126
  entity: this.entityName,
93
127
  resourceId: resourceId.toString(),
@@ -107,13 +141,13 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
107
141
 
108
142
  if (request.authUser && request.token) {
109
143
  const tenantId = request.body.tenantId
110
- if(!tenantId){
144
+ if (!tenantId) {
111
145
  throw new BadRequestError('Missing tenantId')
112
146
  }
113
147
 
114
148
  const tenant = await TenantServiceFactory().findById(tenantId);
115
149
 
116
- if(!tenant){
150
+ if (!tenant) {
117
151
  throw new BadRequestError('Invalid tenantId')
118
152
  }
119
153
 
@@ -121,15 +155,16 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
121
155
  const userService = UserServiceFactory()
122
156
  let {accessToken} = await userService.switchTenant(request.token, tenantId, tenantName)
123
157
 
124
- const detail = `Switched to tenant "${tenantName}" (ID: ${tenantId})`;
125
- this.onUserEvent(request,'switchTenant',request.rbac.userId, detail)
158
+ const username = request.rbac.username
159
+ const detail = `User ${username} switched to tenant "${tenantName}" (ID: ${tenantId})`;
160
+ this.onUserEvent(request, 'switchTenant', request.rbac.userId, detail)
126
161
 
127
162
  return {accessToken}
128
163
  } else {
129
164
  throw new UnauthorizedError()
130
165
  }
131
166
  } catch (e) {
132
- this.handleError(e,reply)
167
+ this.handleError(e, reply)
133
168
  }
134
169
  }
135
170
 
@@ -153,7 +188,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
153
188
  }
154
189
  return paginateResult
155
190
  } catch (e) {
156
- this.handleError(e,reply)
191
+ this.handleError(e, reply)
157
192
  }
158
193
  }
159
194
 
@@ -169,7 +204,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
169
204
  let item = await this.service.search(search, 1000, filters)
170
205
  return item
171
206
  } catch (e) {
172
- this.handleError(e,reply)
207
+ this.handleError(e, reply)
173
208
  }
174
209
  }
175
210
 
@@ -202,9 +237,9 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
202
237
  const userService = UserServiceFactory()
203
238
  let user = await userService.register(payload)
204
239
 
205
- if(user){
240
+ if (user) {
206
241
  const detail = `User ${user?.username} registered successfully.`;
207
- this.onUserEvent(request,'register',user?._id, detail)
242
+ this.onUserEvent(request, 'register', user?._id, detail)
208
243
 
209
244
  //SEND EMAIL FOR EMAIL VERIFICATION
210
245
  await UserEmailService.emailVerifyCode(user.emailCode, user.email)
@@ -217,7 +252,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
217
252
 
218
253
 
219
254
  } catch (e) {
220
- this.handleError(e,reply)
255
+ this.handleError(e, reply)
221
256
  }
222
257
  }
223
258
 
@@ -226,12 +261,12 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
226
261
  const emailCode = request.params.code
227
262
  const userService = UserServiceFactory()
228
263
  const r = await userService.verifyEmail(emailCode)
229
- if(r){
264
+ if (r) {
230
265
  const html = RegistrationCompleteHtml
231
266
  reply.header('Content-Type', 'text/html; charset=utf-8').send(html)
232
267
  }
233
268
  } catch (e) {
234
- this.handleError(e,reply)
269
+ this.handleError(e, reply)
235
270
  }
236
271
  }
237
272
 
@@ -241,7 +276,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
241
276
  const userService = UserServiceFactory()
242
277
  return await userService.verifyPhone(phoneCode)
243
278
  } catch (e) {
244
- this.handleError(e,reply)
279
+ this.handleError(e, reply)
245
280
  }
246
281
  }
247
282
 
@@ -261,7 +296,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
261
296
  this.onCreated(request, user)
262
297
  return user
263
298
  } catch (e) {
264
- this.handleError(e,reply)
299
+ this.handleError(e, reply)
265
300
  }
266
301
  }
267
302
 
@@ -281,7 +316,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
281
316
  this.onUpdated(request, preUser, user)
282
317
  return user
283
318
  } catch (e) {
284
- this.handleError(e,reply)
319
+ this.handleError(e, reply)
285
320
  }
286
321
  }
287
322
 
@@ -309,7 +344,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
309
344
  })
310
345
  }
311
346
  } catch (e) {
312
- this.handleError(e,reply)
347
+ this.handleError(e, reply)
313
348
  }
314
349
  }
315
350
 
@@ -321,7 +356,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
321
356
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
322
357
  const email = request.body.email
323
358
 
324
- if(!email || !emailRegex.test(email)){
359
+ if (!email || !emailRegex.test(email)) {
325
360
  throw new ValidationError([{field: 'email', reason: 'validation.email.invalid'}])
326
361
  }
327
362
 
@@ -336,16 +371,16 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
336
371
  }
337
372
 
338
373
  const detail = `User ${user?.username} request a password recovery .`;
339
- this.onUserEvent(request,'passwordRecoveryRequest',user?._id, detail)
374
+ this.onUserEvent(request, 'passwordRecoveryRequest', user?._id, detail)
340
375
 
341
376
  reply.send({message})
342
377
 
343
378
  } catch (e) {
344
379
  console.error("ERROR RECOVERY", e)
345
- if(e instanceof SecuritySensitiveError){
380
+ if (e instanceof SecuritySensitiveError) {
346
381
  reply.send({message})
347
- }else{
348
- this.handleError(e,reply)
382
+ } else {
383
+ this.handleError(e, reply)
349
384
  }
350
385
  }
351
386
  }
@@ -356,27 +391,27 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
356
391
  const recoveryCode = request.body.recoveryCode
357
392
  const newPassword = request.body.newPassword
358
393
 
359
- if(!recoveryCode){
360
- throw new ValidationError([{field:'recoveryCode', reason: 'validation.required'}])
394
+ if (!recoveryCode) {
395
+ throw new ValidationError([{field: 'recoveryCode', reason: 'validation.required'}])
361
396
  }
362
397
 
363
- if(!newPassword){
364
- throw new ValidationError([{field:'newPassword', reason: 'validation.required'}])
398
+ if (!newPassword) {
399
+ throw new ValidationError([{field: 'newPassword', reason: 'validation.required'}])
365
400
  }
366
401
 
367
402
  const userService = UserServiceFactory()
368
403
  const user: IUser = await userService.changeUserPasswordByCode(recoveryCode, newPassword)
369
- if(user){
404
+ if (user) {
370
405
  const detail = `User ${user?.username} complete a password recovery .`;
371
- this.onUserEvent(request,'passwordRecoveryCompleted',user?._id, detail)
406
+ this.onUserEvent(request, 'passwordRecoveryCompleted', user?._id, detail)
372
407
  reply.send({message: 'action.success'})
373
- }else{
408
+ } else {
374
409
  reply.statusCode = 400
375
410
  reply.send({message: 'action.failure'})
376
411
  }
377
412
 
378
413
  } catch (e) {
379
- this.handleError(e,reply)
414
+ this.handleError(e, reply)
380
415
  }
381
416
  }
382
417
 
@@ -392,10 +427,10 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
392
427
  const userService = UserServiceFactory()
393
428
  const user = await userService.changeOwnPassword(userId, currentPassword, newPassword)
394
429
  const detail = `User ${user?.username} changed his password.`;
395
- this.onUserEvent(request,'changeMyPassword',user?._id, detail)
430
+ this.onUserEvent(request, 'changeMyPassword', user?._id, detail)
396
431
  return {message: 'Password updated successfully'}
397
432
  } catch (e) {
398
- this.handleError(e,reply)
433
+ this.handleError(e, reply)
399
434
  }
400
435
  }
401
436
 
@@ -410,10 +445,10 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
410
445
  const userService = UserServiceFactory()
411
446
  const user = await userService.changeUserPassword(userId, newPassword)
412
447
  const detail = `User ${request.rbac.username} changed password for user ${user.username}.`;
413
- this.onUserEvent(request,'changePassword',user?._id, detail)
448
+ this.onUserEvent(request, 'changePassword', user?._id, detail)
414
449
  return {message: 'Password updated successfully'}
415
450
  } catch (e) {
416
- this.handleError(e,reply)
451
+ this.handleError(e, reply)
417
452
  }
418
453
  }
419
454
 
@@ -440,7 +475,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
440
475
  const user = await userService.changeAvatar(userId, urlFile)
441
476
 
442
477
  const detail = `User ${request.rbac.username} changed avatar.`
443
- this.onUserEvent(request,'changeAvatar',user?._id, detail)
478
+ this.onUserEvent(request, 'changeAvatar', user?._id, detail)
444
479
 
445
480
  return {
446
481
  filename: storedFile.filename,
@@ -449,7 +484,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
449
484
  url: urlFile,
450
485
  }
451
486
  } catch (e) {
452
- this.handleError(e,reply)
487
+ this.handleError(e, reply)
453
488
  }
454
489
 
455
490
  }
@@ -462,7 +497,7 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
462
497
  //console.log("FILE_DIR: ",fileDir, " FILENAME:", filename)
463
498
  return reply.sendFile(filename, fileDir)
464
499
  } catch (e) {
465
- this.handleError(e,reply)
500
+ this.handleError(e, reply)
466
501
  }
467
502
 
468
503
  }
package/src/rbac/Rbac.ts CHANGED
@@ -29,39 +29,39 @@ class Rbac implements IRbac{
29
29
  }
30
30
 
31
31
  get username(): string{
32
- return this.authUser.username
32
+ return this?.authUser?.username
33
33
  }
34
34
 
35
35
  get userId(): string {
36
- return this.authUser?.id.toString()
36
+ return this?.authUser?.id.toString()
37
37
  }
38
38
 
39
39
  get session(): string {
40
- return this.authUser?.session
40
+ return this?.authUser?.session
41
41
  }
42
42
 
43
43
  get apiKeyId(): string {
44
- return this.authUser?.apiKeyId?.toString()
44
+ return this?.authUser?.apiKeyId?.toString()
45
45
  }
46
46
 
47
47
  get apiKeyName(): string {
48
- return this.authUser?.apiKeyName
48
+ return this?.authUser?.apiKeyName
49
49
  }
50
50
 
51
51
  get roleId(): string {
52
- return this.authUser?.roleId?.toString()
52
+ return this?.authUser?.roleId?.toString()
53
53
  }
54
54
 
55
55
  get roleName(): string {
56
- return this.authUser?.roleName
56
+ return this?.authUser?.roleName
57
57
  }
58
58
 
59
59
  get tenantId(): string | undefined {
60
- return this.authUser?.tenantId?.toString();
60
+ return this?.authUser?.tenantId?.toString();
61
61
  }
62
62
 
63
63
  get tenantName(): string | undefined {
64
- return this.authUser?.tenantName ?? undefined;
64
+ return this?.authUser?.tenantName ?? undefined;
65
65
  }
66
66
 
67
67
  assertAuthenticated() {
@@ -40,7 +40,8 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate> {
40
40
  }
41
41
 
42
42
  const accessToken = AuthUtils.generateToken(tokenPayload)
43
- return {accessToken: accessToken}
43
+ delete user.password
44
+ return {accessToken: accessToken, user: user, session: sessionUUID}
44
45
  } else {
45
46
  const userLoginFailService = UserLoginFailServiceFactory()
46
47
  await userLoginFailService.create({