@tomei/sso 0.4.0 → 0.8.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.
Files changed (31) hide show
  1. package/__tests__/unit/components/login-user/login-user.spec.ts +107 -19
  2. package/__tests__/unit/session/session.service.spec.ts +20 -0
  3. package/dist/__tests__/unit/components/login-user/login-user.spec.js +89 -18
  4. package/dist/__tests__/unit/components/login-user/login-user.spec.js.map +1 -1
  5. package/dist/__tests__/unit/session/session.service.spec.js +19 -0
  6. package/dist/__tests__/unit/session/session.service.spec.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/src/components/login-user/login-user.d.ts +3 -1
  10. package/dist/src/components/login-user/login-user.js +82 -19
  11. package/dist/src/components/login-user/login-user.js.map +1 -1
  12. package/dist/src/index.d.ts +0 -1
  13. package/dist/src/index.js +0 -1
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/session/interfaces/session-service.interface.d.ts +1 -0
  16. package/dist/src/session/session.service.d.ts +1 -0
  17. package/dist/src/session/session.service.js +12 -0
  18. package/dist/src/session/session.service.js.map +1 -1
  19. package/dist/tsconfig.tsbuildinfo +1 -1
  20. package/index.ts +1 -1
  21. package/package.json +4 -1
  22. package/src/components/login-user/login-user.ts +107 -21
  23. package/src/index.ts +0 -1
  24. package/src/session/interfaces/session-service.interface.ts +1 -0
  25. package/src/session/session.service.ts +10 -0
  26. package/src/mail/index.ts +0 -2
  27. package/src/mail/interfaces/index.ts +0 -2
  28. package/src/mail/interfaces/send-mail.interface.ts +0 -8
  29. package/src/mail/interfaces/send-new-login-alert.interface.ts +0 -6
  30. package/src/mail/mail.service.ts +0 -33
  31. package/src/mail/mail.ts +0 -40
package/index.ts CHANGED
@@ -1 +1 @@
1
- export * from "./src"
1
+ export * from './src';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.4.0",
3
+ "version": "0.8.0",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -70,5 +70,8 @@
70
70
  "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
71
71
  "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
72
72
  ]
73
+ },
74
+ "dependencies": {
75
+ "@tomei/mailer": "^0.1.3"
73
76
  }
74
77
  }
@@ -6,12 +6,13 @@ import { UserRepository } from './user.repository';
6
6
  import { SystemRepository } from '../system/system.repository';
7
7
  import { SystemAccessRepository } from '../system-access/system-access.repository';
8
8
  import { LoginHistoryRepository } from '../login-history/login-history.repository';
9
- import { MailService } from '../../mail/mail.service';
10
9
  import { UserUserGroupRepository } from '../user-user-group/user-user-group.repository';
11
10
  import { PasswordHashService } from '../password-hash/password-hash.service';
12
11
  import { SessionService } from '../../session/session.service';
13
12
  import { UserGroupRepository } from '../user-group/user-group.repository';
