@constructive-io/graphql-server 5.12.2 → 5.13.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.
- package/esm/middleware/api.js +13 -8
- package/esm/middleware/graphile.js +28 -0
- package/middleware/api.js +13 -8
- package/middleware/graphile.js +28 -0
- package/package.json +14 -14
package/esm/middleware/api.js
CHANGED
|
@@ -41,14 +41,19 @@ const scopedApiNameLookupSql = (routingSchema) => `
|
|
|
41
41
|
* Build a LoaderContext from the API row and options.
|
|
42
42
|
* This is used to resolve per-database module settings via the loader registry.
|
|
43
43
|
*/
|
|
44
|
-
const buildLoaderContext = (routingPool, opts, row) =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
})
|
|
44
|
+
const buildLoaderContext = (routingPool, opts, row) => {
|
|
45
|
+
// Scoped APIs leave dbname NULL when their schemas live in the serving
|
|
46
|
+
// database (pooled tenants); fall back to the server's own database.
|
|
47
|
+
const dbname = row.dbname || opts.pg?.database || '';
|
|
48
|
+
return {
|
|
49
|
+
routingPool,
|
|
50
|
+
routingSchema: getRoutingSchema(opts),
|
|
51
|
+
tenantPool: getPgPool({ ...opts.pg, database: dbname }),
|
|
52
|
+
databaseId: row.database_id,
|
|
53
|
+
apiId: row.api_id,
|
|
54
|
+
dbname
|
|
55
|
+
};
|
|
56
|
+
};
|
|
52
57
|
/**
|
|
53
58
|
* Resolve all per-database module settings in parallel via the loader registry.
|
|
54
59
|
* Each loader independently caches by databaseId — repeated calls are cheap.
|
|
@@ -225,6 +225,34 @@ const buildPreset = (pool, schemas, anonRole, roleName, databaseSettings, apiId,
|
|
|
225
225
|
}
|
|
226
226
|
return { pgSettings };
|
|
227
227
|
}
|
|
228
|
+
// Private (in-cluster) surface: there is no token — identity
|
|
229
|
+
// arrives on the trusted internal X-* headers stamped by the
|
|
230
|
+
// dispatching worker/sync gateway (the same vocabulary as
|
|
231
|
+
// X-Database-Id above). Map it into per-request claims so writes
|
|
232
|
+
// made through this surface carry actor attribution. Never applied
|
|
233
|
+
// on the public surface, where client-supplied identity headers
|
|
234
|
+
// must not assert identity.
|
|
235
|
+
const headerActorId = req.get('X-Actor-Id');
|
|
236
|
+
if (req.api?.isPublic === false && headerActorId) {
|
|
237
|
+
const pgSettings = {
|
|
238
|
+
role: roleName,
|
|
239
|
+
'jwt.claims.user_id': headerActorId,
|
|
240
|
+
'jwt.claims.principal_id': headerActorId,
|
|
241
|
+
...context
|
|
242
|
+
};
|
|
243
|
+
const headerEntityId = req.get('X-Entity-Id');
|
|
244
|
+
if (headerEntityId) {
|
|
245
|
+
pgSettings['jwt.claims.entity_id'] = headerEntityId;
|
|
246
|
+
}
|
|
247
|
+
const headerOrganizationId = req.get('X-Organization-Id');
|
|
248
|
+
if (headerOrganizationId) {
|
|
249
|
+
pgSettings['jwt.claims.organization_id'] = headerOrganizationId;
|
|
250
|
+
}
|
|
251
|
+
if (req.requestId) {
|
|
252
|
+
pgSettings['request.id'] = req.requestId;
|
|
253
|
+
}
|
|
254
|
+
return { pgSettings };
|
|
255
|
+
}
|
|
228
256
|
}
|
|
229
257
|
const anonSettings = {
|
|
230
258
|
role: anonRole,
|
package/middleware/api.js
CHANGED
|
@@ -47,14 +47,19 @@ const scopedApiNameLookupSql = (routingSchema) => `
|
|
|
47
47
|
* Build a LoaderContext from the API row and options.
|
|
48
48
|
* This is used to resolve per-database module settings via the loader registry.
|
|
49
49
|
*/
|
|
50
|
-
const buildLoaderContext = (routingPool, opts, row) =>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
50
|
+
const buildLoaderContext = (routingPool, opts, row) => {
|
|
51
|
+
// Scoped APIs leave dbname NULL when their schemas live in the serving
|
|
52
|
+
// database (pooled tenants); fall back to the server's own database.
|
|
53
|
+
const dbname = row.dbname || opts.pg?.database || '';
|
|
54
|
+
return {
|
|
55
|
+
routingPool,
|
|
56
|
+
routingSchema: (0, routing_1.getRoutingSchema)(opts),
|
|
57
|
+
tenantPool: (0, pg_cache_1.getPgPool)({ ...opts.pg, database: dbname }),
|
|
58
|
+
databaseId: row.database_id,
|
|
59
|
+
apiId: row.api_id,
|
|
60
|
+
dbname
|
|
61
|
+
};
|
|
62
|
+
};
|
|
58
63
|
/**
|
|
59
64
|
* Resolve all per-database module settings in parallel via the loader registry.
|
|
60
65
|
* Each loader independently caches by databaseId — repeated calls are cheap.
|
package/middleware/graphile.js
CHANGED
|
@@ -234,6 +234,34 @@ const buildPreset = (pool, schemas, anonRole, roleName, databaseSettings, apiId,
|
|
|
234
234
|
}
|
|
235
235
|
return { pgSettings };
|
|
236
236
|
}
|
|
237
|
+
// Private (in-cluster) surface: there is no token — identity
|
|
238
|
+
// arrives on the trusted internal X-* headers stamped by the
|
|
239
|
+
// dispatching worker/sync gateway (the same vocabulary as
|
|
240
|
+
// X-Database-Id above). Map it into per-request claims so writes
|
|
241
|
+
// made through this surface carry actor attribution. Never applied
|
|
242
|
+
// on the public surface, where client-supplied identity headers
|
|
243
|
+
// must not assert identity.
|
|
244
|
+
const headerActorId = req.get('X-Actor-Id');
|
|
245
|
+
if (req.api?.isPublic === false && headerActorId) {
|
|
246
|
+
const pgSettings = {
|
|
247
|
+
role: roleName,
|
|
248
|
+
'jwt.claims.user_id': headerActorId,
|
|
249
|
+
'jwt.claims.principal_id': headerActorId,
|
|
250
|
+
...context
|
|
251
|
+
};
|
|
252
|
+
const headerEntityId = req.get('X-Entity-Id');
|
|
253
|
+
if (headerEntityId) {
|
|
254
|
+
pgSettings['jwt.claims.entity_id'] = headerEntityId;
|
|
255
|
+
}
|
|
256
|
+
const headerOrganizationId = req.get('X-Organization-Id');
|
|
257
|
+
if (headerOrganizationId) {
|
|
258
|
+
pgSettings['jwt.claims.organization_id'] = headerOrganizationId;
|
|
259
|
+
}
|
|
260
|
+
if (req.requestId) {
|
|
261
|
+
pgSettings['request.id'] = req.requestId;
|
|
262
|
+
}
|
|
263
|
+
return { pgSettings };
|
|
264
|
+
}
|
|
237
265
|
}
|
|
238
266
|
const anonSettings = {
|
|
239
267
|
role: anonRole,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.13.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive GraphQL Server",
|
|
6
6
|
"main": "index.js",
|
|
@@ -43,18 +43,18 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@constructive-io/csrf": "^0.25.0",
|
|
45
45
|
"@constructive-io/errors": "^0.7.1",
|
|
46
|
-
"@constructive-io/express-context": "^0.22.
|
|
47
|
-
"@constructive-io/graphql-env": "^3.27.
|
|
48
|
-
"@constructive-io/graphql-types": "^3.26.
|
|
46
|
+
"@constructive-io/express-context": "^0.22.3",
|
|
47
|
+
"@constructive-io/graphql-env": "^3.27.3",
|
|
48
|
+
"@constructive-io/graphql-types": "^3.26.3",
|
|
49
49
|
"@constructive-io/query-builder": "^3.8.0",
|
|
50
50
|
"@constructive-io/s3-utils": "^2.28.0",
|
|
51
51
|
"@constructive-io/url-domains": "^2.27.0",
|
|
52
52
|
"@graphile-contrib/pg-many-to-many": "2.0.0-rc.2",
|
|
53
|
-
"@pgpmjs/env": "^2.
|
|
53
|
+
"@pgpmjs/env": "^2.39.1",
|
|
54
54
|
"@pgpmjs/logger": "^2.22.0",
|
|
55
|
-
"@pgpmjs/server-utils": "^3.23.
|
|
56
|
-
"@pgpmjs/types": "^2.
|
|
57
|
-
"agentic-server": "0.20.
|
|
55
|
+
"@pgpmjs/server-utils": "^3.23.3",
|
|
56
|
+
"@pgpmjs/types": "^2.48.0",
|
|
57
|
+
"agentic-server": "0.20.3",
|
|
58
58
|
"cors": "^2.8.6",
|
|
59
59
|
"deepmerge": "^4.3.1",
|
|
60
60
|
"express": "^5.2.1",
|
|
@@ -63,16 +63,16 @@
|
|
|
63
63
|
"grafserv": "1.0.0",
|
|
64
64
|
"graphile-build": "5.0.2",
|
|
65
65
|
"graphile-build-pg": "5.0.2",
|
|
66
|
-
"graphile-cache": "^4.8.
|
|
66
|
+
"graphile-cache": "^4.8.3",
|
|
67
67
|
"graphile-config": "1.0.1",
|
|
68
|
-
"graphile-function-bindings": "^1.9.
|
|
69
|
-
"graphile-settings": "^6.9.
|
|
68
|
+
"graphile-function-bindings": "^1.9.4",
|
|
69
|
+
"graphile-settings": "^6.9.4",
|
|
70
70
|
"graphile-utils": "5.0.1",
|
|
71
71
|
"graphql": "16.13.0",
|
|
72
72
|
"graphql-upload": "^13.0.0",
|
|
73
73
|
"lru-cache": "^11.2.7",
|
|
74
74
|
"pg": "^8.21.0",
|
|
75
|
-
"pg-cache": "^3.23.
|
|
75
|
+
"pg-cache": "^3.23.3",
|
|
76
76
|
"pg-env": "^1.26.0",
|
|
77
77
|
"pg-query-context": "^2.27.0",
|
|
78
78
|
"pg-sql2": "5.0.1",
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
"@types/pg": "^8.20.0",
|
|
89
89
|
"@types/request-ip": "^0.0.41",
|
|
90
90
|
"cookie-parser": "^1.4.7",
|
|
91
|
-
"graphile-test": "5.9.
|
|
91
|
+
"graphile-test": "5.9.4",
|
|
92
92
|
"makage": "^0.3.0",
|
|
93
93
|
"nodemon": "^3.1.14",
|
|
94
94
|
"ts-node": "^10.9.2"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "2832d5632d11eb22e1437df773706ac6a99175fe"
|
|
97
97
|
}
|