digitaltwin-core 0.14.0 → 0.14.2
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.
- package/README.md +2 -2
- package/package.json +102 -106
- package/dist/auth/apisix_parser.d.ts +0 -146
- package/dist/auth/apisix_parser.d.ts.map +0 -1
- package/dist/auth/apisix_parser.js +0 -185
- package/dist/auth/apisix_parser.js.map +0 -1
- package/dist/auth/auth_config.d.ts +0 -126
- package/dist/auth/auth_config.d.ts.map +0 -1
- package/dist/auth/auth_config.js +0 -169
- package/dist/auth/auth_config.js.map +0 -1
- package/dist/auth/index.d.ts +0 -5
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -4
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/types.d.ts +0 -100
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js +0 -2
- package/dist/auth/types.js.map +0 -1
- package/dist/auth/user_service.d.ts +0 -86
- package/dist/auth/user_service.d.ts.map +0 -1
- package/dist/auth/user_service.js +0 -237
- package/dist/auth/user_service.js.map +0 -1
- package/dist/components/assets_manager.d.ts +0 -662
- package/dist/components/assets_manager.d.ts.map +0 -1
- package/dist/components/assets_manager.js +0 -1529
- package/dist/components/assets_manager.js.map +0 -1
- package/dist/components/async_upload.d.ts +0 -20
- package/dist/components/async_upload.d.ts.map +0 -1
- package/dist/components/async_upload.js +0 -10
- package/dist/components/async_upload.js.map +0 -1
- package/dist/components/collector.d.ts +0 -203
- package/dist/components/collector.d.ts.map +0 -1
- package/dist/components/collector.js +0 -202
- package/dist/components/collector.js.map +0 -1
- package/dist/components/custom_table_manager.d.ts +0 -503
- package/dist/components/custom_table_manager.d.ts.map +0 -1
- package/dist/components/custom_table_manager.js +0 -1052
- package/dist/components/custom_table_manager.js.map +0 -1
- package/dist/components/global_assets_handler.d.ts +0 -63
- package/dist/components/global_assets_handler.d.ts.map +0 -1
- package/dist/components/global_assets_handler.js +0 -127
- package/dist/components/global_assets_handler.js.map +0 -1
- package/dist/components/handler.d.ts +0 -104
- package/dist/components/handler.d.ts.map +0 -1
- package/dist/components/handler.js +0 -110
- package/dist/components/handler.js.map +0 -1
- package/dist/components/harvester.d.ts +0 -182
- package/dist/components/harvester.d.ts.map +0 -1
- package/dist/components/harvester.js +0 -393
- package/dist/components/harvester.js.map +0 -1
- package/dist/components/index.d.ts +0 -11
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js +0 -9
- package/dist/components/index.js.map +0 -1
- package/dist/components/interfaces.d.ts +0 -126
- package/dist/components/interfaces.d.ts.map +0 -1
- package/dist/components/interfaces.js +0 -8
- package/dist/components/interfaces.js.map +0 -1
- package/dist/components/map_manager.d.ts +0 -61
- package/dist/components/map_manager.d.ts.map +0 -1
- package/dist/components/map_manager.js +0 -242
- package/dist/components/map_manager.js.map +0 -1
- package/dist/components/tileset_manager.d.ts +0 -125
- package/dist/components/tileset_manager.d.ts.map +0 -1
- package/dist/components/tileset_manager.js +0 -618
- package/dist/components/tileset_manager.js.map +0 -1
- package/dist/components/types.d.ts +0 -226
- package/dist/components/types.d.ts.map +0 -1
- package/dist/components/types.js +0 -8
- package/dist/components/types.js.map +0 -1
- package/dist/database/adapters/knex_database_adapter.d.ts +0 -92
- package/dist/database/adapters/knex_database_adapter.d.ts.map +0 -1
- package/dist/database/adapters/knex_database_adapter.js +0 -647
- package/dist/database/adapters/knex_database_adapter.js.map +0 -1
- package/dist/database/database_adapter.d.ts +0 -251
- package/dist/database/database_adapter.d.ts.map +0 -1
- package/dist/database/database_adapter.js +0 -46
- package/dist/database/database_adapter.js.map +0 -1
- package/dist/engine/digital_twin_engine.d.ts +0 -253
- package/dist/engine/digital_twin_engine.d.ts.map +0 -1
- package/dist/engine/digital_twin_engine.js +0 -790
- package/dist/engine/digital_twin_engine.js.map +0 -1
- package/dist/engine/endpoints.d.ts +0 -47
- package/dist/engine/endpoints.d.ts.map +0 -1
- package/dist/engine/endpoints.js +0 -56
- package/dist/engine/endpoints.js.map +0 -1
- package/dist/engine/events.d.ts +0 -93
- package/dist/engine/events.d.ts.map +0 -1
- package/dist/engine/events.js +0 -71
- package/dist/engine/events.js.map +0 -1
- package/dist/engine/initializer.d.ts +0 -62
- package/dist/engine/initializer.d.ts.map +0 -1
- package/dist/engine/initializer.js +0 -108
- package/dist/engine/initializer.js.map +0 -1
- package/dist/engine/queue_manager.d.ts +0 -87
- package/dist/engine/queue_manager.d.ts.map +0 -1
- package/dist/engine/queue_manager.js +0 -196
- package/dist/engine/queue_manager.js.map +0 -1
- package/dist/engine/scheduler.d.ts +0 -30
- package/dist/engine/scheduler.d.ts.map +0 -1
- package/dist/engine/scheduler.js +0 -370
- package/dist/engine/scheduler.js.map +0 -1
- package/dist/engine/upload_processor.d.ts +0 -36
- package/dist/engine/upload_processor.d.ts.map +0 -1
- package/dist/engine/upload_processor.js +0 -101
- package/dist/engine/upload_processor.js.map +0 -1
- package/dist/env/env.d.ts +0 -134
- package/dist/env/env.d.ts.map +0 -1
- package/dist/env/env.js +0 -177
- package/dist/env/env.js.map +0 -1
- package/dist/index.d.ts +0 -49
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -57
- package/dist/index.js.map +0 -1
- package/dist/openapi/generator.d.ts +0 -93
- package/dist/openapi/generator.d.ts.map +0 -1
- package/dist/openapi/generator.js +0 -293
- package/dist/openapi/generator.js.map +0 -1
- package/dist/openapi/index.d.ts +0 -9
- package/dist/openapi/index.d.ts.map +0 -1
- package/dist/openapi/index.js +0 -9
- package/dist/openapi/index.js.map +0 -1
- package/dist/openapi/types.d.ts +0 -182
- package/dist/openapi/types.d.ts.map +0 -1
- package/dist/openapi/types.js +0 -16
- package/dist/openapi/types.js.map +0 -1
- package/dist/storage/adapters/local_storage_service.d.ts +0 -51
- package/dist/storage/adapters/local_storage_service.d.ts.map +0 -1
- package/dist/storage/adapters/local_storage_service.js +0 -110
- package/dist/storage/adapters/local_storage_service.js.map +0 -1
- package/dist/storage/adapters/ovh_storage_service.d.ts +0 -72
- package/dist/storage/adapters/ovh_storage_service.d.ts.map +0 -1
- package/dist/storage/adapters/ovh_storage_service.js +0 -206
- package/dist/storage/adapters/ovh_storage_service.js.map +0 -1
- package/dist/storage/storage_factory.d.ts +0 -14
- package/dist/storage/storage_factory.d.ts.map +0 -1
- package/dist/storage/storage_factory.js +0 -40
- package/dist/storage/storage_factory.js.map +0 -1
- package/dist/storage/storage_service.d.ts +0 -163
- package/dist/storage/storage_service.d.ts.map +0 -1
- package/dist/storage/storage_service.js +0 -54
- package/dist/storage/storage_service.js.map +0 -1
- package/dist/types/data_record.d.ts +0 -123
- package/dist/types/data_record.d.ts.map +0 -1
- package/dist/types/data_record.js +0 -8
- package/dist/types/data_record.js.map +0 -1
- package/dist/utils/http_responses.d.ts +0 -155
- package/dist/utils/http_responses.d.ts.map +0 -1
- package/dist/utils/http_responses.js +0 -190
- package/dist/utils/http_responses.js.map +0 -1
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -6
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -74
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -92
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/map_to_data_record.d.ts +0 -10
- package/dist/utils/map_to_data_record.d.ts.map +0 -1
- package/dist/utils/map_to_data_record.js +0 -36
- package/dist/utils/map_to_data_record.js.map +0 -1
- package/dist/utils/servable_endpoint.d.ts +0 -63
- package/dist/utils/servable_endpoint.d.ts.map +0 -1
- package/dist/utils/servable_endpoint.js +0 -67
- package/dist/utils/servable_endpoint.js.map +0 -1
- package/dist/utils/zip_utils.d.ts +0 -66
- package/dist/utils/zip_utils.d.ts.map +0 -1
- package/dist/utils/zip_utils.js +0 -169
- package/dist/utils/zip_utils.js.map +0 -1
package/README.md
CHANGED
|
@@ -16,10 +16,10 @@ Digital Twin Core is a minimalist TypeScript framework used to collect and proce
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
19
|
+
pnpm add digitaltwin-core
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
The project requires Node.js
|
|
22
|
+
The project requires Node.js 20 or later.
|
|
23
23
|
|
|
24
24
|
## Building
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -1,106 +1,102 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "digitaltwin-core",
|
|
3
|
-
"version": "0.14.
|
|
4
|
-
"description": "Minimalist framework to collect and handle data in a Digital Twin project",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Axel Hoffmann",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "./dist/index.js",
|
|
9
|
-
"types": "./dist/index.d.ts",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"import": "./dist/index.js",
|
|
13
|
-
"types": "./dist/index.d.ts"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"dist/",
|
|
18
|
-
"README.md",
|
|
19
|
-
"LICENSE"
|
|
20
|
-
],
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
},
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"ultimate-express": "^2.0.9",
|
|
104
|
-
"uuid": "^11.1.0"
|
|
105
|
-
}
|
|
106
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "digitaltwin-core",
|
|
3
|
+
"version": "0.14.2",
|
|
4
|
+
"description": "Minimalist framework to collect and handle data in a Digital Twin project",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Axel Hoffmann",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist/",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"digital twin",
|
|
23
|
+
"data",
|
|
24
|
+
"framework",
|
|
25
|
+
"typescript",
|
|
26
|
+
"iot",
|
|
27
|
+
"real-time"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/CePseudoBE/digitaltwin.git",
|
|
32
|
+
"directory": "digitaltwin-core"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/CePseudoBE/digitaltwin/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/CePseudoBE/digitaltwin/tree/main/digitaltwin-core#readme",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@eslint/js": "^9.0.0",
|
|
43
|
+
"@japa/assert": "^4.1.0",
|
|
44
|
+
"@japa/runner": "^4.3.0",
|
|
45
|
+
"@testcontainers/redis": "^11.3.1",
|
|
46
|
+
"@types/cors": "^2.8.19",
|
|
47
|
+
"@types/ioredis-mock": "^8.2.6",
|
|
48
|
+
"@types/jszip": "^3.4.0",
|
|
49
|
+
"@types/lodash": "^4.17.20",
|
|
50
|
+
"@types/multer": "^2.0.0",
|
|
51
|
+
"@types/uuid": "^10.0.0",
|
|
52
|
+
"eslint": "^9.0.0",
|
|
53
|
+
"globals": "^15.0.0",
|
|
54
|
+
"prettier": "^3.0.0",
|
|
55
|
+
"testcontainers": "^11.3.1",
|
|
56
|
+
"ts-node-maintained": "^10.9.5",
|
|
57
|
+
"typescript-eslint": "^8.0.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"better-sqlite3": "^12.2.0",
|
|
61
|
+
"knex": "^3.0.0",
|
|
62
|
+
"mysql2": "*",
|
|
63
|
+
"pg": "*",
|
|
64
|
+
"sqlite3": "^5.1.7"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"pg": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"mysql2": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"sqlite3": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"better-sqlite3": {
|
|
77
|
+
"optional": true
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@aws-sdk/client-s3": "^3.850.0",
|
|
82
|
+
"bullmq": "^5.56.5",
|
|
83
|
+
"cors": "^2.8.5",
|
|
84
|
+
"ioredis": "^5.6.1",
|
|
85
|
+
"jszip": "^3.10.1",
|
|
86
|
+
"lodash": "^4.17.21",
|
|
87
|
+
"multer": "^2.0.2",
|
|
88
|
+
"ultimate-express": "^2.0.9",
|
|
89
|
+
"uuid": "^11.1.0"
|
|
90
|
+
},
|
|
91
|
+
"scripts": {
|
|
92
|
+
"build": "tsc",
|
|
93
|
+
"dev": "tsc --watch",
|
|
94
|
+
"clean": "rimraf dist",
|
|
95
|
+
"test": "node -r ./bin/set-test-env.cjs --import ts-node-maintained/register/esm --enable-source-maps bin/test.ts",
|
|
96
|
+
"lint": "eslint src/**/*.ts",
|
|
97
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
98
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
99
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
100
|
+
"check": "npm run lint && npm run format:check && npm run build"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { AuthenticatedUser } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Parses authentication information from Apache APISIX headers set after Keycloak authentication.
|
|
4
|
-
*
|
|
5
|
-
* This class handles the parsing of authentication headers forwarded by Apache APISIX
|
|
6
|
-
* after successful Keycloak authentication. APISIX acts as a gateway that:
|
|
7
|
-
* 1. Validates JWT tokens with Keycloak
|
|
8
|
-
* 2. Extracts user information from the token
|
|
9
|
-
* 3. Forwards user data as HTTP headers to downstream services
|
|
10
|
-
*
|
|
11
|
-
* Authentication can be disabled via environment variables for development/testing:
|
|
12
|
-
* - Set DIGITALTWIN_DISABLE_AUTH=true to bypass authentication checks
|
|
13
|
-
* - Set DIGITALTWIN_ANONYMOUS_USER_ID=custom-id to use a custom anonymous user ID
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* // In an AssetsManager handler
|
|
18
|
-
* if (!ApisixAuthParser.hasValidAuth(req.headers)) {
|
|
19
|
-
* return { status: 401, content: 'Authentication required' }
|
|
20
|
-
* }
|
|
21
|
-
*
|
|
22
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
|
|
23
|
-
* const userRecord = await this.userService.findOrCreateUser(authUser!)
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export declare class ApisixAuthParser {
|
|
27
|
-
/**
|
|
28
|
-
* Extracts user information from APISIX headers.
|
|
29
|
-
*
|
|
30
|
-
* Parses the authentication headers forwarded by APISIX:
|
|
31
|
-
* - `x-user-id`: Keycloak user UUID (required)
|
|
32
|
-
* - `x-user-roles`: Comma-separated list of user roles (optional)
|
|
33
|
-
*
|
|
34
|
-
* When authentication is disabled (DIGITALTWIN_DISABLE_AUTH=true),
|
|
35
|
-
* returns a default anonymous user instead of requiring headers.
|
|
36
|
-
*
|
|
37
|
-
* @param headers - HTTP request headers from APISIX
|
|
38
|
-
* @returns Parsed user authentication data, or null if x-user-id is missing and auth is enabled
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* const headers = {
|
|
43
|
-
* 'x-user-id': '6e06a527-a89d-4390-95cd-10ae63cfc939',
|
|
44
|
-
* 'x-user-roles': 'default-roles-master,offline_access'
|
|
45
|
-
* }
|
|
46
|
-
*
|
|
47
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(headers)
|
|
48
|
-
* // Returns: { id: '6e06a527...', roles: ['default-roles-master', 'offline_access'] }
|
|
49
|
-
*
|
|
50
|
-
* // With DIGITALTWIN_DISABLE_AUTH=true
|
|
51
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders({})
|
|
52
|
-
* // Returns: { id: 'anonymous', roles: ['anonymous'] }
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
static parseAuthHeaders(headers: Record<string, string>): AuthenticatedUser | null;
|
|
56
|
-
/**
|
|
57
|
-
* Checks if a request has valid authentication headers.
|
|
58
|
-
*
|
|
59
|
-
* Performs a quick validation to determine if the request contains
|
|
60
|
-
* the minimum required authentication information (x-user-id header).
|
|
61
|
-
* Use this for early authentication checks before parsing.
|
|
62
|
-
*
|
|
63
|
-
* When authentication is disabled (DIGITALTWIN_DISABLE_AUTH=true),
|
|
64
|
-
* this always returns true to allow all requests through.
|
|
65
|
-
*
|
|
66
|
-
* @param headers - HTTP request headers
|
|
67
|
-
* @returns true if x-user-id header is present or auth is disabled, false otherwise
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* // Early authentication check in handler
|
|
72
|
-
* if (!ApisixAuthParser.hasValidAuth(req.headers)) {
|
|
73
|
-
* return { status: 401, content: 'Authentication required' }
|
|
74
|
-
* }
|
|
75
|
-
*
|
|
76
|
-
* // Now safe to proceed with parsing
|
|
77
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
static hasValidAuth(headers: Record<string, string>): boolean;
|
|
81
|
-
/**
|
|
82
|
-
* Extracts just the user ID from headers.
|
|
83
|
-
*
|
|
84
|
-
* Convenience method for cases where you only need the user ID
|
|
85
|
-
* without parsing the full authentication context.
|
|
86
|
-
*
|
|
87
|
-
* When authentication is disabled, returns the configured anonymous user ID.
|
|
88
|
-
*
|
|
89
|
-
* @param headers - HTTP request headers
|
|
90
|
-
* @returns Keycloak user ID, anonymous user ID if auth disabled, or null if not present
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```typescript
|
|
94
|
-
* const userId = ApisixAuthParser.getUserId(req.headers)
|
|
95
|
-
* if (userId) {
|
|
96
|
-
* console.log(`Request from user: ${userId}`)
|
|
97
|
-
* }
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
static getUserId(headers: Record<string, string>): string | null;
|
|
101
|
-
/**
|
|
102
|
-
* Extracts just the user roles from headers.
|
|
103
|
-
*
|
|
104
|
-
* Convenience method for cases where you only need the user roles
|
|
105
|
-
* without parsing the full authentication context.
|
|
106
|
-
*
|
|
107
|
-
* When authentication is disabled, returns the anonymous user roles.
|
|
108
|
-
*
|
|
109
|
-
* @param headers - HTTP request headers
|
|
110
|
-
* @returns Array of role names, anonymous roles if auth disabled, empty array if no roles header present
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```typescript
|
|
114
|
-
* const roles = ApisixAuthParser.getUserRoles(req.headers)
|
|
115
|
-
* if (roles.includes('admin')) {
|
|
116
|
-
* console.log('User has admin privileges')
|
|
117
|
-
* }
|
|
118
|
-
* ```
|
|
119
|
-
*/
|
|
120
|
-
static getUserRoles(headers: Record<string, string>): string[];
|
|
121
|
-
/**
|
|
122
|
-
* Checks if a user has the admin role.
|
|
123
|
-
*
|
|
124
|
-
* Determines if the authenticated user has administrative privileges by checking
|
|
125
|
-
* if their roles include the configured admin role name (default: "admin").
|
|
126
|
-
*
|
|
127
|
-
* The admin role name can be configured via DIGITALTWIN_ADMIN_ROLE_NAME environment variable.
|
|
128
|
-
*
|
|
129
|
-
* @param headers - HTTP request headers
|
|
130
|
-
* @returns true if user has admin role, false otherwise
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* ```typescript
|
|
134
|
-
* if (ApisixAuthParser.isAdmin(req.headers)) {
|
|
135
|
-
* // User has full administrative access
|
|
136
|
-
* // Can view all assets including private assets owned by others
|
|
137
|
-
* console.log('Admin user detected')
|
|
138
|
-
* }
|
|
139
|
-
*
|
|
140
|
-
* // With custom admin role name (DIGITALTWIN_ADMIN_ROLE_NAME=administrator)
|
|
141
|
-
* const isAdmin = ApisixAuthParser.isAdmin(req.headers)
|
|
142
|
-
* ```
|
|
143
|
-
*/
|
|
144
|
-
static isAdmin(headers: Record<string, string>): boolean;
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=apisix_parser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"apisix_parser.d.ts","sourceRoot":"","sources":["../../src/auth/apisix_parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGnD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,gBAAgB;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,iBAAiB,GAAG,IAAI;IAqBlF;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAS7D;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI;IAShE;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE;IAU9D;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;CAK3D"}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { AuthConfig } from './auth_config.js';
|
|
2
|
-
/**
|
|
3
|
-
* Parses authentication information from Apache APISIX headers set after Keycloak authentication.
|
|
4
|
-
*
|
|
5
|
-
* This class handles the parsing of authentication headers forwarded by Apache APISIX
|
|
6
|
-
* after successful Keycloak authentication. APISIX acts as a gateway that:
|
|
7
|
-
* 1. Validates JWT tokens with Keycloak
|
|
8
|
-
* 2. Extracts user information from the token
|
|
9
|
-
* 3. Forwards user data as HTTP headers to downstream services
|
|
10
|
-
*
|
|
11
|
-
* Authentication can be disabled via environment variables for development/testing:
|
|
12
|
-
* - Set DIGITALTWIN_DISABLE_AUTH=true to bypass authentication checks
|
|
13
|
-
* - Set DIGITALTWIN_ANONYMOUS_USER_ID=custom-id to use a custom anonymous user ID
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* // In an AssetsManager handler
|
|
18
|
-
* if (!ApisixAuthParser.hasValidAuth(req.headers)) {
|
|
19
|
-
* return { status: 401, content: 'Authentication required' }
|
|
20
|
-
* }
|
|
21
|
-
*
|
|
22
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
|
|
23
|
-
* const userRecord = await this.userService.findOrCreateUser(authUser!)
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export class ApisixAuthParser {
|
|
27
|
-
/**
|
|
28
|
-
* Extracts user information from APISIX headers.
|
|
29
|
-
*
|
|
30
|
-
* Parses the authentication headers forwarded by APISIX:
|
|
31
|
-
* - `x-user-id`: Keycloak user UUID (required)
|
|
32
|
-
* - `x-user-roles`: Comma-separated list of user roles (optional)
|
|
33
|
-
*
|
|
34
|
-
* When authentication is disabled (DIGITALTWIN_DISABLE_AUTH=true),
|
|
35
|
-
* returns a default anonymous user instead of requiring headers.
|
|
36
|
-
*
|
|
37
|
-
* @param headers - HTTP request headers from APISIX
|
|
38
|
-
* @returns Parsed user authentication data, or null if x-user-id is missing and auth is enabled
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* const headers = {
|
|
43
|
-
* 'x-user-id': '6e06a527-a89d-4390-95cd-10ae63cfc939',
|
|
44
|
-
* 'x-user-roles': 'default-roles-master,offline_access'
|
|
45
|
-
* }
|
|
46
|
-
*
|
|
47
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(headers)
|
|
48
|
-
* // Returns: { id: '6e06a527...', roles: ['default-roles-master', 'offline_access'] }
|
|
49
|
-
*
|
|
50
|
-
* // With DIGITALTWIN_DISABLE_AUTH=true
|
|
51
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders({})
|
|
52
|
-
* // Returns: { id: 'anonymous', roles: ['anonymous'] }
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
static parseAuthHeaders(headers) {
|
|
56
|
-
// If authentication is disabled, return anonymous user
|
|
57
|
-
if (AuthConfig.isAuthDisabled()) {
|
|
58
|
-
return AuthConfig.getAnonymousUser();
|
|
59
|
-
}
|
|
60
|
-
const userId = headers['x-user-id'];
|
|
61
|
-
if (!userId) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
// Parse roles from comma-separated string
|
|
65
|
-
const rolesString = headers['x-user-roles'] || '';
|
|
66
|
-
const roles = rolesString ? rolesString.split(',').map(role => role.trim()) : [];
|
|
67
|
-
return {
|
|
68
|
-
id: userId,
|
|
69
|
-
roles: roles
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Checks if a request has valid authentication headers.
|
|
74
|
-
*
|
|
75
|
-
* Performs a quick validation to determine if the request contains
|
|
76
|
-
* the minimum required authentication information (x-user-id header).
|
|
77
|
-
* Use this for early authentication checks before parsing.
|
|
78
|
-
*
|
|
79
|
-
* When authentication is disabled (DIGITALTWIN_DISABLE_AUTH=true),
|
|
80
|
-
* this always returns true to allow all requests through.
|
|
81
|
-
*
|
|
82
|
-
* @param headers - HTTP request headers
|
|
83
|
-
* @returns true if x-user-id header is present or auth is disabled, false otherwise
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* // Early authentication check in handler
|
|
88
|
-
* if (!ApisixAuthParser.hasValidAuth(req.headers)) {
|
|
89
|
-
* return { status: 401, content: 'Authentication required' }
|
|
90
|
-
* }
|
|
91
|
-
*
|
|
92
|
-
* // Now safe to proceed with parsing
|
|
93
|
-
* const authUser = ApisixAuthParser.parseAuthHeaders(req.headers)
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
static hasValidAuth(headers) {
|
|
97
|
-
// If authentication is disabled, all requests are valid
|
|
98
|
-
if (AuthConfig.isAuthDisabled()) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
return !!headers['x-user-id'];
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Extracts just the user ID from headers.
|
|
105
|
-
*
|
|
106
|
-
* Convenience method for cases where you only need the user ID
|
|
107
|
-
* without parsing the full authentication context.
|
|
108
|
-
*
|
|
109
|
-
* When authentication is disabled, returns the configured anonymous user ID.
|
|
110
|
-
*
|
|
111
|
-
* @param headers - HTTP request headers
|
|
112
|
-
* @returns Keycloak user ID, anonymous user ID if auth disabled, or null if not present
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```typescript
|
|
116
|
-
* const userId = ApisixAuthParser.getUserId(req.headers)
|
|
117
|
-
* if (userId) {
|
|
118
|
-
* console.log(`Request from user: ${userId}`)
|
|
119
|
-
* }
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
static getUserId(headers) {
|
|
123
|
-
// If authentication is disabled, return anonymous user ID
|
|
124
|
-
if (AuthConfig.isAuthDisabled()) {
|
|
125
|
-
return AuthConfig.getAnonymousUserId();
|
|
126
|
-
}
|
|
127
|
-
return headers['x-user-id'] || null;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Extracts just the user roles from headers.
|
|
131
|
-
*
|
|
132
|
-
* Convenience method for cases where you only need the user roles
|
|
133
|
-
* without parsing the full authentication context.
|
|
134
|
-
*
|
|
135
|
-
* When authentication is disabled, returns the anonymous user roles.
|
|
136
|
-
*
|
|
137
|
-
* @param headers - HTTP request headers
|
|
138
|
-
* @returns Array of role names, anonymous roles if auth disabled, empty array if no roles header present
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* ```typescript
|
|
142
|
-
* const roles = ApisixAuthParser.getUserRoles(req.headers)
|
|
143
|
-
* if (roles.includes('admin')) {
|
|
144
|
-
* console.log('User has admin privileges')
|
|
145
|
-
* }
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
static getUserRoles(headers) {
|
|
149
|
-
// If authentication is disabled, return anonymous user roles
|
|
150
|
-
if (AuthConfig.isAuthDisabled()) {
|
|
151
|
-
return AuthConfig.getAnonymousUser().roles;
|
|
152
|
-
}
|
|
153
|
-
const rolesString = headers['x-user-roles'] || '';
|
|
154
|
-
return rolesString ? rolesString.split(',').map(role => role.trim()) : [];
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Checks if a user has the admin role.
|
|
158
|
-
*
|
|
159
|
-
* Determines if the authenticated user has administrative privileges by checking
|
|
160
|
-
* if their roles include the configured admin role name (default: "admin").
|
|
161
|
-
*
|
|
162
|
-
* The admin role name can be configured via DIGITALTWIN_ADMIN_ROLE_NAME environment variable.
|
|
163
|
-
*
|
|
164
|
-
* @param headers - HTTP request headers
|
|
165
|
-
* @returns true if user has admin role, false otherwise
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```typescript
|
|
169
|
-
* if (ApisixAuthParser.isAdmin(req.headers)) {
|
|
170
|
-
* // User has full administrative access
|
|
171
|
-
* // Can view all assets including private assets owned by others
|
|
172
|
-
* console.log('Admin user detected')
|
|
173
|
-
* }
|
|
174
|
-
*
|
|
175
|
-
* // With custom admin role name (DIGITALTWIN_ADMIN_ROLE_NAME=administrator)
|
|
176
|
-
* const isAdmin = ApisixAuthParser.isAdmin(req.headers)
|
|
177
|
-
* ```
|
|
178
|
-
*/
|
|
179
|
-
static isAdmin(headers) {
|
|
180
|
-
const roles = this.getUserRoles(headers);
|
|
181
|
-
const adminRoleName = AuthConfig.getAdminRoleName();
|
|
182
|
-
return roles.includes(adminRoleName);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
//# sourceMappingURL=apisix_parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"apisix_parser.js","sourceRoot":"","sources":["../../src/auth/apisix_parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,gBAAgB;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAA+B;QACnD,uDAAuD;QACvD,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC,gBAAgB,EAAE,CAAA;QACxC,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;QACnC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,IAAI,CAAA;QACf,CAAC;QAED,0CAA0C;QAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QACjD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAEhF,OAAO;YACH,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,KAAK;SACf,CAAA;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,YAAY,CAAC,OAA+B;QAC/C,wDAAwD;QACxD,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAA;QACf,CAAC;QAED,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACjC,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,SAAS,CAAC,OAA+B;QAC5C,0DAA0D;QAC1D,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC,kBAAkB,EAAE,CAAA;QAC1C,CAAC;QAED,OAAO,OAAO,CAAC,WAAW,CAAC,IAAI,IAAI,CAAA;IACvC,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,YAAY,CAAC,OAA+B;QAC/C,6DAA6D;QAC7D,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAA;QAC9C,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QACjD,OAAO,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7E,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,OAAO,CAAC,OAA+B;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;QACxC,MAAM,aAAa,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAA;QACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;IACxC,CAAC;CACJ"}
|