@scryan7371/sdr-security 0.1.2 → 0.1.3

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 (68) hide show
  1. package/README.md +48 -7
  2. package/dist/api/contracts.d.ts +0 -2
  3. package/dist/api/migrations/1739500000000-create-security-identity.d.ts +1 -1
  4. package/dist/api/migrations/1739500000000-create-security-identity.js +9 -35
  5. package/dist/api/migrations/1739510000000-create-security-roles.d.ts +1 -1
  6. package/dist/api/migrations/1739510000000-create-security-roles.js +1 -67
  7. package/dist/api/migrations/1739515000000-create-security-user-roles.d.ts +9 -0
  8. package/dist/api/migrations/1739515000000-create-security-user-roles.js +39 -0
  9. package/dist/api/migrations/1739520000000-create-password-reset-tokens.js +1 -1
  10. package/dist/api/migrations/1739530000000-create-security-user.d.ts +9 -0
  11. package/dist/api/migrations/1739530000000-create-security-user.js +41 -0
  12. package/dist/api/migrations/index.d.ts +3 -2
  13. package/dist/api/migrations/index.js +7 -4
  14. package/dist/api/migrations/migrations.test.js +37 -83
  15. package/dist/api/notification-workflows.d.ts +0 -4
  16. package/dist/api/notification-workflows.js +0 -1
  17. package/dist/api/notification-workflows.test.js +1 -4
  18. package/dist/app/client.d.ts +0 -2
  19. package/dist/app/client.test.js +0 -2
  20. package/dist/nest/contracts.d.ts +0 -3
  21. package/dist/nest/dto/auth.dto.d.ts +0 -2
  22. package/dist/nest/dto/auth.dto.js +0 -10
  23. package/dist/nest/entities/app-user.entity.d.ts +0 -7
  24. package/dist/nest/entities/app-user.entity.js +0 -35
  25. package/dist/nest/entities/security-user.entity.d.ts +9 -0
  26. package/dist/nest/entities/security-user.entity.js +54 -0
  27. package/dist/nest/index.d.ts +1 -0
  28. package/dist/nest/index.js +1 -0
  29. package/dist/nest/security-auth.controller.d.ts +0 -2
  30. package/dist/nest/security-auth.controller.js +0 -2
  31. package/dist/nest/security-auth.controller.test.js +0 -4
  32. package/dist/nest/security-auth.module.js +2 -0
  33. package/dist/nest/security-auth.service.d.ts +5 -4
  34. package/dist/nest/security-auth.service.js +81 -51
  35. package/dist/nest/security-auth.service.test.js +45 -41
  36. package/dist/nest/security-workflows.module.js +2 -0
  37. package/dist/nest/security-workflows.service.d.ts +4 -2
  38. package/dist/nest/security-workflows.service.js +19 -16
  39. package/dist/nest/security-workflows.service.test.js +29 -24
  40. package/package.json +3 -3
  41. package/src/api/contracts.ts +0 -2
  42. package/src/api/migrations/1739500000000-create-security-identity.ts +11 -50
  43. package/src/api/migrations/1739510000000-create-security-roles.ts +2 -89
  44. package/src/api/migrations/1739515000000-create-security-user-roles.ts +49 -0
  45. package/src/api/migrations/1739520000000-create-password-reset-tokens.ts +1 -1
  46. package/src/api/migrations/1739530000000-create-security-user.ts +51 -0
  47. package/src/api/migrations/index.ts +6 -3
  48. package/src/api/migrations/migrations.test.ts +48 -111
  49. package/src/api/notification-workflows.test.ts +1 -4
  50. package/src/api/notification-workflows.ts +1 -8
  51. package/src/app/client.test.ts +0 -2
  52. package/src/app/client.ts +1 -6
  53. package/src/nest/contracts.ts +1 -6
  54. package/src/nest/dto/auth.dto.ts +0 -6
  55. package/src/nest/entities/app-user.entity.ts +0 -21
  56. package/src/nest/entities/security-user.entity.ts +25 -0
  57. package/src/nest/index.ts +1 -0
  58. package/src/nest/security-auth.controller.test.ts +0 -4
  59. package/src/nest/security-auth.controller.ts +0 -4
  60. package/src/nest/security-auth.module.ts +2 -0
  61. package/src/nest/security-auth.service.test.ts +74 -43
  62. package/src/nest/security-auth.service.ts +88 -51
  63. package/src/nest/security-workflows.module.ts +2 -0
  64. package/src/nest/security-workflows.service.test.ts +31 -25
  65. package/src/nest/security-workflows.service.ts +18 -13
  66. package/dist/api/migrations/1739490000000-add-google-subject-to-user.d.ts +0 -5
  67. package/dist/api/migrations/1739490000000-add-google-subject-to-user.js +0 -14
  68. package/src/api/migrations/1739490000000-add-google-subject-to-user.ts +0 -12
