@futdevpro/nts-dynamo 1.15.2 → 1.15.5

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 (192) hide show
  1. package/.cursor/rules/__assistant_guide.mdc +30 -0
  2. package/.cursor/rules/__main.mdc +64 -0
  3. package/.cursor/rules/_ag_backend-structure.mdc +86 -0
  4. package/.cursor/rules/_ag_backend.mdc +16 -0
  5. package/.cursor/rules/_ag_debug.mdc +8 -0
  6. package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -0
  7. package/.cursor/rules/_ag_file-refactoring.mdc +113 -0
  8. package/.cursor/rules/_ag_fixes_rules.mdc +6 -0
  9. package/.cursor/rules/_ag_frontend-structure.mdc +87 -0
  10. package/.cursor/rules/_ag_frontend.mdc +40 -0
  11. package/.cursor/rules/_ag_import-rules.mdc +45 -0
  12. package/.cursor/rules/_ag_naming.mdc +116 -0
  13. package/.cursor/rules/_ag_running_commands.mdc +5 -0
  14. package/.cursor/rules/_ag_server-controller.mdc +6 -0
  15. package/.cursor/rules/_ag_should-be.mdc +7 -0
  16. package/.cursor/rules/_ag_swearing.mdc +47 -0
  17. package/.cursor/rules/ai_development_guide.md +61 -0
  18. package/.cursor/rules/ai_directives.md +114 -0
  19. package/.cursor/rules/cursor-rules.md +160 -0
  20. package/.cursor/rules/default-command.mdc +465 -0
  21. package/.cursor/rules/error_code_pattern.md +40 -0
  22. package/.cursor/rules/saved rule mcp server use.md +16 -0
  23. package/_specifications/BACKLOG.md +15 -0
  24. package/_specifications/TODO.md +15 -0
  25. package/build/_modules/ai/_models/ai-test-generation-result.interface.d.ts +17 -0
  26. package/build/_modules/ai/_models/ai-test-generation-result.interface.d.ts.map +1 -0
  27. package/build/_modules/ai/_models/ai-test-generation-result.interface.js +3 -0
  28. package/build/_modules/ai/_models/ai-test-generation-result.interface.js.map +1 -0
  29. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.d.ts +36 -0
  30. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.d.ts.map +1 -0
  31. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.js +118 -0
  32. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.js.map +1 -0
  33. package/build/_modules/ai/_modules/anthropic/index.d.ts +3 -0
  34. package/build/_modules/ai/_modules/anthropic/index.d.ts.map +1 -0
  35. package/build/_modules/ai/_modules/anthropic/index.js +8 -0
  36. package/build/_modules/ai/_modules/anthropic/index.js.map +1 -0
  37. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.d.ts +35 -0
  38. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.d.ts.map +1 -0
  39. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.js +129 -0
  40. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.js.map +1 -0
  41. package/build/_modules/ai/_modules/fdp-ai/index.d.ts +3 -0
  42. package/build/_modules/ai/_modules/fdp-ai/index.d.ts.map +1 -0
  43. package/build/_modules/ai/_modules/fdp-ai/index.js +8 -0
  44. package/build/_modules/ai/_modules/fdp-ai/index.js.map +1 -0
  45. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.d.ts +40 -0
  46. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.d.ts.map +1 -0
  47. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.js +111 -0
  48. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.js.map +1 -0
  49. package/build/_modules/ai/_modules/open-ai/index.d.ts +1 -0
  50. package/build/_modules/ai/_modules/open-ai/index.d.ts.map +1 -1
  51. package/build/_modules/ai/_modules/open-ai/index.js +1 -0
  52. package/build/_modules/ai/_modules/open-ai/index.js.map +1 -1
  53. package/build/_modules/ai/_services/ai-user-key.service-base.d.ts +45 -0
  54. package/build/_modules/ai/_services/ai-user-key.service-base.d.ts.map +1 -0
  55. package/build/_modules/ai/_services/ai-user-key.service-base.js +15 -0
  56. package/build/_modules/ai/_services/ai-user-key.service-base.js.map +1 -0
  57. package/build/_modules/ai/index.d.ts +2 -0
  58. package/build/_modules/ai/index.d.ts.map +1 -1
  59. package/build/_modules/ai/index.js +2 -0
  60. package/build/_modules/ai/index.js.map +1 -1
  61. package/build/_modules/custom-data/custom-data.controller.d.ts.map +1 -1
  62. package/build/_modules/custom-data/custom-data.controller.js +1 -2
  63. package/build/_modules/custom-data/custom-data.controller.js.map +1 -1
  64. package/build/_modules/socket/app-extended.server.js +1 -1
  65. package/build/_modules/socket/app-extended.server.js.map +1 -1
  66. package/build/_services/base/data.service.d.ts +1 -1
  67. package/build/_services/base/data.service.js +1 -1
  68. package/build/_services/base/db.service.d.ts +1 -1
  69. package/build/_services/base/db.service.js +1 -1
  70. package/build/_services/core/api.service.d.ts.map +1 -1
  71. package/build/_services/core/api.service.js +1 -0
  72. package/build/_services/core/api.service.js.map +1 -1
  73. package/build/_services/core/auth.service.d.ts +2 -2
  74. package/build/_services/core/auth.service.js +1 -1
  75. package/build/_services/core/email.service.js +1 -1
  76. package/build/_services/core/email.service.js.map +1 -1
  77. package/build/_services/core/global.service.d.ts +1 -1
  78. package/build/_services/core/global.service.js +2 -2
  79. package/build/_services/core/global.service.js.map +1 -1
  80. package/build/_services/server/app.server.d.ts.map +1 -1
  81. package/build/_services/server/app.server.js +11 -1
  82. package/build/_services/server/app.server.js.map +1 -1
  83. package/package.json +18 -4
  84. package/scripts/run-coverage-tests.js +5 -1
  85. package/spec/support/helpers/spec-reporter-loader.js +359 -0
  86. package/spec/support/helpers/ts-node-helper.js +84 -0
  87. package/spec/support/jasmine.coverage.json +2 -1
  88. package/spec/support/jasmine.json +3 -3
  89. package/src/_collections/archive.util.spec.ts +36 -0
  90. package/src/_collections/get-environment-settings.util.spec.ts +210 -0
  91. package/src/_collections/star.controller.spec.ts +224 -0
  92. package/src/_models/control-models/api-call-params.control-model.spec.ts +62 -3
  93. package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -0
  94. package/src/_models/control-models/app-params.control-model.spec.ts +158 -2
  95. package/src/_models/control-models/endpoint-params.control-model.spec.ts +578 -0
  96. package/src/_modules/ai/_models/ai-test-generation-result.interface.ts +16 -0
  97. package/src/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.ts +138 -0
  98. package/src/_modules/ai/_modules/anthropic/index.ts +5 -0
  99. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -0
  100. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -0
  101. package/src/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.ts +189 -0
  102. package/src/_modules/ai/_modules/fdp-ai/index.ts +5 -0
  103. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -0
  104. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -0
  105. package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +240 -0
  106. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -0
  107. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +437 -0
  108. package/src/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.ts +157 -0
  109. package/src/_modules/ai/_modules/open-ai/index.ts +1 -0
  110. package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -0
  111. package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -0
  112. package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -0
  113. package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +79 -0
  114. package/src/_modules/ai/_services/ai-user-key.service-base.ts +59 -0
  115. package/src/_modules/ai/index.ts +2 -0
  116. package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -0
  117. package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -0
  118. package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -0
  119. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -0
  120. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -0
  121. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -0
  122. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -0
  123. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -0
  124. package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -0
  125. package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -0
  126. package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -0
  127. package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -0
  128. package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -0
  129. package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -0
  130. package/src/_modules/custom-data/custom-data.controller.ts +1 -3
  131. package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -0
  132. package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -0
  133. package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -0
  134. package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -0
  135. package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -0
  136. package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -0
  137. package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -0
  138. package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -0
  139. package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -0
  140. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -0
  141. package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -0
  142. package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -0
  143. package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -0
  144. package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -0
  145. package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -0
  146. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -0
  147. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +345 -0
  148. package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -0
  149. package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -0
  150. package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -0
  151. package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -0
  152. package/src/_modules/mock/data-model.mock.spec.ts +27 -24
  153. package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -0
  154. package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -0
  155. package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -0
  156. package/src/_modules/server/errors/errors.control-service.spec.ts +230 -0
  157. package/src/_modules/server/errors/errors.controller.spec.ts +165 -0
  158. package/src/_modules/server/errors/errors.data-service.spec.ts +355 -0
  159. package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -0
  160. package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -0
  161. package/src/_modules/server/server-status/server-status.control-service.spec.ts +516 -0
  162. package/src/_modules/server/server-status/server-status.controller.spec.ts +156 -0
  163. package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +6 -3
  164. package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -0
  165. package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -0
  166. package/src/_modules/socket/app-extended.server.ts +1 -1
  167. package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -0
  168. package/src/_modules/test/test.controller.spec.ts +72 -0
  169. package/src/_modules/usage/usage.controller.spec.ts +81 -0
  170. package/src/_modules/usage/usage.data-service.spec.ts +332 -0
  171. package/src/_services/base/api.service-base.spec.ts +125 -0
  172. package/src/_services/base/archive-data.service.spec.ts +196 -0
  173. package/src/_services/base/data.service.spec.ts +493 -0
  174. package/src/_services/base/data.service.ts +1 -1
  175. package/src/_services/base/db.service.spec.ts +59 -18
  176. package/src/_services/base/db.service.ts +1 -1
  177. package/src/_services/base/singleton.service-base.spec.ts +28 -0
  178. package/src/_services/base/singleton.service.spec.ts +114 -0
  179. package/src/_services/core/api.service.ts +1 -0
  180. package/src/_services/core/auth.service.spec.ts +159 -0
  181. package/src/_services/core/auth.service.ts +2 -2
  182. package/src/_services/core/email.service.spec.ts +14 -22
  183. package/src/_services/core/email.service.ts +1 -1
  184. package/src/_services/core/global.service.spec.ts +275 -0
  185. package/src/_services/core/global.service.ts +2 -2
  186. package/src/_services/core/service-collection.service.spec.ts +46 -0
  187. package/src/_services/route/controller.service.ts +1 -1
  188. package/src/_services/route/routing-module.service.spec.ts +8 -6
  189. package/src/_services/server/app.server.ts +17 -1
  190. package/src/_services/shared.static-service.spec.ts +89 -0
  191. package/src/_modules/socket/app-extended.server.spec.ts +0 -227
  192. package/src/_services/server/app.server.spec.ts +0 -138