14
-
13
+ import * as nodemailer from 'nodemailer';
14
+ import { Mailer } from '@tomei/mailer';
15
+ import { ISystemLogin } from '../../../src/interfaces/system-login.interface';
15
16
  export class LoginUser extends ObjectBase implements IPerson {
16
17
  FullName: string;
17
18
  IDNo: string;
@@ -28,7 +29,6 @@ export class LoginUser extends ObjectBase implements IPerson {
28
29
  private _OriginIP: string;
29
30
  private _SessionService: ISessionService;
30
31
  private _PasswordHashService = new PasswordHashService();
31
- private _MailService = new MailService();
32
32
  private static _Repository = new UserRepository();
33
33
  private static _SystemRepository = new SystemRepository();
34
34
  private static _SystemAccessRepository = new SystemAccessRepository();
@@ -233,26 +233,53 @@ export class LoginUser extends ObjectBase implements IPerson {
233
233
  systemId: string,
234
234
  ipAddress: string,
235
235
  ) {
236
- const userLogins = await LoginUser._LoginHistoryRepository.findAll({
237
- where: {
238
- userId: userId,
239
- systemId: systemId,
240
- },
241
- });
236
+ try {
237
+ const userLogins = await LoginUser._LoginHistoryRepository.findAll({
238
+ where: {
239
+ userId: userId,
240
+ systemId: systemId,
241
+ },
242
+ });
242
243
 
243
- const gotPreviousLogins = userLogins?.length !== 0;
244
- let ipFound = null;
245
- if (gotPreviousLogins) {
246
- ipFound = userLogins.find((item) => item.ipAddress === ipAddress);
247
- }
244
+ const gotPreviousLogins = userLogins?.length !== 0;
245
+ let ipFound = null;
246
+ if (gotPreviousLogins) {
247
+ ipFound = userLogins.find((item) => item.ipAddress === ipAddress);
248
+ }
248
249
 
249
- if (gotPreviousLogins && !ipFound) {
250
- await this._MailService.sendNewLoginAlertEmail({
251
- IpAddress: ipAddress,
252
- Email: this.Email,
253
- Name: this.FullName,
254
- LoginDate: new Date(),
255
- });
250
+ if (gotPreviousLogins && !ipFound) {
251
+ const SMTP_HOST = process.env.SMTP_HOST || '';
252
+ const SMTP_PORT = process.env.SMTP_PORT || '';
253
+ const EMAIL_SENDER = process.env.EMAIL_SENDER || '';
254
+ const EMAIL_PASSWORD = process.env.EMAIL_PASSWORD || '';
255
+
256
+ const mailer = new Mailer(nodemailer, {
257
+ host: SMTP_HOST,
258
+ port: Number(SMTP_PORT),
259
+ secure: Number(SMTP_PORT) === 465,
260
+ auth: {
261
+ user: EMAIL_SENDER,
262
+ pass: EMAIL_PASSWORD,
263
+ },
264
+ });
265
+
266
+ await mailer.sendMail({
267
+ from: process.env.EMAIL_SENDER,
268
+ to: this.Email,
269
+ subject: 'New Login Alert',
270
+ html: `<p>Dear ${this.FullName},</p>
271
+ <p>There was a new login to your account from ${ipAddress} on ${new Date().toLocaleString()}.</p>
272
+ <p>If this was you, you can safely ignore this email.</p>
273
+ <p>If you suspect that someone else is trying to access your account, please contact us immediately at itd-support@tomei.com.my.</p>
274
+ <p>Thank you!,</p>
275
+ <p>
276
+ Best Regards,
277
+ IT Department
278
+ </p>`,
279
+ });
280
+ }
281
+ } catch (error) {
282
+ throw error;
256
283
  }
257
284
  }
258
285
 
@@ -431,4 +458,63 @@ export class LoginUser extends ObjectBase implements IPerson {
431
458
  throw error;
432
459
  }
433
460
  }
461
+
462
+ async checkPrivileges(
463
+ systemCode: string,
464
+ privilegeName: string,
465
+ ): Promise<boolean> {
466
+ if (!this.ObjectId) {
467
+ throw new Error('ObjectId(UserId) is not set');
468
+ }
469
+
470
+ const userSession = await this._SessionService.retrieveUserSession(
471
+ this.ObjectId,
472
+ );
473
+
474
+ const systemLogin = userSession.systemLogins.find(
475
+ (system) => system.code === systemCode,
476
+ );
477
+
478
+ if (!systemLogin) {
479
+ return false;
480
+ }
481
+
482
+ const privileges = systemLogin.privileges;
483
+ const hasPrivilege = privileges.includes(privilegeName);
484
+ return hasPrivilege;
485
+ }
486
+
487
+ async checkSession(
488
+ systemCode: string,
489
+ sessionId: string,
490
+ userId: string,
491
+ ): Promise<ISystemLogin> {
492
+ try {
493
+ const userSession = await this._SessionService.retrieveUserSession(
494
+ userId,
495
+ );
496
+
497
+ if (userSession.systemLogins.length === 0) {
498
+ throw new Error('Session expired.');
499
+ }
500
+
501
+ const systemLogin = userSession.systemLogins.find(
502
+ (sl) => sl.code === systemCode,
503
+ );
504
+
505
+ if (!systemLogin) {
506
+ throw new Error('Session expired.');
507
+ }
508
+
509
+ if (systemLogin.sessionId !== sessionId) {
510
+ throw new Error('Session expired.');
511
+ }
512
+
513
+ await this._SessionService.refreshDuration(userId);
514
+
515
+ return systemLogin;
516
+ } catch (error) {
517
+ throw error;
518
+ }
519
+ }
434
520
  }
package/src/index.ts CHANGED
@@ -2,6 +2,5 @@ require('dotenv').config();
2
2
  export * from './components';
3
3
  export * from './interfaces';
4
4
  export * from './redis-client';
5
- export * from './mail';
6
5
  export * from './prisma-client';
7
6
  export * from './session';
@@ -3,4 +3,5 @@ import { IUserSession } from '../../interfaces/user-session.interface';
3
3
  export interface ISessionService {
4
4
  retrieveUserSession(userId: string): Promise<IUserSession>;
5
5
  setUserSession(userId: string, sessionData: IUserSession): Promise<void>;
6
+ refreshDuration(userId: string): Promise<void>;
6
7
  }
@@ -42,4 +42,14 @@ export class SessionService implements ISessionService {
42
42
  throw error;
43
43
  }
44
44
  }
