digitaltwin-core 0.14.2 → 1.0.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 (227) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +494 -359
  3. package/dist/auth/apisix_parser.d.ts +141 -0
  4. package/dist/auth/apisix_parser.d.ts.map +1 -0
  5. package/dist/auth/apisix_parser.js +161 -0
  6. package/dist/auth/apisix_parser.js.map +1 -0
  7. package/dist/auth/auth_config.d.ts +126 -0
  8. package/dist/auth/auth_config.d.ts.map +1 -0
  9. package/dist/auth/auth_config.js +169 -0
  10. package/dist/auth/auth_config.js.map +1 -0
  11. package/dist/auth/auth_provider.d.ts +118 -0
  12. package/dist/auth/auth_provider.d.ts.map +1 -0
  13. package/dist/auth/auth_provider.js +8 -0
  14. package/dist/auth/auth_provider.js.map +1 -0
  15. package/dist/auth/auth_provider_factory.d.ts +91 -0
  16. package/dist/auth/auth_provider_factory.d.ts.map +1 -0
  17. package/dist/auth/auth_provider_factory.js +146 -0
  18. package/dist/auth/auth_provider_factory.js.map +1 -0
  19. package/dist/auth/index.d.ts +8 -0
  20. package/dist/auth/index.d.ts.map +1 -0
  21. package/dist/auth/index.js +7 -0
  22. package/dist/auth/index.js.map +1 -0
  23. package/dist/auth/providers/gateway_auth_provider.d.ts +78 -0
  24. package/dist/auth/providers/gateway_auth_provider.d.ts.map +1 -0
  25. package/dist/auth/providers/gateway_auth_provider.js +109 -0
  26. package/dist/auth/providers/gateway_auth_provider.js.map +1 -0
  27. package/dist/auth/providers/index.d.ts +4 -0
  28. package/dist/auth/providers/index.d.ts.map +1 -0
  29. package/dist/auth/providers/index.js +4 -0
  30. package/dist/auth/providers/index.js.map +1 -0
  31. package/dist/auth/providers/jwt_auth_provider.d.ts +91 -0
  32. package/dist/auth/providers/jwt_auth_provider.d.ts.map +1 -0
  33. package/dist/auth/providers/jwt_auth_provider.js +204 -0
  34. package/dist/auth/providers/jwt_auth_provider.js.map +1 -0
  35. package/dist/auth/providers/no_auth_provider.d.ts +61 -0
  36. package/dist/auth/providers/no_auth_provider.d.ts.map +1 -0
  37. package/dist/auth/providers/no_auth_provider.js +76 -0
  38. package/dist/auth/providers/no_auth_provider.js.map +1 -0
  39. package/dist/auth/types.d.ts +100 -0
  40. package/dist/auth/types.d.ts.map +1 -0
  41. package/dist/auth/types.js +2 -0
  42. package/dist/auth/types.js.map +1 -0
  43. package/dist/auth/user_service.d.ts +86 -0
  44. package/dist/auth/user_service.d.ts.map +1 -0
  45. package/dist/auth/user_service.js +237 -0
  46. package/dist/auth/user_service.js.map +1 -0
  47. package/dist/components/assets_manager.d.ts +662 -0
  48. package/dist/components/assets_manager.d.ts.map +1 -0
  49. package/dist/components/assets_manager.js +1537 -0
  50. package/dist/components/assets_manager.js.map +1 -0
  51. package/dist/components/async_upload.d.ts +20 -0
  52. package/dist/components/async_upload.d.ts.map +1 -0
  53. package/dist/components/async_upload.js +10 -0
  54. package/dist/components/async_upload.js.map +1 -0
  55. package/dist/components/collector.d.ts +203 -0
  56. package/dist/components/collector.d.ts.map +1 -0
  57. package/dist/components/collector.js +214 -0
  58. package/dist/components/collector.js.map +1 -0
  59. package/dist/components/custom_table_manager.d.ts +503 -0
  60. package/dist/components/custom_table_manager.d.ts.map +1 -0
  61. package/dist/components/custom_table_manager.js +1023 -0
  62. package/dist/components/custom_table_manager.js.map +1 -0
  63. package/dist/components/global_assets_handler.d.ts +63 -0
  64. package/dist/components/global_assets_handler.d.ts.map +1 -0
  65. package/dist/components/global_assets_handler.js +127 -0
  66. package/dist/components/global_assets_handler.js.map +1 -0
  67. package/dist/components/handler.d.ts +104 -0
  68. package/dist/components/handler.d.ts.map +1 -0
  69. package/dist/components/handler.js +110 -0
  70. package/dist/components/handler.js.map +1 -0
  71. package/dist/components/harvester.d.ts +182 -0
  72. package/dist/components/harvester.d.ts.map +1 -0
  73. package/dist/components/harvester.js +406 -0
  74. package/dist/components/harvester.js.map +1 -0
  75. package/dist/components/index.d.ts +11 -0
  76. package/dist/components/index.d.ts.map +1 -0
  77. package/dist/components/index.js +9 -0
  78. package/dist/components/index.js.map +1 -0
  79. package/dist/components/interfaces.d.ts +126 -0
  80. package/dist/components/interfaces.d.ts.map +1 -0
  81. package/dist/components/interfaces.js +8 -0
  82. package/dist/components/interfaces.js.map +1 -0
  83. package/dist/components/map_manager.d.ts +61 -0
  84. package/dist/components/map_manager.d.ts.map +1 -0
  85. package/dist/components/map_manager.js +242 -0
  86. package/dist/components/map_manager.js.map +1 -0
  87. package/dist/components/tileset_manager.d.ts +125 -0
  88. package/dist/components/tileset_manager.d.ts.map +1 -0
  89. package/dist/components/tileset_manager.js +623 -0
  90. package/dist/components/tileset_manager.js.map +1 -0
  91. package/dist/components/types.d.ts +226 -0
  92. package/dist/components/types.d.ts.map +1 -0
  93. package/dist/components/types.js +8 -0
  94. package/dist/components/types.js.map +1 -0
  95. package/dist/database/adapters/knex_database_adapter.d.ts +97 -0
  96. package/dist/database/adapters/knex_database_adapter.d.ts.map +1 -0
  97. package/dist/database/adapters/knex_database_adapter.js +729 -0
  98. package/dist/database/adapters/knex_database_adapter.js.map +1 -0
  99. package/dist/database/database_adapter.d.ts +262 -0
  100. package/dist/database/database_adapter.d.ts.map +1 -0
  101. package/dist/database/database_adapter.js +46 -0
  102. package/dist/database/database_adapter.js.map +1 -0
  103. package/dist/engine/digital_twin_engine.d.ts +295 -0
  104. package/dist/engine/digital_twin_engine.d.ts.map +1 -0
  105. package/dist/engine/digital_twin_engine.js +907 -0
  106. package/dist/engine/digital_twin_engine.js.map +1 -0
  107. package/dist/engine/endpoints.d.ts +47 -0
  108. package/dist/engine/endpoints.d.ts.map +1 -0
  109. package/dist/engine/endpoints.js +88 -0
  110. package/dist/engine/endpoints.js.map +1 -0
  111. package/dist/engine/error_handler.d.ts +20 -0
  112. package/dist/engine/error_handler.d.ts.map +1 -0
  113. package/dist/engine/error_handler.js +69 -0
  114. package/dist/engine/error_handler.js.map +1 -0
  115. package/dist/engine/events.d.ts +93 -0
  116. package/dist/engine/events.d.ts.map +1 -0
  117. package/dist/engine/events.js +71 -0
  118. package/dist/engine/events.js.map +1 -0
  119. package/dist/engine/health.d.ts +112 -0
  120. package/dist/engine/health.d.ts.map +1 -0
  121. package/dist/engine/health.js +190 -0
  122. package/dist/engine/health.js.map +1 -0
  123. package/dist/engine/initializer.d.ts +62 -0
  124. package/dist/engine/initializer.d.ts.map +1 -0
  125. package/dist/engine/initializer.js +108 -0
  126. package/dist/engine/initializer.js.map +1 -0
  127. package/dist/engine/queue_manager.d.ts +87 -0
  128. package/dist/engine/queue_manager.d.ts.map +1 -0
  129. package/dist/engine/queue_manager.js +196 -0
  130. package/dist/engine/queue_manager.js.map +1 -0
  131. package/dist/engine/scheduler.d.ts +30 -0
  132. package/dist/engine/scheduler.d.ts.map +1 -0
  133. package/dist/engine/scheduler.js +378 -0
  134. package/dist/engine/scheduler.js.map +1 -0
  135. package/dist/engine/upload_processor.d.ts +36 -0
  136. package/dist/engine/upload_processor.d.ts.map +1 -0
  137. package/dist/engine/upload_processor.js +113 -0
  138. package/dist/engine/upload_processor.js.map +1 -0
  139. package/dist/env/env.d.ts +134 -0
  140. package/dist/env/env.d.ts.map +1 -0
  141. package/dist/env/env.js +177 -0
  142. package/dist/env/env.js.map +1 -0
  143. package/dist/errors/index.d.ts +94 -0
  144. package/dist/errors/index.d.ts.map +1 -0
  145. package/dist/errors/index.js +149 -0
  146. package/dist/errors/index.js.map +1 -0
  147. package/dist/index.d.ts +55 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +65 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/openapi/generator.d.ts +93 -0
  152. package/dist/openapi/generator.d.ts.map +1 -0
  153. package/dist/openapi/generator.js +293 -0
  154. package/dist/openapi/generator.js.map +1 -0
  155. package/dist/openapi/index.d.ts +9 -0
  156. package/dist/openapi/index.d.ts.map +1 -0
  157. package/dist/openapi/index.js +9 -0
  158. package/dist/openapi/index.js.map +1 -0
  159. package/dist/openapi/types.d.ts +182 -0
  160. package/dist/openapi/types.d.ts.map +1 -0
  161. package/dist/openapi/types.js +16 -0
  162. package/dist/openapi/types.js.map +1 -0
  163. package/dist/storage/adapters/local_storage_service.d.ts +57 -0
  164. package/dist/storage/adapters/local_storage_service.d.ts.map +1 -0
  165. package/dist/storage/adapters/local_storage_service.js +132 -0
  166. package/dist/storage/adapters/local_storage_service.js.map +1 -0
  167. package/dist/storage/adapters/ovh_storage_service.d.ts +72 -0
  168. package/dist/storage/adapters/ovh_storage_service.d.ts.map +1 -0
  169. package/dist/storage/adapters/ovh_storage_service.js +205 -0
  170. package/dist/storage/adapters/ovh_storage_service.js.map +1 -0
  171. package/dist/storage/storage_factory.d.ts +14 -0
  172. package/dist/storage/storage_factory.d.ts.map +1 -0
  173. package/dist/storage/storage_factory.js +43 -0
  174. package/dist/storage/storage_factory.js.map +1 -0
  175. package/dist/storage/storage_service.d.ts +163 -0
  176. package/dist/storage/storage_service.d.ts.map +1 -0
  177. package/dist/storage/storage_service.js +58 -0
  178. package/dist/storage/storage_service.js.map +1 -0
  179. package/dist/types/data_record.d.ts +123 -0
  180. package/dist/types/data_record.d.ts.map +1 -0
  181. package/dist/types/data_record.js +8 -0
  182. package/dist/types/data_record.js.map +1 -0
  183. package/dist/utils/graceful_shutdown.d.ts +44 -0
  184. package/dist/utils/graceful_shutdown.d.ts.map +1 -0
  185. package/dist/utils/graceful_shutdown.js +79 -0
  186. package/dist/utils/graceful_shutdown.js.map +1 -0
  187. package/dist/utils/http_responses.d.ts +175 -0
  188. package/dist/utils/http_responses.d.ts.map +1 -0
  189. package/dist/utils/http_responses.js +216 -0
  190. package/dist/utils/http_responses.js.map +1 -0
  191. package/dist/utils/index.d.ts +8 -0
  192. package/dist/utils/index.d.ts.map +1 -0
  193. package/dist/utils/index.js +6 -0
  194. package/dist/utils/index.js.map +1 -0
  195. package/dist/utils/logger.d.ts +74 -0
  196. package/dist/utils/logger.d.ts.map +1 -0
  197. package/dist/utils/logger.js +92 -0
  198. package/dist/utils/logger.js.map +1 -0
  199. package/dist/utils/map_to_data_record.d.ts +10 -0
  200. package/dist/utils/map_to_data_record.d.ts.map +1 -0
  201. package/dist/utils/map_to_data_record.js +36 -0
  202. package/dist/utils/map_to_data_record.js.map +1 -0
  203. package/dist/utils/safe_async.d.ts +50 -0
  204. package/dist/utils/safe_async.d.ts.map +1 -0
  205. package/dist/utils/safe_async.js +90 -0
  206. package/dist/utils/safe_async.js.map +1 -0
  207. package/dist/utils/servable_endpoint.d.ts +63 -0
  208. package/dist/utils/servable_endpoint.d.ts.map +1 -0
  209. package/dist/utils/servable_endpoint.js +67 -0
  210. package/dist/utils/servable_endpoint.js.map +1 -0
  211. package/dist/utils/zip_utils.d.ts +66 -0
  212. package/dist/utils/zip_utils.d.ts.map +1 -0
  213. package/dist/utils/zip_utils.js +169 -0
  214. package/dist/utils/zip_utils.js.map +1 -0
  215. package/dist/validation/index.d.ts +3 -0
  216. package/dist/validation/index.d.ts.map +1 -0
  217. package/dist/validation/index.js +7 -0
  218. package/dist/validation/index.js.map +1 -0
  219. package/dist/validation/schemas.d.ts +273 -0
  220. package/dist/validation/schemas.d.ts.map +1 -0
  221. package/dist/validation/schemas.js +82 -0
  222. package/dist/validation/schemas.js.map +1 -0
  223. package/dist/validation/validate.d.ts +49 -0
  224. package/dist/validation/validate.d.ts.map +1 -0
  225. package/dist/validation/validate.js +110 -0
  226. package/dist/validation/validate.js.map +1 -0
  227. package/package.json +23 -13
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @fileoverview JWT authentication provider for direct token validation.
3
+ *
4
+ * This provider validates JWT tokens from the Authorization header without
5
+ * requiring an API gateway. Useful for standalone deployments or when you
6
+ * want to handle authentication directly in the application.
7
+ *
8
+ * Supports:
9
+ * - HMAC algorithms (HS256, HS384, HS512) with a secret key
10
+ * - RSA algorithms (RS256, RS384, RS512) with a public key
11
+ * - EC algorithms (ES256, ES384, ES512) with a public key
12
+ * - Keycloak token format (realm_access.roles)
13
+ * - Custom claim paths for user ID and roles
14
+ */
15
+ import type { AuthProvider, AuthRequest, AuthProviderConfig } from '../auth_provider.js';
16
+ import type { AuthenticatedUser } from '../types.js';
17
+ /**
18
+ * Authentication provider for JWT token validation.
19
+ *
20
+ * This provider validates JWT tokens directly in the application, without
21
+ * requiring an API gateway. It extracts user information from token claims.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // With HMAC secret
26
+ * const provider = new JwtAuthProvider({
27
+ * mode: 'jwt',
28
+ * jwt: {
29
+ * secret: 'your-256-bit-secret',
30
+ * algorithm: 'HS256'
31
+ * }
32
+ * })
33
+ *
34
+ * // With RSA public key (Keycloak)
35
+ * const provider = new JwtAuthProvider({
36
+ * mode: 'jwt',
37
+ * jwt: {
38
+ * publicKey: fs.readFileSync('public.pem', 'utf-8'),
39
+ * algorithm: 'RS256',
40
+ * issuer: 'https://keycloak.example.com/realms/myrealm',
41
+ * rolesClaim: 'realm_access.roles'
42
+ * }
43
+ * })
44
+ * ```
45
+ */
46
+ export declare class JwtAuthProvider implements AuthProvider {
47
+ #private;
48
+ /**
49
+ * Creates a new JwtAuthProvider.
50
+ *
51
+ * @param config - Authentication configuration with JWT settings
52
+ * @throws Error if JWT configuration is missing or incomplete
53
+ */
54
+ constructor(config: AuthProviderConfig);
55
+ /**
56
+ * Parse the request and validate the JWT token.
57
+ *
58
+ * @param req - Request object with headers
59
+ * @returns Authenticated user, or null if token is missing/invalid
60
+ */
61
+ parseRequest(req: AuthRequest): AuthenticatedUser | null;
62
+ /**
63
+ * Check if the request has a valid Authorization header with Bearer token.
64
+ *
65
+ * @param req - Request object with headers
66
+ * @returns true if Authorization header is present with Bearer scheme
67
+ */
68
+ hasValidAuth(req: AuthRequest): boolean;
69
+ /**
70
+ * Check if the authenticated user has admin privileges.
71
+ *
72
+ * @param req - Request object with headers
73
+ * @returns true if the user has the admin role
74
+ */
75
+ isAdmin(req: AuthRequest): boolean;
76
+ /**
77
+ * Get the user ID from the JWT token.
78
+ *
79
+ * @param req - Request object with headers
80
+ * @returns User ID, or null if not authenticated
81
+ */
82
+ getUserId(req: AuthRequest): string | null;
83
+ /**
84
+ * Get the user roles from the JWT token.
85
+ *
86
+ * @param req - Request object with headers
87
+ * @returns Array of role names, empty array if not authenticated
88
+ */
89
+ getUserRoles(req: AuthRequest): string[];
90
+ }
91
+ //# sourceMappingURL=jwt_auth_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt_auth_provider.d.ts","sourceRoot":"","sources":["../../../src/auth/providers/jwt_auth_provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,eAAgB,YAAW,YAAY;;IAShD;;;;;OAKG;gBACS,MAAM,EAAE,kBAAkB;IAwBtC;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,GAAG,IAAI;IAuBxD;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAIvC;;;;;OAKG;IACH,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAKlC;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI;IAK1C;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,EAAE;CAkE3C"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * @fileoverview JWT authentication provider for direct token validation.
3
+ *
4
+ * This provider validates JWT tokens from the Authorization header without
5
+ * requiring an API gateway. Useful for standalone deployments or when you
6
+ * want to handle authentication directly in the application.
7
+ *
8
+ * Supports:
9
+ * - HMAC algorithms (HS256, HS384, HS512) with a secret key
10
+ * - RSA algorithms (RS256, RS384, RS512) with a public key
11
+ * - EC algorithms (ES256, ES384, ES512) with a public key
12
+ * - Keycloak token format (realm_access.roles)
13
+ * - Custom claim paths for user ID and roles
14
+ */
15
+ import jwt from 'jsonwebtoken';
16
+ /**
17
+ * Authentication provider for JWT token validation.
18
+ *
19
+ * This provider validates JWT tokens directly in the application, without
20
+ * requiring an API gateway. It extracts user information from token claims.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // With HMAC secret
25
+ * const provider = new JwtAuthProvider({
26
+ * mode: 'jwt',
27
+ * jwt: {
28
+ * secret: 'your-256-bit-secret',
29
+ * algorithm: 'HS256'
30
+ * }
31
+ * })
32
+ *
33
+ * // With RSA public key (Keycloak)
34
+ * const provider = new JwtAuthProvider({
35
+ * mode: 'jwt',
36
+ * jwt: {
37
+ * publicKey: fs.readFileSync('public.pem', 'utf-8'),
38
+ * algorithm: 'RS256',
39
+ * issuer: 'https://keycloak.example.com/realms/myrealm',
40
+ * rolesClaim: 'realm_access.roles'
41
+ * }
42
+ * })
43
+ * ```
44
+ */
45
+ export class JwtAuthProvider {
46
+ #secret;
47
+ #algorithm;
48
+ #issuer;
49
+ #audience;
50
+ #userIdClaim;
51
+ #rolesClaim;
52
+ #adminRoleName;
53
+ /**
54
+ * Creates a new JwtAuthProvider.
55
+ *
56
+ * @param config - Authentication configuration with JWT settings
57
+ * @throws Error if JWT configuration is missing or incomplete
58
+ */
59
+ constructor(config) {
60
+ if (!config.jwt) {
61
+ throw new Error('JWT configuration required for JWT auth mode');
62
+ }
63
+ const { jwt: jwtConfig } = config;
64
+ // Secret or public key
65
+ if (jwtConfig.publicKey) {
66
+ this.#secret = jwtConfig.publicKey;
67
+ }
68
+ else if (jwtConfig.secret) {
69
+ this.#secret = jwtConfig.secret;
70
+ }
71
+ else {
72
+ throw new Error('JWT secret or publicKey required');
73
+ }
74
+ this.#algorithm = jwtConfig.algorithm || 'HS256';
75
+ this.#issuer = jwtConfig.issuer;
76
+ this.#audience = jwtConfig.audience;
77
+ this.#userIdClaim = jwtConfig.userIdClaim || 'sub';
78
+ this.#rolesClaim = jwtConfig.rolesClaim || 'roles';
79
+ this.#adminRoleName = config.adminRoleName || 'admin';
80
+ }
81
+ /**
82
+ * Parse the request and validate the JWT token.
83
+ *
84
+ * @param req - Request object with headers
85
+ * @returns Authenticated user, or null if token is missing/invalid
86
+ */
87
+ parseRequest(req) {
88
+ const token = this.#extractToken(req);
89
+ if (!token)
90
+ return null;
91
+ try {
92
+ const decoded = jwt.verify(token, this.#secret, {
93
+ algorithms: [this.#algorithm],
94
+ issuer: this.#issuer,
95
+ audience: this.#audience
96
+ });
97
+ const userId = this.#extractClaim(decoded, this.#userIdClaim);
98
+ if (!userId || typeof userId !== 'string')
99
+ return null;
100
+ const roles = this.#extractRoles(decoded);
101
+ return { id: userId, roles };
102
+ }
103
+ catch {
104
+ // Token invalid or expired
105
+ return null;
106
+ }
107
+ }
108
+ /**
109
+ * Check if the request has a valid Authorization header with Bearer token.
110
+ *
111
+ * @param req - Request object with headers
112
+ * @returns true if Authorization header is present with Bearer scheme
113
+ */
114
+ hasValidAuth(req) {
115
+ return !!this.#extractToken(req);
116
+ }
117
+ /**
118
+ * Check if the authenticated user has admin privileges.
119
+ *
120
+ * @param req - Request object with headers
121
+ * @returns true if the user has the admin role
122
+ */
123
+ isAdmin(req) {
124
+ const user = this.parseRequest(req);
125
+ return user?.roles.includes(this.#adminRoleName) ?? false;
126
+ }
127
+ /**
128
+ * Get the user ID from the JWT token.
129
+ *
130
+ * @param req - Request object with headers
131
+ * @returns User ID, or null if not authenticated
132
+ */
133
+ getUserId(req) {
134
+ const user = this.parseRequest(req);
135
+ return user?.id ?? null;
136
+ }
137
+ /**
138
+ * Get the user roles from the JWT token.
139
+ *
140
+ * @param req - Request object with headers
141
+ * @returns Array of role names, empty array if not authenticated
142
+ */
143
+ getUserRoles(req) {
144
+ const user = this.parseRequest(req);
145
+ return user?.roles ?? [];
146
+ }
147
+ /**
148
+ * Extract the Bearer token from the Authorization header.
149
+ */
150
+ #extractToken(req) {
151
+ const authHeader = this.#getHeader(req.headers, 'authorization');
152
+ if (!authHeader)
153
+ return null;
154
+ // Format: "Bearer <token>"
155
+ const parts = authHeader.split(' ');
156
+ if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') {
157
+ return null;
158
+ }
159
+ return parts[1];
160
+ }
161
+ /**
162
+ * Extract a claim value from the token payload.
163
+ * Supports nested paths like "realm_access.roles".
164
+ */
165
+ #extractClaim(payload, path) {
166
+ const parts = path.split('.');
167
+ let current = payload;
168
+ for (const part of parts) {
169
+ if (current === null || current === undefined)
170
+ return undefined;
171
+ if (typeof current !== 'object')
172
+ return undefined;
173
+ current = current[part];
174
+ }
175
+ return current;
176
+ }
177
+ /**
178
+ * Extract roles from the token payload.
179
+ * Supports standard array format and Keycloak's realm_access.roles.
180
+ */
181
+ #extractRoles(payload) {
182
+ // Try configured roles claim first
183
+ const roles = this.#extractClaim(payload, this.#rolesClaim);
184
+ if (Array.isArray(roles)) {
185
+ return roles.filter((r) => typeof r === 'string');
186
+ }
187
+ // Fallback to Keycloak format
188
+ const realmAccess = payload.realm_access;
189
+ if (realmAccess?.roles && Array.isArray(realmAccess.roles)) {
190
+ return realmAccess.roles;
191
+ }
192
+ return [];
193
+ }
194
+ /**
195
+ * Get a header value as a string.
196
+ */
197
+ #getHeader(headers, name) {
198
+ const value = headers[name];
199
+ if (!value)
200
+ return null;
201
+ return Array.isArray(value) ? value[0] : value;
202
+ }
203
+ }
204
+ //# sourceMappingURL=jwt_auth_provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt_auth_provider.js","sourceRoot":"","sources":["../../../src/auth/providers/jwt_auth_provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview No-authentication provider for development and testing.
3
+ *
4
+ * This provider bypasses all authentication checks and returns a configurable
5
+ * anonymous user for all requests. Use only in development or testing environments.
6
+ *
7
+ * WARNING: Never use this provider in production!
8
+ */
9
+ import type { AuthProvider, AuthRequest } from '../auth_provider.js';
10
+ import type { AuthenticatedUser } from '../types.js';
11
+ /**
12
+ * Authentication provider that bypasses authentication.
13
+ *
14
+ * All requests are treated as authenticated with a configurable anonymous user.
15
+ * This provider is useful for development and testing when you don't want to
16
+ * set up authentication infrastructure.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Development setup
21
+ * const provider = new NoAuthProvider('dev-user-123')
22
+ *
23
+ * // All requests return the same user
24
+ * const user = provider.parseRequest(req) // { id: 'dev-user-123', roles: ['user'] }
25
+ * provider.hasValidAuth(req) // always true
26
+ * provider.isAdmin(req) // always false
27
+ * ```
28
+ */
29
+ export declare class NoAuthProvider implements AuthProvider {
30
+ #private;
31
+ /**
32
+ * Creates a new NoAuthProvider.
33
+ *
34
+ * @param anonymousUserId - User ID for the anonymous user (default: 'anonymous')
35
+ * @param anonymousRoles - Roles for the anonymous user (default: ['anonymous'])
36
+ */
37
+ constructor(anonymousUserId?: string, anonymousRoles?: string[]);
38
+ /**
39
+ * Returns the anonymous user for all requests.
40
+ *
41
+ * @returns Anonymous user with configured ID and roles
42
+ */
43
+ parseRequest(_req: AuthRequest): AuthenticatedUser | null;
44
+ /**
45
+ * Always returns true (all requests are "authenticated").
46
+ */
47
+ hasValidAuth(_req: AuthRequest): boolean;
48
+ /**
49
+ * Always returns false (anonymous user is never admin).
50
+ */
51
+ isAdmin(_req: AuthRequest): boolean;
52
+ /**
53
+ * Returns the anonymous user ID.
54
+ */
55
+ getUserId(_req: AuthRequest): string | null;
56
+ /**
57
+ * Returns the anonymous user roles.
58
+ */
59
+ getUserRoles(_req: AuthRequest): string[];
60
+ }
61
+ //# sourceMappingURL=no_auth_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no_auth_provider.d.ts","sourceRoot":"","sources":["../../../src/auth/providers/no_auth_provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,cAAe,YAAW,YAAY;;IAI/C;;;;;OAKG;gBACS,eAAe,SAAc,EAAE,cAAc,GAAE,MAAM,EAAkB;IAKnF;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,GAAG,IAAI;IAOzD;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO;IAIxC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO;IAInC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI;IAI3C;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE;CAG5C"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @fileoverview No-authentication provider for development and testing.
3
+ *
4
+ * This provider bypasses all authentication checks and returns a configurable
5
+ * anonymous user for all requests. Use only in development or testing environments.
6
+ *
7
+ * WARNING: Never use this provider in production!
8
+ */
9
+ /**
10
+ * Authentication provider that bypasses authentication.
11
+ *
12
+ * All requests are treated as authenticated with a configurable anonymous user.
13
+ * This provider is useful for development and testing when you don't want to
14
+ * set up authentication infrastructure.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // Development setup
19
+ * const provider = new NoAuthProvider('dev-user-123')
20
+ *
21
+ * // All requests return the same user
22
+ * const user = provider.parseRequest(req) // { id: 'dev-user-123', roles: ['user'] }
23
+ * provider.hasValidAuth(req) // always true
24
+ * provider.isAdmin(req) // always false
25
+ * ```
26
+ */
27
+ export class NoAuthProvider {
28
+ #anonymousUserId;
29
+ #anonymousRoles;
30
+ /**
31
+ * Creates a new NoAuthProvider.
32
+ *
33
+ * @param anonymousUserId - User ID for the anonymous user (default: 'anonymous')
34
+ * @param anonymousRoles - Roles for the anonymous user (default: ['anonymous'])
35
+ */
36
+ constructor(anonymousUserId = 'anonymous', anonymousRoles = ['anonymous']) {
37
+ this.#anonymousUserId = anonymousUserId;
38
+ this.#anonymousRoles = anonymousRoles;
39
+ }
40
+ /**
41
+ * Returns the anonymous user for all requests.
42
+ *
43
+ * @returns Anonymous user with configured ID and roles
44
+ */
45
+ parseRequest(_req) {
46
+ return {
47
+ id: this.#anonymousUserId,
48
+ roles: this.#anonymousRoles
49
+ };
50
+ }
51
+ /**
52
+ * Always returns true (all requests are "authenticated").
53
+ */
54
+ hasValidAuth(_req) {
55
+ return true;
56
+ }
57
+ /**
58
+ * Always returns false (anonymous user is never admin).
59
+ */
60
+ isAdmin(_req) {
61
+ return false;
62
+ }
63
+ /**
64
+ * Returns the anonymous user ID.
65
+ */
66
+ getUserId(_req) {
67
+ return this.#anonymousUserId;
68
+ }
69
+ /**
70
+ * Returns the anonymous user roles.
71
+ */
72
+ getUserRoles(_req) {
73
+ return this.#anonymousRoles;
74
+ }
75
+ }
76
+ //# sourceMappingURL=no_auth_provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no_auth_provider.js","sourceRoot":"","sources":["../../../src/auth/providers/no_auth_provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,cAAc;IACd,gBAAgB,CAAQ;IACxB,eAAe,CAAU;IAElC;;;;;OAKG;IACH,YAAY,eAAe,GAAG,WAAW,EAAE,iBAA2B,CAAC,WAAW,CAAC;QAC/E,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAA;QACvC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAA;IACzC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,IAAiB;QAC1B,OAAO;YACH,EAAE,EAAE,IAAI,CAAC,gBAAgB;YACzB,KAAK,EAAE,IAAI,CAAC,eAAe;SAC9B,CAAA;IACL,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAiB;QAC1B,OAAO,IAAI,CAAA;IACf,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAiB;QACrB,OAAO,KAAK,CAAA;IAChB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAAiB;QACvB,OAAO,IAAI,CAAC,gBAAgB,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAiB;QAC1B,OAAO,IAAI,CAAC,eAAe,CAAA;IAC/B,CAAC;CACJ"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * User information extracted from Keycloak JWT via Apache APISIX headers.
3
+ *
4
+ * This interface represents the authenticated user data parsed from APISIX
5
+ * headers after Keycloak authentication. APISIX forwards these headers:
6
+ * - `x-user-id`: The Keycloak user UUID
7
+ * - `x-user-roles`: Comma-separated list of user roles
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
12
+ * if (authUser) {
13
+ * console.log(`User ${authUser.id} has roles: ${authUser.roles.join(', ')}`)
14
+ * }
15
+ * ```
16
+ */
17
+ export interface AuthenticatedUser {
18
+ /** User ID from Keycloak (x-user-id header) - UUID format */
19
+ id: string;
20
+ /** User roles from Keycloak (x-user-roles header, parsed from comma-separated string) */
21
+ roles: string[];
22
+ }
23
+ /**
24
+ * User record stored in the database.
25
+ *
26
+ * Represents a user stored in the normalized user management system.
27
+ * Users are created automatically when they first access the system
28
+ * after being authenticated by Keycloak via APISIX.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const userService = new UserService(database)
33
+ * const userRecord = await userService.findOrCreateUser(authenticatedUser)
34
+ * console.log(`User ${userRecord.keycloak_id} has ${userRecord.roles.length} roles`)
35
+ * ```
36
+ */
37
+ export interface UserRecord {
38
+ /** Primary key (auto-increment) */
39
+ id?: number;
40
+ /** Keycloak user ID (UUID, unique across system) */
41
+ keycloak_id: string;
42
+ /** User roles (populated from user_roles junction table) */
43
+ roles: string[];
44
+ /** First time the user was seen in the system */
45
+ created_at: Date;
46
+ /** Last time the user's roles were updated */
47
+ updated_at: Date;
48
+ }
49
+ /**
50
+ * Authentication context passed to handlers.
51
+ *
52
+ * Contains both the raw authentication data from APISIX headers
53
+ * and the corresponding database user record. Used internally
54
+ * by components that need full user context.
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const authContext: AuthContext = {
59
+ * user: authUser,
60
+ * userRecord: await userService.findOrCreateUser(authUser)
61
+ * }
62
+ * ```
63
+ */
64
+ export interface AuthContext {
65
+ /** Authenticated user information from APISIX headers */
66
+ user: AuthenticatedUser;
67
+ /** Database user record with full role information */
68
+ userRecord: UserRecord;
69
+ }
70
+ /**
71
+ * Request object extended with authentication context.
72
+ *
73
+ * Represents an HTTP request that has been augmented with
74
+ * authentication information. Used by handlers that need
75
+ * access to both request data and user context.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * async function handleRequest(req: AuthenticatedRequest) {
80
+ * if (req.auth) {
81
+ * console.log(`Request from user: ${req.auth.user.id}`)
82
+ * }
83
+ * }
84
+ * ```
85
+ */
86
+ export interface AuthenticatedRequest {
87
+ /** Original Express request object */
88
+ originalRequest: any;
89
+ /** Authentication context (undefined if not authenticated) */
90
+ auth?: AuthContext;
91
+ /** Request headers (including APISIX authentication headers) */
92
+ headers: Record<string, string>;
93
+ /** URL parameters */
94
+ params?: Record<string, string>;
95
+ /** Request body */
96
+ body?: any;
97
+ /** File upload (for multipart requests with assets) */
98
+ file?: any;
99
+ }
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,iBAAiB;IAC9B,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAA;IACV,yFAAyF;IACzF,KAAK,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAU;IACvB,mCAAmC;IACnC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,iDAAiD;IACjD,UAAU,EAAE,IAAI,CAAA;IAChB,8CAA8C;IAC9C,UAAU,EAAE,IAAI,CAAA;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IACxB,yDAAyD;IACzD,IAAI,EAAE,iBAAiB,CAAA;IACvB,sDAAsD;IACtD,UAAU,EAAE,UAAU,CAAA;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,oBAAoB;IACjC,sCAAsC;IACtC,eAAe,EAAE,GAAG,CAAA;IACpB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,mBAAmB;IACnB,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,uDAAuD;IACvD,IAAI,CAAC,EAAE,GAAG,CAAA;CACb"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ import type { DatabaseAdapter } from '../database/database_adapter.js';
2
+ import type { AuthenticatedUser, UserRecord } from './types.js';
3
+ /**
4
+ * Service for managing users in the Digital Twin framework.
5
+ *
6
+ * This service handles the complete user lifecycle in a Digital Twin application
7
+ * with Keycloak authentication via Apache APISIX. It manages a normalized database
8
+ * schema with three tables:
9
+ *
10
+ * - `users`: Core user records linked to Keycloak IDs
11
+ * - `roles`: Master list of available roles
12
+ * - `user_roles`: Many-to-many relationship between users and roles
13
+ *
14
+ * Key features:
15
+ * - Automatic user creation on first authentication
16
+ * - Role synchronization with Keycloak
17
+ * - Optimized queries with proper indexing
18
+ * - Transaction-safe role updates
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Initialize in your Digital Twin engine
23
+ * const userService = new UserService(databaseAdapter)
24
+ * await userService.initializeTables()
25
+ *
26
+ * // Use in AssetsManager handlers
27
+ * const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
28
+ * const userRecord = await userService.findOrCreateUser(authUser!)
29
+ *
30
+ * // Link assets to users
31
+ * await this.uploadAsset({
32
+ * description: 'My file',
33
+ * source: 'upload',
34
+ * owner_id: userRecord.id!.toString(),
35
+ * filename: 'document.pdf',
36
+ * file: buffer
37
+ * })
38
+ * ```
39
+ */
40
+ export declare class UserService {
41
+ private db;
42
+ private readonly usersTable;
43
+ private readonly rolesTable;
44
+ private readonly userRolesTable;
45
+ constructor(db: DatabaseAdapter);
46
+ /**
47
+ * Ensures all user-related tables exist in the database
48
+ */
49
+ initializeTables(): Promise<void>;
50
+ /**
51
+ * Finds or creates a user and synchronizes their roles.
52
+ *
53
+ * When authentication is disabled, returns a mock user record
54
+ * without touching the database.
55
+ */
56
+ findOrCreateUser(authUser: AuthenticatedUser): Promise<UserRecord>;
57
+ /**
58
+ * Gets a user by their database ID
59
+ */
60
+ getUserById(id: number): Promise<UserRecord | undefined>;
61
+ /**
62
+ * Gets a user by their Keycloak ID with roles
63
+ */
64
+ getUserByKeycloakId(keycloakId: string): Promise<UserRecord | undefined>;
65
+ /**
66
+ * Gets the underlying Knex instance from the database adapter
67
+ */
68
+ private getKnex;
69
+ /**
70
+ * Finds a user by their Keycloak ID
71
+ */
72
+ private findUserByKeycloakId;
73
+ /**
74
+ * Creates a new user record
75
+ */
76
+ private createUser;
77
+ /**
78
+ * Synchronizes user roles with what's provided by Keycloak
79
+ */
80
+ private syncUserRoles;
81
+ /**
82
+ * Gets a user with their roles populated
83
+ */
84
+ private getUserWithRoles;
85
+ }
86
+ //# sourceMappingURL=user_service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user_service.d.ts","sourceRoot":"","sources":["../../src/auth/user_service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAI/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAe;gBAElC,EAAE,EAAE,eAAe;IAI/B;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDvC;;;;;OAKG;IACG,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BxE;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAI9D;;OAEG;IACG,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAY9E;;OAEG;IACH,OAAO,CAAC,OAAO;IAOf;;OAEG;YACW,oBAAoB;IAgBlC;;OAEG;YACW,UAAU;IAuBxB;;OAEG;YACW,aAAa;IAoC3B;;OAEG;YACW,gBAAgB;CAqCjC"}