@@ -9,8 +9,6 @@ export declare const createSecurityClient: (options: SecurityClientOptions) => {
9
9
  register: (payload: {
10
10
  email: string;
11
11
  password: string;
12
- firstName?: string;
13
- lastName?: string;
14
12
  }) => Promise<RegisterResponse>;
15
13
  login: (payload: {
16
14
  email: string;
@@ -26,8 +26,6 @@ const makeFetch = (responses) => {
26
26
  await client.register({
27
27
  email: "user@example.com",
28
28
  password: "Secret123",
29
- firstName: "A",
30
- lastName: "B",
31
29
  });
32
30
  (0, vitest_1.expect)(fetchImpl).toHaveBeenCalledWith("https://api.example.com/security/auth/register", vitest_1.expect.objectContaining({
33
31
  method: "POST",
@@ -1,8 +1,6 @@
1
1
  export type SecurityWorkflowUser = {
2
2
  id: string;
3
3
  email: string;
4
- firstName: string | null;
5
- lastName: string | null;
6
4
  };
7
5
  export type SecurityWorkflowNotifier = {
8
6
  sendEmailVerification?: (params: {
@@ -19,6 +17,5 @@ export type SecurityWorkflowNotifier = {
19
17
  }) => Promise<void>;
20
18
  sendUserAccountApproved: (params: {
21
19
  email: string;
22
- firstName: string | null;
23
20
  }) => Promise<void>;
24
21
  };
@@ -1,8 +1,6 @@
1
1
  export declare class RegisterDto {
2
2
  email: string;
3
3
  password: string;
4
- firstName?: string | null;
5
- lastName?: string | null;
6
4
  }
7
5
  export declare class LoginDto {
8
6
  email: string;
@@ -14,8 +14,6 @@ const swagger_1 = require("@nestjs/swagger");
14
14
  class RegisterDto {
15
15
  email;
16
16
  password;
17
- firstName;
18
- lastName;
19
17
  }
20
18
  exports.RegisterDto = RegisterDto;
21
19
  __decorate([
@@ -26,14 +24,6 @@ __decorate([
26
24
  (0, swagger_1.ApiProperty)({ example: "StrongPass1" }),
27
25
  __metadata("design:type", String)
28
26
  ], RegisterDto.prototype, "password", void 0);
29
- __decorate([
30
- (0, swagger_1.ApiProperty)({ required: false, nullable: true, example: "John" }),
31
- __metadata("design:type", Object)
32
- ], RegisterDto.prototype, "firstName", void 0);
33
- __decorate([
34
- (0, swagger_1.ApiProperty)({ required: false, nullable: true, example: "Doe" }),
35
- __metadata("design:type", Object)
36
- ], RegisterDto.prototype, "lastName", void 0);
37
27
  class LoginDto {
38
28
  email;
39
29
  password;
@@ -1,11 +1,4 @@
1
1
  export declare class AppUserEntity {
2
2
  id: string;
3
3
  email: string;
4
- passwordHash: string;
5
- firstName: string | null;
6
- lastName: string | null;
7
- emailVerifiedAt: Date | null;
8
- emailVerificationToken: string | null;
9
- adminApprovedAt: Date | null;
10
- isActive: boolean;
11
4
  }
@@ -14,13 +14,6 @@ const typeorm_1 = require("typeorm");
14
14
  let AppUserEntity = class AppUserEntity {
15
15
  id;
16
16
  email;
17
- passwordHash;
18
- firstName;
19
- lastName;
20
- emailVerifiedAt;
21
- emailVerificationToken;
22
- adminApprovedAt;
23
- isActive;
24
17
  };
25
18
  exports.AppUserEntity = AppUserEntity;
26
19
  __decorate([
@@ -31,34 +24,6 @@ __decorate([
31
24
  (0, typeorm_1.Column)({ type: "varchar" }),
32
25
  __metadata("design:type", String)
33
26
  ], AppUserEntity.prototype, "email", void 0);
34
- __decorate([
35
- (0, typeorm_1.Column)({ type: "varchar", name: "password_hash" }),
36
- __metadata("design:type", String)
37
- ], AppUserEntity.prototype, "passwordHash", void 0);
38
- __decorate([
39
- (0, typeorm_1.Column)({ type: "varchar", name: "first_name", nullable: true }),
40
- __metadata("design:type", Object)
41
- ], AppUserEntity.prototype, "firstName", void 0);
42
- __decorate([
43
- (0, typeorm_1.Column)({ type: "varchar", name: "last_name", nullable: true }),
44
- __metadata("design:type", Object)
45
- ], AppUserEntity.prototype, "lastName", void 0);
46
- __decorate([
47
- (0, typeorm_1.Column)({ type: "timestamptz", name: "email_verified_at", nullable: true }),
48
- __metadata("design:type", Object)
49
- ], AppUserEntity.prototype, "emailVerifiedAt", void 0);
50
- __decorate([
51
- (0, typeorm_1.Column)({ type: "varchar", name: "email_verification_token", nullable: true }),
52
- __metadata("design:type", Object)
53
- ], AppUserEntity.prototype, "emailVerificationToken", void 0);
54
- __decorate([
55
- (0, typeorm_1.Column)({ type: "timestamptz", name: "admin_approved_at", nullable: true }),
56
- __metadata("design:type", Object)
57
- ], AppUserEntity.prototype, "adminApprovedAt", void 0);
58
- __decorate([
59
- (0, typeorm_1.Column)({ type: "boolean", name: "is_active", default: true }),
60
- __metadata("design:type", Boolean)
61
- ], AppUserEntity.prototype, "isActive", void 0);
62
27
  exports.AppUserEntity = AppUserEntity = __decorate([
63
28
  (0, typeorm_1.Entity)({ name: "app_user" })
64
29
  ], AppUserEntity);
@@ -0,0 +1,9 @@
1
+ export declare class SecurityUserEntity {
2
+ userId: string;
3
+ passwordHash: string;
4
+ emailVerifiedAt: Date | null;
5
+ emailVerificationToken: string | null;
6
+ adminApprovedAt: Date | null;
7
+ isActive: boolean;
8
+ createdAt: Date;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SecurityUserEntity = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ let SecurityUserEntity = class SecurityUserEntity {
15
+ userId;
16
+ passwordHash;
17
+ emailVerifiedAt;
18
+ emailVerificationToken;
19
+ adminApprovedAt;
20
+ isActive;
21
+ createdAt;
22
+ };
23
+ exports.SecurityUserEntity = SecurityUserEntity;
24
+ __decorate([
25
+ (0, typeorm_1.PrimaryColumn)({ type: "varchar", name: "user_id" }),
26
+ __metadata("design:type", String)
27
+ ], SecurityUserEntity.prototype, "userId", void 0);
28
+ __decorate([
29
+ (0, typeorm_1.Column)({ type: "varchar", name: "password_hash" }),
30
+ __metadata("design:type", String)
31
+ ], SecurityUserEntity.prototype, "passwordHash", void 0);
32
+ __decorate([
33
+ (0, typeorm_1.Column)({ type: "timestamptz", name: "email_verified_at", nullable: true }),
34
+ __metadata("design:type", Object)
35
+ ], SecurityUserEntity.prototype, "emailVerifiedAt", void 0);
36
+ __decorate([
37
+ (0, typeorm_1.Column)({ type: "varchar", name: "email_verification_token", nullable: true }),
38
+ __metadata("design:type", Object)
39
+ ], SecurityUserEntity.prototype, "emailVerificationToken", void 0);
40
+ __decorate([
41
+ (0, typeorm_1.Column)({ type: "timestamptz", name: "admin_approved_at", nullable: true }),
42
+ __metadata("design:type", Object)
43
+ ], SecurityUserEntity.prototype, "adminApprovedAt", void 0);
44
+ __decorate([
45
+ (0, typeorm_1.Column)({ type: "boolean", name: "is_active", default: true }),
46
+ __metadata("design:type", Boolean)
47
+ ], SecurityUserEntity.prototype, "isActive", void 0);
48
+ __decorate([
49
+ (0, typeorm_1.CreateDateColumn)({ name: "created_at" }),
50
+ __metadata("design:type", Date)
51
+ ], SecurityUserEntity.prototype, "createdAt", void 0);
52
+ exports.SecurityUserEntity = SecurityUserEntity = __decorate([
53
+ (0, typeorm_1.Entity)({ name: "security_user" })
54
+ ], SecurityUserEntity);
@@ -15,4 +15,5 @@ export * from "./entities/app-user.entity";
15
15
  export * from "./entities/refresh-token.entity";
16
16
  export * from "./entities/password-reset-token.entity";
17
17
  export * from "./entities/security-role.entity";
18
+ export * from "./entities/security-user.entity";
18
19
  export * from "./entities/security-user-role.entity";
@@ -31,4 +31,5 @@ __exportStar(require("./entities/app-user.entity"), exports);
31
31
  __exportStar(require("./entities/refresh-token.entity"), exports);
32
32
  __exportStar(require("./entities/password-reset-token.entity"), exports);
33
33
  __exportStar(require("./entities/security-role.entity"), exports);
34
+ __exportStar(require("./entities/security-user.entity"), exports);
34
35
  __exportStar(require("./entities/security-user-role.entity"), exports);
@@ -10,8 +10,6 @@ export declare class SecurityAuthController {
10
10
  register(body: {
11
11
  email?: string;
12
12
  password?: string;
13
- firstName?: string;
14
- lastName?: string;
15
13
  }): Promise<import("../api").RegisterResponse>;
16
14
  login(body: {
17
15
  email?: string;
@@ -30,8 +30,6 @@ let SecurityAuthController = class SecurityAuthController {
30
30
  return this.authService.register({
31
31
  email: body.email,
32
32
  password: body.password,
33
- firstName: body.firstName ?? null,
34
- lastName: body.lastName ?? null,
35
33
  });
36
34
  }
37
35
  async login(body) {
@@ -29,15 +29,11 @@ const makeAuthService = () => ({
29
29
  const result = await controller.register({
30
30
  email: "user@example.com",
31
31
  password: "Secret123",
32
- firstName: "A",
33
- lastName: "B",
34
32
  });
35
33
  (0, vitest_1.expect)(result).toEqual({ success: true });
36
34
  (0, vitest_1.expect)(service.register).toHaveBeenCalledWith({
37
35
  email: "user@example.com",
38
36
  password: "Secret123",
39
- firstName: "A",
40
- lastName: "B",
41
37
  });
42
38
  });
43
39
  (0, vitest_1.it)("validates login and refresh payloads", async () => {
@@ -14,6 +14,7 @@ const app_user_entity_1 = require("./entities/app-user.entity");
14
14
  const password_reset_token_entity_1 = require("./entities/password-reset-token.entity");
15
15
  const refresh_token_entity_1 = require("./entities/refresh-token.entity");
16
16
  const security_role_entity_1 = require("./entities/security-role.entity");
17
+ const security_user_entity_1 = require("./entities/security-user.entity");
17
18
  const security_user_role_entity_1 = require("./entities/security-user-role.entity");
18
19
  const security_admin_guard_1 = require("./security-admin.guard");
19
20
  const security_auth_controller_1 = require("./security-auth.controller");
@@ -40,6 +41,7 @@ let SecurityAuthModule = SecurityAuthModule_1 = class SecurityAuthModule {
40
41
  imports: [
41
42
  typeorm_1.TypeOrmModule.forFeature([
42
43
  app_user_entity_1.AppUserEntity,
44
+ security_user_entity_1.SecurityUserEntity,
43
45
  refresh_token_entity_1.RefreshTokenEntity,
44
46
  password_reset_token_entity_1.PasswordResetTokenEntity,
45
47
  security_role_entity_1.SecurityRoleEntity,
@@ -5,22 +5,22 @@ import { AppUserEntity } from "./entities/app-user.entity";
5
5
  import { PasswordResetTokenEntity } from "./entities/password-reset-token.entity";
6
6
  import { RefreshTokenEntity } from "./entities/refresh-token.entity";
7
7
  import { SecurityRoleEntity } from "./entities/security-role.entity";
8
+ import { SecurityUserEntity } from "./entities/security-user.entity";
8
9
  import { SecurityUserRoleEntity } from "./entities/security-user-role.entity";
9
10
  import { SecurityWorkflowNotifier } from "./contracts";
10
11
  export declare class SecurityAuthService {
11
- private readonly usersRepo;
12
+ private readonly appUsersRepo;
13
+ private readonly securityUsersRepo;
12
14
  private readonly refreshTokenRepo;
13
15
  private readonly passwordResetRepo;
14
16
  private readonly rolesRepo;
15
17
  private readonly userRolesRepo;
16
18
  private readonly options;
17
19
  private readonly notifier;
18
- constructor(usersRepo: Repository<AppUserEntity>, refreshTokenRepo: Repository<RefreshTokenEntity>, passwordResetRepo: Repository<PasswordResetTokenEntity>, rolesRepo: Repository<SecurityRoleEntity>, userRolesRepo: Repository<SecurityUserRoleEntity>, options: SecurityAuthModuleOptions, notifier: SecurityWorkflowNotifier);
20
+ constructor(appUsersRepo: Repository<AppUserEntity>, securityUsersRepo: Repository<SecurityUserEntity>, refreshTokenRepo: Repository<RefreshTokenEntity>, passwordResetRepo: Repository<PasswordResetTokenEntity>, rolesRepo: Repository<SecurityRoleEntity>, userRolesRepo: Repository<SecurityUserRoleEntity>, options: SecurityAuthModuleOptions, notifier: SecurityWorkflowNotifier);
19
21
  register(params: {
20
22
  email: string;
21
23
  password: string;
22
- firstName?: string | null;
23
- lastName?: string | null;
24
24
  }): Promise<RegisterResponse>;
25
25
  login(params: {
26
26
  email: string;
@@ -50,6 +50,7 @@ export declare class SecurityAuthService {
50
50
  userId: string;
51
51
  roles: string[];
52
52
  }>;
53
+ getUserIdByVerificationToken(token: string): Promise<string | null>;
53
54
  private assertCanAuthenticate;
54
55
  private issueTokens;
55
56
  private createEmailVerificationToken;
@@ -26,21 +26,24 @@ const app_user_entity_1 = require("./entities/app-user.entity");
26
26
  const password_reset_token_entity_1 = require("./entities/password-reset-token.entity");
27
27
  const refresh_token_entity_1 = require("./entities/refresh-token.entity");
28
28
  const security_role_entity_1 = require("./entities/security-role.entity");
29
+ const security_user_entity_1 = require("./entities/security-user.entity");
29
30
  const security_user_role_entity_1 = require("./entities/security-user-role.entity");
30
31
  const tokens_1 = require("./tokens");
31
32
  const EMAIL_TOKEN_BYTES = 24;
32
33
  const REFRESH_TOKEN_BYTES = 32;
33
34
  const PASSWORD_ROUNDS = 12;
34
35
  let SecurityAuthService = class SecurityAuthService {
35
- usersRepo;
36
+ appUsersRepo;
37
+ securityUsersRepo;
36
38
  refreshTokenRepo;
37
39
  passwordResetRepo;
38
40
  rolesRepo;
39
41
  userRolesRepo;
40
42
  options;
41
43
  notifier;
42
- constructor(usersRepo, refreshTokenRepo, passwordResetRepo, rolesRepo, userRolesRepo, options, notifier) {
43
- this.usersRepo = usersRepo;
44
+ constructor(appUsersRepo, securityUsersRepo, refreshTokenRepo, passwordResetRepo, rolesRepo, userRolesRepo, options, notifier) {
45
+ this.appUsersRepo = appUsersRepo;
46
+ this.securityUsersRepo = securityUsersRepo;
44
47
  this.refreshTokenRepo = refreshTokenRepo;
45
48
  this.passwordResetRepo = passwordResetRepo;
46
49
  this.rolesRepo = rolesRepo;
@@ -50,45 +53,52 @@ let SecurityAuthService = class SecurityAuthService {
50
53
  }
51
54
  async register(params) {
52
55
  const email = (0, validation_1.sanitizeEmail)(params.email);
53
- const existing = await this.usersRepo.findOne({ where: { email } });
56
+ const existing = await this.appUsersRepo.findOne({ where: { email } });
54
57
  if (existing) {
55
58
  throw new common_1.BadRequestException("Email already in use");
56
59
  }
57
- const user = await this.usersRepo.save(this.usersRepo.create({
60
+ const appUser = await this.appUsersRepo.save(this.appUsersRepo.create({
58
61
  email,
62
+ }));
63
+ const securityUser = await this.securityUsersRepo.save(this.securityUsersRepo.create({
64
+ userId: appUser.id,
59
65
  passwordHash: await (0, bcryptjs_1.hash)(params.password, PASSWORD_ROUNDS),
60
- firstName: params.firstName ?? null,
61
- lastName: params.lastName ?? null,
62
66
  emailVerifiedAt: null,
63
67
  emailVerificationToken: null,
64
68
  adminApprovedAt: null,
65
69
  isActive: true,
66
70
  }));
67
- const verificationToken = await this.createEmailVerificationToken(user.id);
71
+ const verificationToken = await this.createEmailVerificationToken(appUser.id);
68
72
  if (this.notifier.sendEmailVerification) {
69
73
  await this.notifier.sendEmailVerification({
70
- email: user.email,
74
+ email: appUser.email,
71
75
  token: verificationToken,
72
76
  });
73
77
  }
74
78
  return {
75
79
  success: true,
76
- user: await this.toSafeUser(user),
80
+ user: await this.toSafeUser(appUser, securityUser),
77
81
  debugToken: verificationToken,
78
82
  };
79
83
  }
80
84
  async login(params) {
81
85
  const email = (0, validation_1.sanitizeEmail)(params.email);
82
- const user = await this.usersRepo.findOne({ where: { email } });
83
- if (!user) {
86
+ const appUser = await this.appUsersRepo.findOne({ where: { email } });
87
+ if (!appUser) {
88
+ throw new common_1.UnauthorizedException("Invalid credentials");
89
+ }
90
+ const securityUser = await this.securityUsersRepo.findOne({
91
+ where: { userId: appUser.id },
92
+ });
93
+ if (!securityUser) {
84
94
  throw new common_1.UnauthorizedException("Invalid credentials");
85
95
  }
86
- const ok = await (0, bcryptjs_1.compare)(params.password, user.passwordHash);
96
+ const ok = await (0, bcryptjs_1.compare)(params.password, securityUser.passwordHash);
87
97
  if (!ok) {
88
98
  throw new common_1.UnauthorizedException("Invalid credentials");
89
99
  }
90
- this.assertCanAuthenticate(user);
91
- return this.issueTokens(user);
100
+ this.assertCanAuthenticate(securityUser);
101
+ return this.issueTokens(appUser, securityUser);
92
102
  }
93
103
  async refresh(refreshToken) {
94
104
  const record = await this.findValidRefreshToken(refreshToken);
@@ -96,14 +106,20 @@ let SecurityAuthService = class SecurityAuthService {
96
106
  throw new common_1.UnauthorizedException("Invalid refresh token");
97
107
  }
98
108
  await this.refreshTokenRepo.update({ id: record.id }, { revokedAt: new Date() });
99
- const user = await this.usersRepo.findOne({
109
+ const appUser = await this.appUsersRepo.findOne({
100
110
  where: { id: record.userId ?? "" },
101
111
  });
102
- if (!user) {
112
+ if (!appUser) {
103
113
  throw new common_1.UnauthorizedException("User not found");
104
114
  }
105
- this.assertCanAuthenticate(user);
106
- return this.issueTokens(user);
115
+ const securityUser = await this.securityUsersRepo.findOne({
116
+ where: { userId: appUser.id },
117
+ });
118
+ if (!securityUser) {
119
+ throw new common_1.UnauthorizedException("User not found");
120
+ }
121
+ this.assertCanAuthenticate(securityUser);
122
+ return this.issueTokens(appUser, securityUser);
107
123
  }
108
124
  async logout(refreshToken) {
109
125
  if (!refreshToken) {
@@ -116,34 +132,42 @@ let SecurityAuthService = class SecurityAuthService {
116
132
  return { success: true };
117
133
  }
118
134
  async changePassword(params) {
119
- const user = await this.usersRepo.findOne({ where: { id: params.userId } });
120
- if (!user) {
135
+ const securityUser = await this.securityUsersRepo.findOne({
136
+ where: { userId: params.userId },
137
+ });
138
+ if (!securityUser) {
121
139
  throw new common_1.BadRequestException("User not found");
122
140
  }
123
- const ok = await (0, bcryptjs_1.compare)(params.currentPassword, user.passwordHash);
141
+ const ok = await (0, bcryptjs_1.compare)(params.currentPassword, securityUser.passwordHash);
124
142
  if (!ok) {
125
143
  throw new common_1.UnauthorizedException("Current password is incorrect");
126
144
  }
127
- await this.usersRepo.update({ id: user.id }, { passwordHash: await (0, bcryptjs_1.hash)(params.newPassword, PASSWORD_ROUNDS) });
145
+ await this.securityUsersRepo.update({ userId: securityUser.userId }, { passwordHash: await (0, bcryptjs_1.hash)(params.newPassword, PASSWORD_ROUNDS) });
128
146
  return { success: true };
129
147
  }
130
148
  async requestForgotPassword(emailInput) {
131
149
  const email = (0, validation_1.sanitizeEmail)(emailInput);
132
- const user = await this.usersRepo.findOne({ where: { email } });
133
- if (!user) {
150
+ const appUser = await this.appUsersRepo.findOne({ where: { email } });
151
+ if (!appUser) {
152
+ return { success: true };
153
+ }
154
+ const securityUser = await this.securityUsersRepo.findOne({
155
+ where: { userId: appUser.id },
156
+ });
157
+ if (!securityUser) {
134
158
  return { success: true };
135
159
  }
136
160
  const token = (0, crypto_1.randomBytes)(EMAIL_TOKEN_BYTES).toString("hex");
137
161
  const expiresAt = new Date(Date.now() +
138
162
  (this.options.passwordResetTokenExpiresInMinutes ?? 30) * 60_000);
139
163
  await this.passwordResetRepo.save(this.passwordResetRepo.create({
140
- userId: user.id,
164
+ userId: appUser.id,
141
165
  token,
142
166
  expiresAt,
143
167
  usedAt: null,
144
168
  }));
145
169
  if (this.notifier.sendPasswordReset) {
146
- await this.notifier.sendPasswordReset({ email: user.email, token });
170
+ await this.notifier.sendPasswordReset({ email: appUser.email, token });
147
171
  }
148
172
  return { success: true };
149
173
  }
@@ -152,23 +176,29 @@ let SecurityAuthService = class SecurityAuthService {
152
176
  if (!reset || reset.usedAt || reset.expiresAt.getTime() <= Date.now()) {
153
177
  throw new common_1.BadRequestException("Invalid password reset token");
154
178
  }
155
- await this.usersRepo.update({ id: reset.userId }, { passwordHash: await (0, bcryptjs_1.hash)(newPassword, PASSWORD_ROUNDS) });
179
+ await this.securityUsersRepo.update({ userId: reset.userId }, { passwordHash: await (0, bcryptjs_1.hash)(newPassword, PASSWORD_ROUNDS) });
156
180
  await this.passwordResetRepo.update({ id: reset.id }, { usedAt: new Date() });
157
181
  return { success: true };
158
182
  }
159
183
  async verifyEmailByToken(token) {
160
- const user = await this.usersRepo.findOne({
184
+ const user = await this.securityUsersRepo.findOne({
161
185
  where: { emailVerificationToken: token },
162
186
  });
163
187
  if (!user) {
164
188
  throw new common_1.BadRequestException("Invalid verification token");
165
189
  }
166
- await this.usersRepo.update({ id: user.id }, { emailVerifiedAt: new Date(), emailVerificationToken: null });
190
+ await this.securityUsersRepo.update({ userId: user.userId }, { emailVerifiedAt: new Date(), emailVerificationToken: null });
167
191
  return { success: true };
168
192
  }
169
193
  async getMyRoles(userId) {
170
194
  return { userId, roles: await this.getUserRoleKeys(userId) };
171
195
  }
196
+ async getUserIdByVerificationToken(token) {
197
+ const user = await this.securityUsersRepo.findOne({
198
+ where: { emailVerificationToken: token },
199
+ });
200
+ return user?.userId ?? null;
201
+ }
172
202
  assertCanAuthenticate(user) {
173
203
  if (!user.isActive) {
174
204
  throw new common_1.UnauthorizedException("Account is inactive");
@@ -181,17 +211,17 @@ let SecurityAuthService = class SecurityAuthService {
181
211
  throw new common_1.UnauthorizedException("Admin approval required");
182
212
  }
183
213
  }
184
- async issueTokens(user) {
185
- const roles = await this.getUserRoleKeys(user.id);
214
+ async issueTokens(appUser, securityUser) {
215
+ const roles = await this.getUserRoleKeys(appUser.id);
186
216
  const accessTokenExpiresIn = this.options.accessTokenExpiresIn ?? "15m";
187
- const accessToken = (0, jsonwebtoken_1.sign)({ sub: user.id, email: user.email, roles }, this.options.jwtSecret, { expiresIn: accessTokenExpiresIn });
217
+ const accessToken = (0, jsonwebtoken_1.sign)({ sub: appUser.id, email: appUser.email, roles }, this.options.jwtSecret, { expiresIn: accessTokenExpiresIn });
188
218
  const refreshToken = (0, crypto_1.randomBytes)(REFRESH_TOKEN_BYTES).toString("hex");
189
219
  const refreshTokenHash = await (0, bcryptjs_1.hash)(refreshToken, PASSWORD_ROUNDS);
190
220
  const refreshTokenExpiresAt = new Date(Date.now() +
191
221
  (this.options.refreshTokenExpiresInDays ?? 30) * 24 * 60 * 60 * 1000);
192
222
  await this.refreshTokenRepo.save(this.refreshTokenRepo.create({
193
223
  id: (0, crypto_1.randomUUID)(),
194
- userId: user.id,
224
+ userId: appUser.id,
195
225
  tokenHash: refreshTokenHash,
196
226
  expiresAt: refreshTokenExpiresAt,
197
227
  revokedAt: null,
@@ -201,12 +231,12 @@ let SecurityAuthService = class SecurityAuthService {
201
231
  accessTokenExpiresIn,
202
232
  refreshToken,
203
233
  refreshTokenExpiresAt,
204
- user: await this.toSafeUser(user),
234
+ user: await this.toSafeUser(appUser, securityUser),
205
235
  };
206
236
  }
207
237
  async createEmailVerificationToken(userId) {
208
238
  const token = (0, crypto_1.randomBytes)(EMAIL_TOKEN_BYTES).toString("hex");
209
- await this.usersRepo.update({ id: userId }, { emailVerificationToken: token });
239
+ await this.securityUsersRepo.update({ userId }, { emailVerificationToken: token });
210
240
  return token;
211
241
  }
212
242
  async findValidRefreshToken(token, onlyUnexpired = true) {
@@ -236,18 +266,16 @@ let SecurityAuthService = class SecurityAuthService {
236
266
  const roles = await this.rolesRepo.find({ where: { id: (0, typeorm_2.In)(roleIds) } });
237
267
  return roles.map((role) => (0, roles_1.normalizeRoleName)(role.roleKey)).sort();
238
268
  }
239
- async toSafeUser(user) {
269
+ async toSafeUser(appUser, securityUser) {
240
270
  return {
241
- id: user.id,
242
- email: user.email,
243
- firstName: user.firstName,
244
- lastName: user.lastName,
271
+ id: appUser.id,
272
+ email: appUser.email,
245
273
  phone: null,
246
- roles: await this.getUserRoleKeys(user.id),
247
- emailVerifiedAt: user.emailVerifiedAt,
274
+ roles: await this.getUserRoleKeys(appUser.id),
275
+ emailVerifiedAt: securityUser.emailVerifiedAt,
248
276
  phoneVerifiedAt: null,
249
- adminApprovedAt: user.adminApprovedAt,
250
- isActive: user.isActive,
277
+ adminApprovedAt: securityUser.adminApprovedAt,
278
+ isActive: securityUser.isActive,
251
279
  };
252
280
  }
253
281
  };
@@ -255,15 +283,17 @@ exports.SecurityAuthService = SecurityAuthService;
255
283
  exports.SecurityAuthService = SecurityAuthService = __decorate([
256
284
  (0, common_1.Injectable)(),
257
285
  __param(0, (0, typeorm_1.InjectRepository)(app_user_entity_1.AppUserEntity)),
258
- __param(1, (0, typeorm_1.InjectRepository)(refresh_token_entity_1.RefreshTokenEntity)),
259
- __param(2, (0, typeorm_1.InjectRepository)(password_reset_token_entity_1.PasswordResetTokenEntity)),
260
- __param(3, (0, typeorm_1.InjectRepository)(security_role_entity_1.SecurityRoleEntity)),
261
- __param(4, (0, typeorm_1.InjectRepository)(security_user_role_entity_1.SecurityUserRoleEntity)),
262
- __param(5, (0, common_1.Inject)(security_auth_constants_1.SECURITY_AUTH_OPTIONS)),
263
- __param(6, (0, common_1.Inject)(tokens_1.SECURITY_WORKFLOW_NOTIFIER)),
286
+ __param(1, (0, typeorm_1.InjectRepository)(security_user_entity_1.SecurityUserEntity)),
287
+ __param(2, (0, typeorm_1.InjectRepository)(refresh_token_entity_1.RefreshTokenEntity)),
288
+ __param(3, (0, typeorm_1.InjectRepository)(password_reset_token_entity_1.PasswordResetTokenEntity)),
289
+ __param(4, (0, typeorm_1.InjectRepository)(security_role_entity_1.SecurityRoleEntity)),
290
+ __param(5, (0, typeorm_1.InjectRepository)(security_user_role_entity_1.SecurityUserRoleEntity)),
291
+ __param(6, (0, common_1.Inject)(security_auth_constants_1.SECURITY_AUTH_OPTIONS)),
292
+ __param(7, (0, common_1.Inject)(tokens_1.SECURITY_WORKFLOW_NOTIFIER)),
264
293
  __metadata("design:paramtypes", [typeorm_2.Repository,
265
294
  typeorm_2.Repository,
266
295
  typeorm_2.Repository,
267
296
  typeorm_2.Repository,
297
+ typeorm_2.Repository,
268
298
  typeorm_2.Repository, Object, Object])
269
299
  ], SecurityAuthService);