@@ -0,0 +1,107 @@
1
+
2
+ import { DyNTS_OAuth2_Controller } from './oauth2.controller';
3
+ import { DyNTS_Endpoint_Params } from '../../../_models/control-models/endpoint-params.control-model';
4
+ import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
5
+ import { DyNTS_OAuth2_AuthService } from '../_services/oauth2.auth-service';
6
+ import { DyNTS_OAuth2_ControlService } from '../_services/oauth2.control-service';
7
+
8
+ describe('| DyNTS_OAuth2_Controller', () => {
9
+ let controller: DyNTS_OAuth2_Controller;
10
+ let mockAuthService: jasmine.SpyObj<DyNTS_OAuth2_AuthService>;
11
+ let mockControlService: jasmine.SpyObj<DyNTS_OAuth2_ControlService>;
12
+
13
+ beforeEach(() => {
14
+ // Reset singleton instances to prevent state leakage between tests
15
+ (DyNTS_OAuth2_Controller as any).instance = undefined;
16
+ (DyNTS_OAuth2_ControlService as any).instance = undefined;
17
+ (DyNTS_OAuth2_AuthService as any).instance = undefined;
18
+
19
+ // Mock the services to prevent circular dependency
20
+ mockAuthService = jasmine.createSpyObj('DyNTS_OAuth2_AuthService', [
21
+ 'authenticate_token',
22
+ 'getTokenFromRequest',
23
+ ]);
24
+ mockControlService = jasmine.createSpyObj('DyNTS_OAuth2_ControlService', [
25
+ 'handleAuthorizationRequest',
26
+ 'handleTokenRequest',
27
+ 'handleUserInfoRequest',
28
+ 'handleTokenRevocation',
29
+ ]);
30
+
31
+ spyOn(DyNTS_OAuth2_AuthService, 'getInstance').and.returnValue(mockAuthService);
32
+ spyOn(DyNTS_OAuth2_ControlService, 'getInstance').and.returnValue(mockControlService);
33
+
34
+ // Now we can safely get the Controller instance
35
+ controller = DyNTS_OAuth2_Controller.getInstance();
36
+
37
+ // Replace the services with our mocks
38
+ (controller as any).authService = mockAuthService;
39
+ (controller as any).controlService = mockControlService;
40
+ });
41
+
42
+ it('| should be a singleton instance', () => {
43
+ const instance1 = DyNTS_OAuth2_Controller.getInstance();
44
+ const instance2 = DyNTS_OAuth2_Controller.getInstance();
45
+
46
+ expect(instance1).toBe(instance2);
47
+ expect(instance1).toBeInstanceOf(DyNTS_OAuth2_Controller);
48
+ });
49
+
50
+ describe('| setupEndpoints', () => {
51
+ it('| should setup all OAuth2 endpoints', () => {
52
+ controller.setupEndpoints();
53
+
54
+ expect(controller.endpoints).toBeDefined();
55
+ expect(controller.endpoints.length).toBe(4);
56
+ });
57
+
58
+ it('| should setup authorize endpoint', () => {
59
+ controller.setupEndpoints();
60
+
61
+ const authorizeEndpoint = controller.endpoints.find(ep => ep.name === 'authorize');
62
+ expect(authorizeEndpoint).toBeDefined();
63
+ expect(authorizeEndpoint?.type).toBe(DyFM_HttpCallType.get);
64
+ expect(authorizeEndpoint?.endpoint).toBe('/oauth2/authorize');
65
+ expect((authorizeEndpoint as any)?.tasks).toBeDefined();
66
+ expect((authorizeEndpoint as any)?.tasks?.length).toBe(1);
67
+ });
68
+
69
+ it('| should setup token endpoint', () => {
70
+ controller.setupEndpoints();
71
+
72
+ const tokenEndpoint = controller.endpoints.find(ep => ep.name === 'token');
73
+ expect(tokenEndpoint).toBeDefined();
74
+ expect(tokenEndpoint?.type).toBe(DyFM_HttpCallType.post);
75
+ expect(tokenEndpoint?.endpoint).toBe('/oauth2/token');
76
+ expect((tokenEndpoint as any)?.tasks).toBeDefined();
77
+ expect((tokenEndpoint as any)?.tasks?.length).toBe(1);
78
+ });
79
+
80
+ it('| should setup userinfo endpoint', () => {
81
+ controller.setupEndpoints();
82
+
83
+ const userinfoEndpoint = controller.endpoints.find(ep => ep.name === 'userinfo');
84
+ expect(userinfoEndpoint).toBeDefined();
85
+ expect(userinfoEndpoint?.type).toBe(DyFM_HttpCallType.get);
86
+ expect(userinfoEndpoint?.endpoint).toBe('/oauth2/userinfo');
87
+ expect((userinfoEndpoint as any)?.preProcesses).toBeDefined();
88
+ expect((userinfoEndpoint as any)?.preProcesses?.length).toBe(1);
89
+ expect((userinfoEndpoint as any)?.tasks).toBeDefined();
90
+ expect((userinfoEndpoint as any)?.tasks?.length).toBe(1);
91
+ });
92
+
93
+ it('| should setup revoke endpoint', () => {
94
+ controller.setupEndpoints();
95
+
96
+ const revokeEndpoint = controller.endpoints.find(ep => ep.name === 'revoke');
97
+ expect(revokeEndpoint).toBeDefined();
98
+ expect(revokeEndpoint?.type).toBe(DyFM_HttpCallType.post);
99
+ expect(revokeEndpoint?.endpoint).toBe('/oauth2/revoke');
100
+ expect((revokeEndpoint as any)?.preProcesses).toBeDefined();
101
+ expect((revokeEndpoint as any)?.preProcesses?.length).toBe(1);
102
+ expect((revokeEndpoint as any)?.tasks).toBeDefined();
103
+ expect((revokeEndpoint as any)?.tasks?.length).toBe(1);
104
+ });
105
+ });
106
+ });
107
+
@@ -0,0 +1,254 @@
1
+
2
+ import { DyNTS_OAuth2_AuthService } from './oauth2.auth-service';
3
+ import { DyNTS_OAuth2_ControlService } from './oauth2.control-service';
4
+ import { Request, Response } from 'express';
5
+ import { DyFM_Error } from '@futdevpro/fsm-dynamo';
6
+ import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
7
+
8
+ describe('| DyNTS_OAuth2_AuthService', () => {
9
+ let service: DyNTS_OAuth2_AuthService;
10
+ let mockControlService: jasmine.SpyObj<DyNTS_OAuth2_ControlService>;
11
+ let mockRequest: Partial<Request>;
12
+ let mockResponse: Partial<Response>;
13
+
14
+ beforeEach(() => {
15
+ // Reset singleton instances to prevent state leakage between tests
16
+ (DyNTS_OAuth2_ControlService as any).instance = undefined;
17
+ (DyNTS_OAuth2_AuthService as any).instance = undefined;
18
+
19
+ // Mock the ControlService.getInstance() to prevent circular dependency
20
+ mockControlService = jasmine.createSpyObj('DyNTS_OAuth2_ControlService', [
21
+ 'getAccessTokenData',
22
+ 'getRefreshTokenData',
23
+ 'getClient',
24
+ 'getUser',
25
+ 'validateClientCredentials',
26
+ 'validateUserCredentials',
27
+ ]);
28
+ spyOn(DyNTS_OAuth2_ControlService, 'getInstance').and.returnValue(mockControlService);
29
+
30
+ // Now we can safely get the AuthService instance
31
+ service = DyNTS_OAuth2_AuthService.getInstance();
32
+
33
+ // Replace the controlService with our mock
34
+ (service as any).controlService = mockControlService;
35
+
36
+ mockRequest = {
37
+ headers: {},
38
+ };
39
+
40
+ mockResponse = {
41
+ setHeader: jasmine.createSpy('setHeader'),
42
+ };
43
+ });
44
+
45
+ it('| should be a singleton instance', () => {
46
+ const instance1 = DyNTS_OAuth2_AuthService.getInstance();
47
+ const instance2 = DyNTS_OAuth2_AuthService.getInstance();
48
+
49
+ expect(instance1).toBe(instance2);
50
+ expect(instance1).toBeInstanceOf(DyNTS_OAuth2_AuthService);
51
+ });
52
+
53
+ describe('| authenticate_token', () => {
54
+ it('| should authenticate valid token', async () => {
55
+ mockRequest.headers = {
56
+ authorization: 'Bearer valid-token-123',
57
+ };
58
+ spyOn(service, 'getTokenFromRequest').and.returnValue('Bearer valid-token-123');
59
+ mockControlService.getAccessTokenData.and.returnValue({
60
+ clientId: 'client-123',
61
+ scope: 'read',
62
+ expiresAt: Date.now() + 3600000, // 1 hour from now
63
+ });
64
+
65
+ await service.authenticate_token(mockRequest as Request, mockResponse as Response);
66
+
67
+ expect(mockControlService.getAccessTokenData).toHaveBeenCalledWith('valid-token-123');
68
+ expect(mockResponse.setHeader).toHaveBeenCalledWith('authorization', 'Bearer valid-token-123');
69
+ });
70
+
71
+ it('| should throw error when token format is invalid', async () => {
72
+ mockRequest.headers = {
73
+ authorization: 'InvalidFormat token',
74
+ };
75
+
76
+ await expectAsync(
77
+ service.authenticate_token(mockRequest as Request, mockResponse as Response)
78
+ ).toBeRejected();
79
+ });
80
+
81
+ it('| should throw error when token is missing', async () => {
82
+ mockRequest.headers = {};
83
+
84
+ await expectAsync(
85
+ service.authenticate_token(mockRequest as Request, mockResponse as Response)
86
+ ).toBeRejected();
87
+ });
88
+
89
+ it('| should throw error when token is expired', async () => {
90
+ mockRequest.headers = {
91
+ authorization: 'Bearer expired-token',
92
+ };
93
+ mockControlService.getAccessTokenData.and.returnValue({
94
+ clientId: 'client-123',
95
+ scope: 'read',
96
+ expiresAt: Date.now() - 1000, // Expired
97
+ });
98
+
99
+ await expectAsync(
100
+ service.authenticate_token(mockRequest as Request, mockResponse as Response)
101
+ ).toBeRejected();
102
+ });
103
+
104
+ it('| should throw error when token data is not found', async () => {
105
+ mockRequest.headers = {
106
+ authorization: 'Bearer invalid-token',
107
+ };
108
+ mockControlService.getAccessTokenData.and.returnValue(null);
109
+
110
+ await expectAsync(
111
+ service.authenticate_token(mockRequest as Request, mockResponse as Response)
112
+ ).toBeRejected();
113
+ });
114
+ });
115
+
116
+ describe('| authenticate_tokenSelf', () => {
117
+ it('| should authenticate valid token for self', async () => {
118
+ mockRequest.headers = {
119
+ authorization: 'Bearer valid-token-123',
120
+ };
121
+ mockRequest.params = {
122
+ userId: 'client-123',
123
+ };
124
+ spyOn(service, 'getTokenFromRequest').and.returnValue('Bearer valid-token-123');
125
+ spyOn(service, 'getIssuerFromRequest').and.returnValue('client-123');
126
+ mockControlService.getAccessTokenData.and.returnValue({
127
+ clientId: 'client-123',
128
+ scope: 'read',
129
+ expiresAt: Date.now() + 3600000,
130
+ } as any);
131
+
132
+ await service.authenticate_tokenSelf(mockRequest as Request, mockResponse as Response);
133
+
134
+ expect(mockControlService.getAccessTokenData).toHaveBeenCalledWith('valid-token-123');
135
+ expect(mockResponse.setHeader).toHaveBeenCalledWith('authorization', 'Bearer valid-token-123');
136
+ });
137
+
138
+ it('| should throw error when userId does not match', async () => {
139
+ mockRequest.headers = {
140
+ authorization: 'Bearer valid-token-123',
141
+ };
142
+ mockRequest.params = {
143
+ userId: 'user-456',
144
+ };
145
+ mockControlService.getAccessTokenData.and.returnValue({
146
+ clientId: 'client-123',
147
+ scope: 'read',
148
+ expiresAt: Date.now() + 3600000,
149
+ } as any);
150
+
151
+ await expectAsync(
152
+ service.authenticate_tokenSelf(mockRequest as Request, mockResponse as Response)
153
+ ).toBeRejected();
154
+ });
155
+ });
156
+
157
+ describe('| authenticate_tokenPerm_accUsageData', () => {
158
+ it('| should authenticate token with usage data permission', async () => {
159
+ mockRequest.headers = {
160
+ authorization: 'Bearer valid-token-123',
161
+ };
162
+ spyOn(service, 'getTokenFromRequest').and.returnValue('Bearer valid-token-123');
163
+ mockControlService.getAccessTokenData.and.returnValue({
164
+ clientId: 'client-123',
165
+ scope: 'usage_data read',
166
+ expiresAt: Date.now() + 3600000,
167
+ } as any);
168
+
169
+ await service.authenticate_tokenPerm_accUsageData(mockRequest as Request, mockResponse as Response);
170
+
171
+ expect(mockResponse.setHeader).toHaveBeenCalledWith('authorization', 'Bearer valid-token-123');
172
+ });
173
+
174
+ it('| should throw error when permission is missing', async () => {
175
+ mockRequest.headers = {
176
+ authorization: 'Bearer valid-token-123',
177
+ };
178
+ mockControlService.getAccessTokenData.and.returnValue({
179
+ clientId: 'client-123',
180
+ scope: 'read',
181
+ expiresAt: Date.now() + 3600000,
182
+ } as any);
183
+
184
+ await expectAsync(
185
+ service.authenticate_tokenPerm_accUsageData(mockRequest as Request, mockResponse as Response)
186
+ ).toBeRejected();
187
+ });
188
+ });
189
+
190
+ describe('| getIssuerFromRequest', () => {
191
+ it('| should return issuer from valid token', () => {
192
+ mockRequest.headers = {
193
+ authorization: 'Bearer valid-token-123',
194
+ };
195
+ spyOn(service, 'getTokenFromRequest').and.returnValue('Bearer valid-token-123');
196
+ mockControlService.getAccessTokenData.and.returnValue({
197
+ clientId: 'client-123',
198
+ scope: 'read',
199
+ expiresAt: Date.now() + 3600000,
200
+ } as any);
201
+
202
+ const result = service.getIssuerFromRequest(mockRequest as Request);
203
+
204
+ expect(result).toBe('client-123');
205
+ });
206
+
207
+ it('| should return undefined when token is missing', () => {
208
+ mockRequest.headers = {};
209
+
210
+ const result = service.getIssuerFromRequest(mockRequest as Request);
211
+
212
+ expect(result).toBeUndefined();
213
+ });
214
+
215
+ it('| should return undefined when token data is not found', () => {
216
+ mockRequest.headers = {
217
+ authorization: 'Bearer invalid-token',
218
+ };
219
+ mockControlService.getAccessTokenData.and.returnValue(null);
220
+
221
+ const result = service.getIssuerFromRequest(mockRequest as Request);
222
+
223
+ expect(result).toBeUndefined();
224
+ });
225
+ });
226
+
227
+ describe('| getUsernameFromRequest', () => {
228
+ it('| should return username from valid token', () => {
229
+ mockRequest.headers = {
230
+ authorization: 'Bearer valid-token-123',
231
+ };
232
+ spyOn(service, 'getTokenFromRequest').and.returnValue('Bearer valid-token-123');
233
+ mockControlService.getAccessTokenData.and.returnValue({
234
+ clientId: 'client-123',
235
+ scope: 'read',
236
+ expiresAt: Date.now() + 3600000,
237
+ } as any);
238
+
239
+ const result = service.getUsernameFromRequest(mockRequest as Request);
240
+
241
+ // The implementation returns clientId as username (see TODO comment in code)
242
+ expect(result).toBe('client-123');
243
+ });
244
+
245
+ it('| should return undefined when token is missing', () => {
246
+ mockRequest.headers = {};
247
+
248
+ const result = service.getUsernameFromRequest(mockRequest as Request);
249
+
250
+ expect(result).toBeUndefined();
251
+ });
252
+ });
253
+ });
254
+