45
+
46
+ async refreshDuration(userid: string): Promise<void> {
47
+ try {
48
+ const key = `tomei-sid:${userid}`;
49
+ const userSession = await this.retrieveUserSession(userid);
50
+ await this.setUserSession(key, userSession);
51
+ } catch (error) {
52
+ throw error;
53
+ }
54
+ }
45
55
  }
package/src/mail/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './mail.service';
2
- export * from './mail';
@@ -1,2 +0,0 @@
1
- export * from './send-mail.interface';
2
- export * from './send-new-login-alert.interface';
@@ -1,8 +0,0 @@
1
- export interface ISendMailOptionsInterface {
2
- to: string | string[];
3
- cc?: string | string[];
4
- bcc?: string | string[];
5
- subject: string;
6
- text?: string;
7
- html: string;
8
- }
@@ -1,6 +0,0 @@
1
- export interface ISendNewLoginAlertOptions {
2
- IpAddress: string;
3
- Email: string;
4
- Name: string;
5
- LoginDate: Date;
6
- }
@@ -1,33 +0,0 @@
1
- import { ISendNewLoginAlertOptions } from './interfaces/send-new-login-alert.interface';
2
- import Mail from './mail';
3
-
4
- export class MailService {
5
- MailClient: Mail;
6
- constructor() {
7
- this.MailClient = Mail.init();
8
- }
9
-
10
- public async sendNewLoginAlertEmail(
11
- options: ISendNewLoginAlertOptions,
12
- ): Promise<void> {
13
- try {
14
- await this.MailClient.sendMail({
15
- to: options.Email,
16
- subject: 'New Login Alert',
17
- html: `<p>Dear ${options.Name},</p>
18
- <p>There was a new login to your account from ${
19
- options.IpAddress
20
- } on ${options.LoginDate.toLocaleString()}.</p>
21
- <p>If this was you, you can safely ignore this email.</p>
22
- <p>If you suspect that someone else is trying to access your account, please contact us immediately at itd-support@tomei.com.my.</p>
23
- <p>Thank you!,</p>
24
- <p>
25
- Best Regards,
26
- IT Department
27
- </p>`,
28
- });
29
- } catch (error) {
30
- throw error;
31
- }
32
- }
33
- }
package/src/mail/mail.ts DELETED
@@ -1,40 +0,0 @@
1
- import * as nodemailer from 'nodemailer';
2
- import { ISendMailOptionsInterface } from './interfaces/send-mail.interface';
3
-
4
- export default class Mail {
5
- private static transporter: nodemailer.Transporter;
6
-
7
- constructor() {}
8
-
9
- static init() {
10
- if (!Mail.transporter) {
11
- Mail.transporter = nodemailer.createTransport({
12
- host: process.env.SMTP_HOST,
13
- port: Number(process.env.SMTP_PORT),
14
- secure: Number(process.env.SMTP_PORT) === 465,
15
- auth: {
16
- user: process.env.EMAIL_SENDER,
17
- pass: process.env.EMAIL_PASSWORD,
18
- },
19
- });
20
- }
21
- return new Mail();
22
- }
23
-
24
- //SEND MAIL
25
- async sendMail(options: ISendMailOptionsInterface): Promise<void> {
26
- try {
27
- await Mail.transporter.sendMail({
28
- from: process.env.EMAIL_SENDER,
29
- to: options.to,
30
- cc: options.cc,
31
- bcc: options.bcc,
32
- subject: options.subject,
33
- text: options.text,
34
- html: options.html,
35
- });
36
- } catch (error) {
37
- throw error;
38
- }
39
- }
40
- }