@flusys/nestjs-auth 6.0.2 → 6.1.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.
Files changed (71) hide show
  1. package/cjs/controllers/authentication.controller.spec.js +219 -0
  2. package/cjs/controllers/branch.controller.spec.js +134 -0
  3. package/cjs/controllers/company-selection.controller.spec.js +84 -0
  4. package/cjs/controllers/company.controller.spec.js +131 -0
  5. package/cjs/controllers/email-verification.controller.spec.js +142 -0
  6. package/cjs/controllers/user-permission.controller.spec.js +138 -0
  7. package/cjs/controllers/user.controller.spec.js +204 -0
  8. package/cjs/docs/auth-swagger.config.spec.js +130 -0
  9. package/cjs/entities/index.spec.js +73 -0
  10. package/cjs/helpers/auth-response.mapper.js +46 -0
  11. package/cjs/helpers/auth-response.mapper.spec.js +139 -0
  12. package/cjs/helpers/index.js +19 -0
  13. package/cjs/helpers/token.helper.js +58 -0
  14. package/cjs/helpers/token.helper.spec.js +86 -0
  15. package/cjs/index.js +1 -0
  16. package/cjs/interceptors/clear-token.interceptor.spec.js +107 -0
  17. package/cjs/interceptors/set-token.interceptor.spec.js +165 -0
  18. package/cjs/modules/auth.module.spec.js +243 -0
  19. package/cjs/services/auth-config.service.spec.js +97 -0
  20. package/cjs/services/auth-datasource.provider.spec.js +161 -0
  21. package/cjs/services/auth-email.service.spec.js +404 -0
  22. package/cjs/services/authentication.service.js +37 -109
  23. package/cjs/services/authentication.service.spec.js +904 -0
  24. package/cjs/services/branch.service.spec.js +154 -0
  25. package/cjs/services/company-selection-session.service.spec.js +90 -0
  26. package/cjs/services/company.service.spec.js +113 -0
  27. package/cjs/services/user-permission.service.spec.js +202 -0
  28. package/cjs/services/user.service.spec.js +704 -0
  29. package/cjs/strategies/jwt.strategy.js +1 -1
  30. package/cjs/strategies/jwt.strategy.spec.js +166 -0
  31. package/cjs/validators/password.validator.spec.js +161 -0
  32. package/entities/pending-registration.entity.d.ts +2 -7
  33. package/fesm/controllers/authentication.controller.spec.js +215 -0
  34. package/fesm/controllers/branch.controller.spec.js +130 -0
  35. package/fesm/controllers/company-selection.controller.spec.js +80 -0
  36. package/fesm/controllers/company.controller.spec.js +127 -0
  37. package/fesm/controllers/email-verification.controller.spec.js +138 -0
  38. package/fesm/controllers/user-permission.controller.spec.js +134 -0
  39. package/fesm/controllers/user.controller.spec.js +200 -0
  40. package/fesm/docs/auth-swagger.config.spec.js +126 -0
  41. package/fesm/entities/index.spec.js +69 -0
  42. package/fesm/helpers/auth-response.mapper.js +25 -0
  43. package/fesm/helpers/auth-response.mapper.spec.js +135 -0
  44. package/fesm/helpers/index.js +2 -0
  45. package/fesm/helpers/token.helper.js +40 -0
  46. package/fesm/helpers/token.helper.spec.js +82 -0
  47. package/fesm/index.js +1 -0
  48. package/fesm/interceptors/clear-token.interceptor.spec.js +103 -0
  49. package/fesm/interceptors/set-token.interceptor.spec.js +161 -0
  50. package/fesm/interfaces/authentication.interface.js +1 -1
  51. package/fesm/modules/auth.module.spec.js +239 -0
  52. package/fesm/services/auth-config.service.spec.js +93 -0
  53. package/fesm/services/auth-datasource.provider.spec.js +157 -0
  54. package/fesm/services/auth-email.service.spec.js +359 -0
  55. package/fesm/services/authentication.service.js +37 -109
  56. package/fesm/services/authentication.service.spec.js +859 -0
  57. package/fesm/services/branch.service.spec.js +150 -0
  58. package/fesm/services/company-selection-session.service.spec.js +86 -0
  59. package/fesm/services/company.service.spec.js +109 -0
  60. package/fesm/services/user-permission.service.spec.js +198 -0
  61. package/fesm/services/user.service.spec.js +659 -0
  62. package/fesm/strategies/jwt.strategy.js +1 -1
  63. package/fesm/strategies/jwt.strategy.spec.js +162 -0
  64. package/fesm/validators/password.validator.spec.js +157 -0
  65. package/helpers/auth-response.mapper.d.ts +22 -0
  66. package/helpers/index.d.ts +2 -0
  67. package/helpers/token.helper.d.ts +8 -0
  68. package/index.d.ts +1 -0
  69. package/interfaces/authentication.interface.d.ts +7 -0
  70. package/package.json +8 -3
  71. package/services/authentication.service.d.ts +1 -8
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _common = require("@nestjs/common");
6
+ const _emailverificationcontroller = require("./email-verification.controller");
7
+ function buildRequest() {
8
+ return {
9
+ headers: {},
10
+ get: jest.fn((h)=>h === 'host' ? 'app.example.com' : undefined),
11
+ protocol: 'https'
12
+ };
13
+ }
14
+ describe('EmailVerificationController', ()=>{
15
+ let controller;
16
+ let mockAuthService;
17
+ let mockAuthEmailService;
18
+ let mockAuthConfig;
19
+ let mockDataSourceProvider;
20
+ beforeEach(()=>{
21
+ mockAuthService = {
22
+ createUserFromPendingRegistration: jest.fn()
23
+ };
24
+ mockAuthEmailService = {
25
+ forgotPassword: jest.fn(),
26
+ resetPassword: jest.fn(),
27
+ resendVerificationEmail: jest.fn(),
28
+ verifyEmail: jest.fn()
29
+ };
30
+ mockAuthConfig = {};
31
+ mockDataSourceProvider = {
32
+ isEmailVerificationEnabled: jest.fn().mockReturnValue(true)
33
+ };
34
+ controller = new _emailverificationcontroller.EmailVerificationController(mockAuthService, mockAuthEmailService, mockAuthConfig, mockDataSourceProvider);
35
+ });
36
+ describe('when email verification is disabled for the tenant', ()=>{
37
+ beforeEach(()=>{
38
+ mockDataSourceProvider.isEmailVerificationEnabled.mockReturnValue(false);
39
+ });
40
+ it('rejects forgotPassword', async ()=>{
41
+ await expect(controller.forgotPassword(buildRequest(), {
42
+ email: 'a@example.com'
43
+ })).rejects.toThrow(_common.BadRequestException);
44
+ });
45
+ it('rejects resetPassword', async ()=>{
46
+ await expect(controller.resetPassword({
47
+ token: 't',
48
+ newPassword: 'New1!aaaa'
49
+ })).rejects.toThrow(_common.BadRequestException);
50
+ });
51
+ it('rejects resendVerification', async ()=>{
52
+ await expect(controller.resendVerification(buildRequest(), {
53
+ email: 'a@example.com'
54
+ })).rejects.toThrow(_common.BadRequestException);
55
+ });
56
+ it('rejects verifyEmail', async ()=>{
57
+ await expect(controller.verifyEmail({
58
+ token: 't'
59
+ })).rejects.toThrow(_common.BadRequestException);
60
+ });
61
+ });
62
+ describe('forgotPassword', ()=>{
63
+ it('delegates to authEmailService with a built frontend reset URL', async ()=>{
64
+ mockAuthEmailService.forgotPassword.mockResolvedValue({
65
+ success: true,
66
+ message: 'sent',
67
+ messageKey: 'auth.password.reset.email.sent'
68
+ });
69
+ const result = await controller.forgotPassword(buildRequest(), {
70
+ email: 'a@example.com'
71
+ });
72
+ expect(mockAuthEmailService.forgotPassword).toHaveBeenCalledWith('a@example.com', expect.any(String));
73
+ expect(result.success).toBe(true);
74
+ });
75
+ });
76
+ describe('resetPassword', ()=>{
77
+ it('delegates to authEmailService.resetPassword', async ()=>{
78
+ mockAuthEmailService.resetPassword.mockResolvedValue({
79
+ success: true,
80
+ message: 'done',
81
+ messageKey: 'auth.password.reset.success'
82
+ });
83
+ const result = await controller.resetPassword({
84
+ token: 'tok',
85
+ newPassword: 'New1!aaaa'
86
+ });
87
+ expect(mockAuthEmailService.resetPassword).toHaveBeenCalledWith('tok', 'New1!aaaa');
88
+ expect(result.success).toBe(true);
89
+ });
90
+ });
91
+ describe('resendVerification', ()=>{
92
+ it('delegates to authEmailService.resendVerificationEmail', async ()=>{
93
+ mockAuthEmailService.resendVerificationEmail.mockResolvedValue({
94
+ success: true,
95
+ message: 'sent',
96
+ messageKey: 'email.verification.resend.success'
97
+ });
98
+ await controller.resendVerification(buildRequest(), {
99
+ email: 'a@example.com'
100
+ });
101
+ expect(mockAuthEmailService.resendVerificationEmail).toHaveBeenCalledWith('a@example.com', expect.any(String));
102
+ });
103
+ });
104
+ describe('verifyEmail', ()=>{
105
+ it('completes registration when the token resolves a pending registration', async ()=>{
106
+ mockAuthEmailService.verifyEmail.mockResolvedValue({
107
+ type: 'pending',
108
+ pending: {
109
+ id: 'pending-1'
110
+ }
111
+ });
112
+ mockAuthService.createUserFromPendingRegistration.mockResolvedValue({
113
+ accessToken: 'a'
114
+ });
115
+ const result = await controller.verifyEmail({
116
+ token: 'tok'
117
+ });
118
+ expect(mockAuthService.createUserFromPendingRegistration).toHaveBeenCalledWith({
119
+ id: 'pending-1'
120
+ });
121
+ expect(result.data).toEqual({
122
+ accessToken: 'a'
123
+ });
124
+ });
125
+ it('returns the verification message when the token verifies an existing user token', async ()=>{
126
+ mockAuthEmailService.verifyEmail.mockResolvedValue({
127
+ type: 'verified',
128
+ message: 'Email has been verified successfully.',
129
+ messageKey: 'email.verification.success'
130
+ });
131
+ const result = await controller.verifyEmail({
132
+ token: 'tok'
133
+ });
134
+ expect(result).toEqual({
135
+ success: true,
136
+ message: 'Email has been verified successfully.',
137
+ messageKey: 'email.verification.success'
138
+ });
139
+ expect(mockAuthService.createUserFromPendingRegistration).not.toHaveBeenCalled();
140
+ });
141
+ });
142
+ });
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _userpermissioncontroller = require("./user-permission.controller");
6
+ const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
7
+ describe('UserPermissionController', ()=>{
8
+ let controller;
9
+ let mockPermissionService;
10
+ beforeEach(()=>{
11
+ mockPermissionService = {
12
+ findUserCompanies: jest.fn(),
13
+ findUserBranches: jest.fn(),
14
+ assignPermission: jest.fn(),
15
+ revokePermission: jest.fn()
16
+ };
17
+ controller = new _userpermissioncontroller.UserPermissionController(mockPermissionService);
18
+ });
19
+ describe('assignUserCompany', ()=>{
20
+ it('assigns and revokes company permissions in a single batch', async ()=>{
21
+ const result = await controller.assignUserCompany({
22
+ userId: 'user-1',
23
+ items: [
24
+ {
25
+ targetId: 'company-1',
26
+ isAdd: true
27
+ },
28
+ {
29
+ targetId: 'company-2',
30
+ isAdd: false
31
+ }
32
+ ]
33
+ });
34
+ expect(mockPermissionService.assignPermission).toHaveBeenCalledWith('user-1', 'company-1', _usercompanypermissionentity.PermissionType.COMPANY);
35
+ expect(mockPermissionService.revokePermission).toHaveBeenCalledWith('user-1', 'company-2', _usercompanypermissionentity.PermissionType.COMPANY);
36
+ expect(result.messageVariables).toEqual({
37
+ added: 1,
38
+ removed: 1
39
+ });
40
+ });
41
+ });
42
+ describe('getUserCompanies', ()=>{
43
+ it('maps permission entities to the response DTO shape', async ()=>{
44
+ mockPermissionService.findUserCompanies.mockResolvedValue([
45
+ {
46
+ id: 'perm-1',
47
+ userId: 'user-1',
48
+ targetId: 'company-1',
49
+ company: {
50
+ id: 'company-1',
51
+ name: 'Acme',
52
+ slug: 'acme'
53
+ }
54
+ }
55
+ ]);
56
+ const result = await controller.getUserCompanies('user-1');
57
+ expect(result.data).toEqual([
58
+ {
59
+ id: 'perm-1',
60
+ userId: 'user-1',
61
+ companyId: 'company-1',
62
+ companyName: 'Acme',
63
+ companySlug: 'acme'
64
+ }
65
+ ]);
66
+ });
67
+ it('falls back to targetId and empty strings when the company relation is missing', async ()=>{
68
+ mockPermissionService.findUserCompanies.mockResolvedValue([
69
+ {
70
+ id: 'perm-1',
71
+ userId: 'user-1',
72
+ targetId: 'company-1',
73
+ company: undefined
74
+ }
75
+ ]);
76
+ const result = await controller.getUserCompanies('user-1');
77
+ expect(result.data[0]).toEqual({
78
+ id: 'perm-1',
79
+ userId: 'user-1',
80
+ companyId: 'company-1',
81
+ companyName: '',
82
+ companySlug: ''
83
+ });
84
+ });
85
+ });
86
+ describe('assignUserBranch', ()=>{
87
+ it('assigns and revokes branch permissions in a single batch', async ()=>{
88
+ const result = await controller.assignUserBranch({
89
+ userId: 'user-1',
90
+ items: [
91
+ {
92
+ targetId: 'branch-1',
93
+ isAdd: true
94
+ }
95
+ ]
96
+ });
97
+ expect(mockPermissionService.assignPermission).toHaveBeenCalledWith('user-1', 'branch-1', _usercompanypermissionentity.PermissionType.BRANCH);
98
+ expect(result.messageVariables).toEqual({
99
+ added: 1,
100
+ removed: 0
101
+ });
102
+ });
103
+ });
104
+ describe('getUserBranches', ()=>{
105
+ it('maps permission entities to the response DTO shape', async ()=>{
106
+ mockPermissionService.findUserBranches.mockResolvedValue([
107
+ {
108
+ id: 'perm-1',
109
+ userId: 'user-1',
110
+ targetId: 'branch-1',
111
+ branch: {
112
+ id: 'branch-1',
113
+ name: 'Main',
114
+ slug: 'main',
115
+ companyId: 'company-1'
116
+ }
117
+ }
118
+ ]);
119
+ const result = await controller.getUserBranches('user-1', 'company-1');
120
+ expect(mockPermissionService.findUserBranches).toHaveBeenCalledWith('user-1', 'company-1');
121
+ expect(result.data).toEqual([
122
+ {
123
+ id: 'perm-1',
124
+ userId: 'user-1',
125
+ branchId: 'branch-1',
126
+ branchName: 'Main',
127
+ branchSlug: 'main',
128
+ companyId: 'company-1'
129
+ }
130
+ ]);
131
+ });
132
+ it('supports an optional companyId filter', async ()=>{
133
+ mockPermissionService.findUserBranches.mockResolvedValue([]);
134
+ await controller.getUserBranches('user-1');
135
+ expect(mockPermissionService.findUserBranches).toHaveBeenCalledWith('user-1', undefined);
136
+ });
137
+ });
138
+ });
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
6
+ const _usercontroller = require("./user.controller");
7
+ function buildUser(overrides = {}) {
8
+ return {
9
+ id: 'user-1',
10
+ name: 'Test User',
11
+ email: 'test@example.com',
12
+ phone: null,
13
+ isActive: true,
14
+ readOnly: false,
15
+ createdAt: new Date(),
16
+ updatedAt: new Date(),
17
+ ...overrides
18
+ };
19
+ }
20
+ describe('UserController', ()=>{
21
+ let controller;
22
+ let mockUserService;
23
+ beforeEach(()=>{
24
+ mockUserService = {
25
+ insert: jest.fn(),
26
+ insertMany: jest.fn(),
27
+ findById: jest.fn(),
28
+ findByIds: jest.fn(),
29
+ update: jest.fn(),
30
+ updateMany: jest.fn(),
31
+ bulkUpsert: jest.fn(),
32
+ getAll: jest.fn(),
33
+ delete: jest.fn(),
34
+ getProfileWithExtras: jest.fn(),
35
+ verifyEmail: jest.fn(),
36
+ verifyPhone: jest.fn(),
37
+ updateStatus: jest.fn(),
38
+ profile: jest.fn(),
39
+ getProfileSections: jest.fn(),
40
+ getProfileSectionData: jest.fn(),
41
+ updateProfileSection: jest.fn(),
42
+ getProfileCompletion: jest.fn()
43
+ };
44
+ controller = new _usercontroller.UserController(mockUserService);
45
+ });
46
+ describe('insert', ()=>{
47
+ it('creates a user and returns the mapped response', async ()=>{
48
+ const user = (0, _loggedusermock.buildMockUser)();
49
+ mockUserService.insert.mockResolvedValue(buildUser());
50
+ const result = await controller.insert({
51
+ name: 'Test User',
52
+ email: 'test@example.com',
53
+ password: 'Password1!'
54
+ }, user);
55
+ expect(mockUserService.insert).toHaveBeenCalledWith({
56
+ name: 'Test User',
57
+ email: 'test@example.com',
58
+ password: 'Password1!'
59
+ }, user);
60
+ expect(result.success).toBe(true);
61
+ expect(result.data).toEqual(expect.objectContaining({
62
+ id: 'user-1'
63
+ }));
64
+ });
65
+ });
66
+ describe('getAll', ()=>{
67
+ it('paginates users and maps the response list', async ()=>{
68
+ mockUserService.getAll.mockResolvedValue({
69
+ data: [
70
+ buildUser()
71
+ ],
72
+ total: 1
73
+ });
74
+ const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
75
+ expect(mockUserService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
76
+ expect(result.data).toHaveLength(1);
77
+ });
78
+ });
79
+ describe('getProfileWithExtras', ()=>{
80
+ it('returns the enriched profile payload', async ()=>{
81
+ const user = (0, _loggedusermock.buildMockUser)();
82
+ mockUserService.getProfileWithExtras.mockResolvedValue({
83
+ ...buildUser(),
84
+ completionPercentage: 80
85
+ });
86
+ const result = await controller.getProfileWithExtras('user-1', user);
87
+ expect(mockUserService.getProfileWithExtras).toHaveBeenCalledWith('user-1', user);
88
+ expect(result).toEqual({
89
+ success: true,
90
+ message: 'Profile extras retrieved successfully',
91
+ messageKey: expect.any(String),
92
+ data: expect.objectContaining({
93
+ completionPercentage: 80
94
+ })
95
+ });
96
+ });
97
+ });
98
+ describe('verifyEmail', ()=>{
99
+ it('verifies the email and returns a success message', async ()=>{
100
+ mockUserService.verifyEmail.mockResolvedValue(undefined);
101
+ const result = await controller.verifyEmail('user-1');
102
+ expect(mockUserService.verifyEmail).toHaveBeenCalledWith('user-1');
103
+ expect(result.success).toBe(true);
104
+ });
105
+ });
106
+ describe('verifyPhone', ()=>{
107
+ it('verifies the phone and returns a success message', async ()=>{
108
+ mockUserService.verifyPhone.mockResolvedValue(undefined);
109
+ const result = await controller.verifyPhone('user-1');
110
+ expect(mockUserService.verifyPhone).toHaveBeenCalledWith('user-1');
111
+ expect(result.success).toBe(true);
112
+ });
113
+ });
114
+ describe('updateStatus', ()=>{
115
+ it('updates the active status for the given user', async ()=>{
116
+ const user = (0, _loggedusermock.buildMockUser)();
117
+ mockUserService.updateStatus.mockResolvedValue(undefined);
118
+ const result = await controller.updateStatus('user-1', false, user);
119
+ expect(mockUserService.updateStatus).toHaveBeenCalledWith('user-1', false, user);
120
+ expect(result.success).toBe(true);
121
+ });
122
+ });
123
+ describe('profile', ()=>{
124
+ it('updates the current user profile and returns the data', async ()=>{
125
+ const user = (0, _loggedusermock.buildMockUser)();
126
+ mockUserService.profile.mockResolvedValue('user-1');
127
+ const result = await controller.profile({
128
+ id: 'user-1',
129
+ name: 'New Name'
130
+ }, user);
131
+ expect(mockUserService.profile).toHaveBeenCalledWith({
132
+ id: 'user-1',
133
+ name: 'New Name'
134
+ }, user);
135
+ expect(result).toEqual({
136
+ success: true,
137
+ message: 'Profile updated successfully',
138
+ messageKey: expect.any(String),
139
+ data: 'user-1'
140
+ });
141
+ });
142
+ });
143
+ describe('getProfileSections', ()=>{
144
+ it('returns the profile section definitions', async ()=>{
145
+ mockUserService.getProfileSections.mockResolvedValue([
146
+ {
147
+ id: 's1',
148
+ name: 'Basic',
149
+ order: 1
150
+ }
151
+ ]);
152
+ const result = await controller.getProfileSections();
153
+ expect(result.data).toEqual([
154
+ {
155
+ id: 's1',
156
+ name: 'Basic',
157
+ order: 1
158
+ }
159
+ ]);
160
+ });
161
+ });
162
+ describe('getProfileSectionData', ()=>{
163
+ it('returns data for the requested section', async ()=>{
164
+ const user = (0, _loggedusermock.buildMockUser)();
165
+ mockUserService.getProfileSectionData.mockResolvedValue({
166
+ sectionId: 's1',
167
+ data: {
168
+ foo: 'bar'
169
+ },
170
+ isComplete: true
171
+ });
172
+ const result = await controller.getProfileSectionData('user-1', 's1', user);
173
+ expect(mockUserService.getProfileSectionData).toHaveBeenCalledWith('user-1', 's1', user);
174
+ expect(result.data).toEqual(expect.objectContaining({
175
+ sectionId: 's1',
176
+ isComplete: true
177
+ }));
178
+ });
179
+ });
180
+ describe('updateProfileSection', ()=>{
181
+ it('updates the requested section', async ()=>{
182
+ const user = (0, _loggedusermock.buildMockUser)();
183
+ mockUserService.updateProfileSection.mockResolvedValue(undefined);
184
+ const result = await controller.updateProfileSection('user-1', 's1', {
185
+ foo: 'bar'
186
+ }, user);
187
+ expect(mockUserService.updateProfileSection).toHaveBeenCalledWith('user-1', 's1', {
188
+ foo: 'bar'
189
+ }, user);
190
+ expect(result.success).toBe(true);
191
+ });
192
+ });
193
+ describe('getProfileCompletion', ()=>{
194
+ it('returns the completion percentage', async ()=>{
195
+ const user = (0, _loggedusermock.buildMockUser)();
196
+ mockUserService.getProfileCompletion.mockResolvedValue(42);
197
+ const result = await controller.getProfileCompletion('user-1', user);
198
+ expect(mockUserService.getProfileCompletion).toHaveBeenCalledWith('user-1', user);
199
+ expect(result.data).toEqual({
200
+ completionPercentage: 42
201
+ });
202
+ });
203
+ });
204
+ });
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _authswaggerconfig = require("./auth-swagger.config");
6
+ describe('authSwaggerConfig', ()=>{
7
+ it('should default to both features enabled and single-database mode when no config is given', ()=>{
8
+ const config = (0, _authswaggerconfig.authSwaggerConfig)();
9
+ expect(config.title).toBe('Auth API');
10
+ expect(config.path).toBe('api/docs/auth');
11
+ expect(config.bearerAuth).toBe(true);
12
+ expect(config.excludeTags).toEqual([]);
13
+ expect(config.excludeSchemaProperties).toBeUndefined();
14
+ expect(config.excludeExamples).toBeUndefined();
15
+ expect(config.excludePaths).toBeUndefined();
16
+ expect(config.description).not.toContain('Multi-Tenant Mode');
17
+ });
18
+ it('should exclude company-related tags, schema properties, and examples when the company feature is off', ()=>{
19
+ const config = (0, _authswaggerconfig.authSwaggerConfig)({
20
+ enableCompanyFeature: false,
21
+ databaseMode: 'single'
22
+ });
23
+ expect(config.excludeTags).toEqual(expect.arrayContaining([
24
+ 'Companies',
25
+ 'Branches',
26
+ 'User Permissions',
27
+ 'Company Selection'
28
+ ]));
29
+ expect(config.excludeSchemaProperties).toEqual(expect.arrayContaining([
30
+ expect.objectContaining({
31
+ schemaName: 'RegistrationDto'
32
+ })
33
+ ]));
34
+ expect(config.excludeExamples).toEqual(expect.arrayContaining([
35
+ expect.objectContaining({
36
+ pathPattern: '/auth/login',
37
+ examples: [
38
+ 'loginSuccessWithCompany',
39
+ 'companySelection'
40
+ ]
41
+ })
42
+ ]));
43
+ // Email verification is still enabled by default, so its paths must not be excluded
44
+ expect(config.excludePaths).toBeUndefined();
45
+ });
46
+ it('should exclude email-verification paths, schema properties, and examples when disabled', ()=>{
47
+ const config = (0, _authswaggerconfig.authSwaggerConfig)({
48
+ enableEmailVerification: false
49
+ });
50
+ expect(config.excludePaths).toEqual([
51
+ '/auth/forgot-password',
52
+ '/auth/reset-password',
53
+ '/auth/resend-verification',
54
+ '/auth/verify-email'
55
+ ]);
56
+ expect(config.excludeSchemaProperties).toEqual(expect.arrayContaining([
57
+ expect.objectContaining({
58
+ schemaName: 'LoginResponseRequiresEmailVerificationDto'
59
+ })
60
+ ]));
61
+ expect(config.excludeExamples).toEqual(expect.arrayContaining([
62
+ expect.objectContaining({
63
+ pathPattern: '/auth/login',
64
+ examples: [
65
+ 'emailVerification'
66
+ ]
67
+ })
68
+ ]));
69
+ // Company feature is still enabled by default, so its tags must not be excluded
70
+ expect(config.excludeTags).toEqual([]);
71
+ });
72
+ it('should merge exclusions from both features when both are disabled', ()=>{
73
+ const config = (0, _authswaggerconfig.authSwaggerConfig)({
74
+ enableCompanyFeature: false,
75
+ enableEmailVerification: false
76
+ });
77
+ expect(config.excludeTags?.length).toBeGreaterThan(0);
78
+ expect(config.excludePaths?.length).toBeGreaterThan(0);
79
+ // Both feature's schema exclusions should be present together
80
+ const schemaNames = config.excludeSchemaProperties?.map((e)=>e.schemaName) ?? [];
81
+ expect(schemaNames).toContain('RegistrationDto');
82
+ expect(schemaNames).toContain('LoginResponseRequiresEmailVerificationDto');
83
+ // Both feature's example exclusions merge onto the same /auth/login path
84
+ const loginExclusions = config.excludeExamples?.filter((e)=>e.pathPattern === '/auth/login');
85
+ expect(loginExclusions).toHaveLength(2);
86
+ });
87
+ it('should mention multi-tenant mode in the description only for multi-tenant database mode', ()=>{
88
+ const multiTenant = (0, _authswaggerconfig.authSwaggerConfig)({
89
+ databaseMode: 'multi-tenant'
90
+ });
91
+ const single = (0, _authswaggerconfig.authSwaggerConfig)({
92
+ databaseMode: 'single'
93
+ });
94
+ expect(multiTenant.description).toContain('Multi-Tenant Mode');
95
+ expect(single.description).not.toContain('Multi-Tenant Mode');
96
+ });
97
+ it('should describe the multi-company login flow only when the company feature is enabled', ()=>{
98
+ const withCompany = (0, _authswaggerconfig.authSwaggerConfig)({
99
+ enableCompanyFeature: true
100
+ });
101
+ const withoutCompany = (0, _authswaggerconfig.authSwaggerConfig)({
102
+ enableCompanyFeature: false
103
+ });
104
+ expect(withCompany.description).toContain('Multi-Company Login');
105
+ expect(withCompany.description).toContain('/auth/switch-company');
106
+ expect(withoutCompany.description).not.toContain('Multi-Company Login');
107
+ expect(withoutCompany.description).not.toContain('/auth/switch-company');
108
+ });
109
+ it('should describe email verification endpoints only when enabled', ()=>{
110
+ const withVerification = (0, _authswaggerconfig.authSwaggerConfig)({
111
+ enableEmailVerification: true
112
+ });
113
+ const withoutVerification = (0, _authswaggerconfig.authSwaggerConfig)({
114
+ enableEmailVerification: false
115
+ });
116
+ expect(withVerification.description).toContain('/auth/forgot-password');
117
+ expect(withoutVerification.description).not.toContain('### Email Verification Endpoints');
118
+ });
119
+ it('should list company administration endpoints only when the company feature is enabled', ()=>{
120
+ const withCompany = (0, _authswaggerconfig.authSwaggerConfig)({
121
+ enableCompanyFeature: true
122
+ });
123
+ const withoutCompany = (0, _authswaggerconfig.authSwaggerConfig)({
124
+ enableCompanyFeature: false
125
+ });
126
+ expect(withCompany.description).toContain('/administration/company/*');
127
+ expect(withoutCompany.description).not.toContain('/administration/company/*');
128
+ expect(withoutCompany.description).toContain('/administration/users/*');
129
+ });
130
+ });
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _index = require("./index");
6
+ const _appuserentity = require("./app-user.entity");
7
+ const _usertokenentity = require("./user-token.entity");
8
+ const _pendingregistrationentity = require("./pending-registration.entity");
9
+ const _companyentity = require("./company.entity");
10
+ const _companybranchentity = require("./company-branch.entity");
11
+ const _usercompanypermissionentity = require("./user-company-permission.entity");
12
+ describe('getAuthEntitiesByConfig', ()=>{
13
+ it('should always include the base entities', ()=>{
14
+ const entities = (0, _index.getAuthEntitiesByConfig)({
15
+ enableCompanyFeature: false,
16
+ enableEmailVerification: false
17
+ });
18
+ expect(entities).toEqual(expect.arrayContaining([
19
+ _appuserentity.AppUser,
20
+ _usertokenentity.UserToken
21
+ ]));
22
+ });
23
+ it('should include PendingRegistration when email verification is enabled', ()=>{
24
+ const entities = (0, _index.getAuthEntitiesByConfig)({
25
+ enableEmailVerification: true
26
+ });
27
+ expect(entities).toContain(_pendingregistrationentity.PendingRegistration);
28
+ });
29
+ it('should exclude PendingRegistration when email verification is disabled', ()=>{
30
+ const entities = (0, _index.getAuthEntitiesByConfig)({
31
+ enableEmailVerification: false
32
+ });
33
+ expect(entities).not.toContain(_pendingregistrationentity.PendingRegistration);
34
+ });
35
+ it('should include company entities when the company feature is enabled', ()=>{
36
+ const entities = (0, _index.getAuthEntitiesByConfig)({
37
+ enableCompanyFeature: true
38
+ });
39
+ expect(entities).toEqual(expect.arrayContaining([
40
+ _companyentity.Company,
41
+ _companybranchentity.CompanyBranch,
42
+ _usercompanypermissionentity.UserCompanyPermission
43
+ ]));
44
+ });
45
+ it('should exclude company entities when the company feature is disabled', ()=>{
46
+ const entities = (0, _index.getAuthEntitiesByConfig)({
47
+ enableCompanyFeature: false
48
+ });
49
+ expect(entities).not.toEqual(expect.arrayContaining([
50
+ _companyentity.Company
51
+ ]));
52
+ });
53
+ it('should default enableEmailVerification to true and enableCompanyFeature to false when omitted', ()=>{
54
+ const entities = (0, _index.getAuthEntitiesByConfig)({});
55
+ expect(entities).toContain(_pendingregistrationentity.PendingRegistration);
56
+ expect(entities).not.toContain(_companyentity.Company);
57
+ });
58
+ it('should include every entity group when both features are enabled', ()=>{
59
+ const entities = (0, _index.getAuthEntitiesByConfig)({
60
+ enableCompanyFeature: true,
61
+ enableEmailVerification: true
62
+ });
63
+ expect(entities).toHaveLength(6);
64
+ expect(entities).toEqual(expect.arrayContaining([
65
+ _appuserentity.AppUser,
66
+ _usertokenentity.UserToken,
67
+ _pendingregistrationentity.PendingRegistration,
68
+ _companyentity.Company,
69
+ _companybranchentity.CompanyBranch,
70
+ _usercompanypermissionentity.UserCompanyPermission
71
+ ]));
72
+ });
73
+ });