@constructive-io/graphql-server 4.25.2 → 4.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/middleware/api.js +61 -6
- package/esm/middleware/upload.js +83 -0
- package/middleware/api.js +61 -6
- package/middleware/upload.js +83 -0
- package/package.json +4 -4
package/esm/middleware/api.js
CHANGED
|
@@ -75,6 +75,28 @@ const RLS_MODULE_SQL = `
|
|
|
75
75
|
WHERE api_id = $1 AND name = 'rls_module'
|
|
76
76
|
LIMIT 1
|
|
77
77
|
`;
|
|
78
|
+
const RLS_SETTINGS_SQL = `
|
|
79
|
+
SELECT
|
|
80
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
81
|
+
role_schema.schema_name AS role_schema,
|
|
82
|
+
auth_fn.name AS authenticate,
|
|
83
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
84
|
+
role_fn.name AS current_role,
|
|
85
|
+
role_id_fn.name AS current_role_id,
|
|
86
|
+
ua_fn.name AS current_user_agent,
|
|
87
|
+
ip_fn.name AS current_ip_address
|
|
88
|
+
FROM services_public.rls_settings rs
|
|
89
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
90
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
91
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
92
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
93
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
94
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
95
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
96
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
97
|
+
WHERE rs.database_id = $1
|
|
98
|
+
LIMIT 1
|
|
99
|
+
`;
|
|
78
100
|
/**
|
|
79
101
|
* Discover auth settings table location via public metaschema tables.
|
|
80
102
|
* Joins sessions_module with metaschema_public.schema to resolve
|
|
@@ -155,6 +177,24 @@ const toRlsModule = (row) => {
|
|
|
155
177
|
currentUserAgent: d.current_user_agent,
|
|
156
178
|
};
|
|
157
179
|
};
|
|
180
|
+
const toRlsModuleFromSettings = (row) => {
|
|
181
|
+
if (!row)
|
|
182
|
+
return undefined;
|
|
183
|
+
return {
|
|
184
|
+
authenticate: row.authenticate,
|
|
185
|
+
authenticateStrict: row.authenticate_strict,
|
|
186
|
+
privateSchema: {
|
|
187
|
+
schemaName: row.authenticate_schema,
|
|
188
|
+
},
|
|
189
|
+
publicSchema: {
|
|
190
|
+
schemaName: row.role_schema,
|
|
191
|
+
},
|
|
192
|
+
currentRole: row.current_role,
|
|
193
|
+
currentRoleId: row.current_role_id,
|
|
194
|
+
currentIpAddress: row.current_ip_address,
|
|
195
|
+
currentUserAgent: row.current_user_agent,
|
|
196
|
+
};
|
|
197
|
+
};
|
|
158
198
|
const toAuthSettings = (row) => {
|
|
159
199
|
if (!row)
|
|
160
200
|
return undefined;
|
|
@@ -169,14 +209,14 @@ const toAuthSettings = (row) => {
|
|
|
169
209
|
captchaSiteKey: row.captcha_site_key,
|
|
170
210
|
};
|
|
171
211
|
};
|
|
172
|
-
const toApiStructure = (row, opts,
|
|
212
|
+
const toApiStructure = (row, opts, rlsModule, authSettingsRow) => ({
|
|
173
213
|
apiId: row.api_id,
|
|
174
214
|
dbname: row.dbname || opts.pg?.database || '',
|
|
175
215
|
anonRole: row.anon_role || 'anon',
|
|
176
216
|
roleName: row.role_name || 'authenticated',
|
|
177
217
|
schema: row.schemas || [],
|
|
178
218
|
apiModules: [],
|
|
179
|
-
rlsModule
|
|
219
|
+
rlsModule,
|
|
180
220
|
domains: [],
|
|
181
221
|
databaseId: row.database_id,
|
|
182
222
|
isPublic: row.is_public,
|
|
@@ -211,9 +251,24 @@ const queryApiList = async (pool, isPublic) => {
|
|
|
211
251
|
const result = await pool.query(API_LIST_SQL, [isPublic]);
|
|
212
252
|
return result.rows;
|
|
213
253
|
};
|
|
214
|
-
const
|
|
254
|
+
const queryRlsSettings = async (pool, databaseId) => {
|
|
255
|
+
try {
|
|
256
|
+
const result = await pool.query(RLS_SETTINGS_SQL, [databaseId]);
|
|
257
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const queryRlsModuleLegacy = async (pool, apiId) => {
|
|
215
264
|
const result = await pool.query(RLS_MODULE_SQL, [apiId]);
|
|
216
|
-
return result.rows[0] ?? null;
|
|
265
|
+
return toRlsModule(result.rows[0] ?? null);
|
|
266
|
+
};
|
|
267
|
+
const queryRlsModule = async (pool, databaseId, apiId) => {
|
|
268
|
+
const fromSettings = await queryRlsSettings(pool, databaseId);
|
|
269
|
+
if (fromSettings)
|
|
270
|
+
return fromSettings;
|
|
271
|
+
return queryRlsModuleLegacy(pool, apiId);
|
|
217
272
|
};
|
|
218
273
|
/**
|
|
219
274
|
* Load server-relevant auth settings from the tenant DB.
|
|
@@ -291,7 +346,7 @@ const resolveApiNameHeader = async (ctx) => {
|
|
|
291
346
|
log.debug(`[api-name-lookup] No API found for databaseId=${headers.databaseId} name=${headers.apiName}`);
|
|
292
347
|
return null;
|
|
293
348
|
}
|
|
294
|
-
const rlsModule = await queryRlsModule(pool, row.api_id);
|
|
349
|
+
const rlsModule = await queryRlsModule(pool, row.database_id, row.api_id);
|
|
295
350
|
const authSettings = await queryAuthSettings(opts, row.dbname);
|
|
296
351
|
log.debug(`[api-name-lookup] resolved schemas: [${row.schemas?.join(', ')}], rlsModule: ${rlsModule ? 'found' : 'none'}, authSettings: ${authSettings ? 'found' : 'none'}`);
|
|
297
352
|
return toApiStructure(row, opts, rlsModule, authSettings);
|
|
@@ -308,7 +363,7 @@ const resolveDomainLookup = async (ctx) => {
|
|
|
308
363
|
log.debug(`[domain-lookup] No API found for domain=${domain} subdomain=${subdomain}`);
|
|
309
364
|
return null;
|
|
310
365
|
}
|
|
311
|
-
const rlsModule = await queryRlsModule(pool, row.api_id);
|
|
366
|
+
const rlsModule = await queryRlsModule(pool, row.database_id, row.api_id);
|
|
312
367
|
const authSettings = await queryAuthSettings(opts, row.dbname);
|
|
313
368
|
log.debug(`[domain-lookup] resolved schemas: [${row.schemas?.join(', ')}], rlsModule: ${rlsModule ? 'found' : 'none'}, authSettings: ${authSettings ? 'found' : 'none'}`);
|
|
314
369
|
return toApiStructure(row, opts, rlsModule, authSettings);
|
package/esm/middleware/upload.js
CHANGED
|
@@ -68,6 +68,51 @@ const RLS_MODULE_BY_DBNAME_SQL = `
|
|
|
68
68
|
ORDER BY a.id
|
|
69
69
|
LIMIT 1
|
|
70
70
|
`;
|
|
71
|
+
const RLS_SETTINGS_BY_DATABASE_ID_SQL = `
|
|
72
|
+
SELECT
|
|
73
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
74
|
+
role_schema.schema_name AS role_schema,
|
|
75
|
+
auth_fn.name AS authenticate,
|
|
76
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
77
|
+
role_fn.name AS current_role,
|
|
78
|
+
role_id_fn.name AS current_role_id,
|
|
79
|
+
ua_fn.name AS current_user_agent,
|
|
80
|
+
ip_fn.name AS current_ip_address
|
|
81
|
+
FROM services_public.rls_settings rs
|
|
82
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
83
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
84
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
85
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
86
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
87
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
88
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
89
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
90
|
+
WHERE rs.database_id = $1
|
|
91
|
+
LIMIT 1
|
|
92
|
+
`;
|
|
93
|
+
const RLS_SETTINGS_BY_DBNAME_SQL = `
|
|
94
|
+
SELECT
|
|
95
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
96
|
+
role_schema.schema_name AS role_schema,
|
|
97
|
+
auth_fn.name AS authenticate,
|
|
98
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
99
|
+
role_fn.name AS current_role,
|
|
100
|
+
role_id_fn.name AS current_role_id,
|
|
101
|
+
ua_fn.name AS current_user_agent,
|
|
102
|
+
ip_fn.name AS current_ip_address
|
|
103
|
+
FROM services_public.rls_settings rs
|
|
104
|
+
JOIN services_public.apis a ON rs.database_id = a.database_id
|
|
105
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
106
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
107
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
108
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
109
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
110
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
111
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
112
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
113
|
+
WHERE a.dbname = $1
|
|
114
|
+
LIMIT 1
|
|
115
|
+
`;
|
|
71
116
|
const toRlsModule = (row) => {
|
|
72
117
|
if (!row?.data)
|
|
73
118
|
return undefined;
|
|
@@ -83,6 +128,20 @@ const toRlsModule = (row) => {
|
|
|
83
128
|
currentUserAgent: d.current_user_agent,
|
|
84
129
|
};
|
|
85
130
|
};
|
|
131
|
+
const toRlsModuleFromSettings = (row) => {
|
|
132
|
+
if (!row)
|
|
133
|
+
return undefined;
|
|
134
|
+
return {
|
|
135
|
+
authenticate: row.authenticate,
|
|
136
|
+
authenticateStrict: row.authenticate_strict,
|
|
137
|
+
privateSchema: { schemaName: row.authenticate_schema },
|
|
138
|
+
publicSchema: { schemaName: row.role_schema },
|
|
139
|
+
currentRole: row.current_role,
|
|
140
|
+
currentRoleId: row.current_role_id,
|
|
141
|
+
currentIpAddress: row.current_ip_address,
|
|
142
|
+
currentUserAgent: row.current_user_agent,
|
|
143
|
+
};
|
|
144
|
+
};
|
|
86
145
|
const getBearerToken = (authorization) => {
|
|
87
146
|
if (!authorization)
|
|
88
147
|
return null;
|
|
@@ -92,7 +151,28 @@ const getBearerToken = (authorization) => {
|
|
|
92
151
|
}
|
|
93
152
|
return authToken;
|
|
94
153
|
};
|
|
154
|
+
const queryRlsSettingsByDatabaseId = async (pool, databaseId) => {
|
|
155
|
+
try {
|
|
156
|
+
const result = await pool.query(RLS_SETTINGS_BY_DATABASE_ID_SQL, [databaseId]);
|
|
157
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const queryRlsSettingsByDbname = async (pool, dbname) => {
|
|
164
|
+
try {
|
|
165
|
+
const result = await pool.query(RLS_SETTINGS_BY_DBNAME_SQL, [dbname]);
|
|
166
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
95
172
|
const queryRlsModuleByDatabaseId = async (pool, databaseId) => {
|
|
173
|
+
const fromSettings = await queryRlsSettingsByDatabaseId(pool, databaseId);
|
|
174
|
+
if (fromSettings)
|
|
175
|
+
return fromSettings;
|
|
96
176
|
const result = await pool.query(RLS_MODULE_BY_DATABASE_ID_SQL, [databaseId]);
|
|
97
177
|
return toRlsModule(result.rows[0] ?? null);
|
|
98
178
|
};
|
|
@@ -101,6 +181,9 @@ const queryRlsModuleByApiId = async (pool, apiId) => {
|
|
|
101
181
|
return toRlsModule(result.rows[0] ?? null);
|
|
102
182
|
};
|
|
103
183
|
const queryRlsModuleByDbname = async (pool, dbname) => {
|
|
184
|
+
const fromSettings = await queryRlsSettingsByDbname(pool, dbname);
|
|
185
|
+
if (fromSettings)
|
|
186
|
+
return fromSettings;
|
|
104
187
|
const result = await pool.query(RLS_MODULE_BY_DBNAME_SQL, [dbname]);
|
|
105
188
|
return toRlsModule(result.rows[0] ?? null);
|
|
106
189
|
};
|
package/middleware/api.js
CHANGED
|
@@ -81,6 +81,28 @@ const RLS_MODULE_SQL = `
|
|
|
81
81
|
WHERE api_id = $1 AND name = 'rls_module'
|
|
82
82
|
LIMIT 1
|
|
83
83
|
`;
|
|
84
|
+
const RLS_SETTINGS_SQL = `
|
|
85
|
+
SELECT
|
|
86
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
87
|
+
role_schema.schema_name AS role_schema,
|
|
88
|
+
auth_fn.name AS authenticate,
|
|
89
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
90
|
+
role_fn.name AS current_role,
|
|
91
|
+
role_id_fn.name AS current_role_id,
|
|
92
|
+
ua_fn.name AS current_user_agent,
|
|
93
|
+
ip_fn.name AS current_ip_address
|
|
94
|
+
FROM services_public.rls_settings rs
|
|
95
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
96
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
97
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
98
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
99
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
100
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
101
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
102
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
103
|
+
WHERE rs.database_id = $1
|
|
104
|
+
LIMIT 1
|
|
105
|
+
`;
|
|
84
106
|
/**
|
|
85
107
|
* Discover auth settings table location via public metaschema tables.
|
|
86
108
|
* Joins sessions_module with metaschema_public.schema to resolve
|
|
@@ -163,6 +185,24 @@ const toRlsModule = (row) => {
|
|
|
163
185
|
currentUserAgent: d.current_user_agent,
|
|
164
186
|
};
|
|
165
187
|
};
|
|
188
|
+
const toRlsModuleFromSettings = (row) => {
|
|
189
|
+
if (!row)
|
|
190
|
+
return undefined;
|
|
191
|
+
return {
|
|
192
|
+
authenticate: row.authenticate,
|
|
193
|
+
authenticateStrict: row.authenticate_strict,
|
|
194
|
+
privateSchema: {
|
|
195
|
+
schemaName: row.authenticate_schema,
|
|
196
|
+
},
|
|
197
|
+
publicSchema: {
|
|
198
|
+
schemaName: row.role_schema,
|
|
199
|
+
},
|
|
200
|
+
currentRole: row.current_role,
|
|
201
|
+
currentRoleId: row.current_role_id,
|
|
202
|
+
currentIpAddress: row.current_ip_address,
|
|
203
|
+
currentUserAgent: row.current_user_agent,
|
|
204
|
+
};
|
|
205
|
+
};
|
|
166
206
|
const toAuthSettings = (row) => {
|
|
167
207
|
if (!row)
|
|
168
208
|
return undefined;
|
|
@@ -177,14 +217,14 @@ const toAuthSettings = (row) => {
|
|
|
177
217
|
captchaSiteKey: row.captcha_site_key,
|
|
178
218
|
};
|
|
179
219
|
};
|
|
180
|
-
const toApiStructure = (row, opts,
|
|
220
|
+
const toApiStructure = (row, opts, rlsModule, authSettingsRow) => ({
|
|
181
221
|
apiId: row.api_id,
|
|
182
222
|
dbname: row.dbname || opts.pg?.database || '',
|
|
183
223
|
anonRole: row.anon_role || 'anon',
|
|
184
224
|
roleName: row.role_name || 'authenticated',
|
|
185
225
|
schema: row.schemas || [],
|
|
186
226
|
apiModules: [],
|
|
187
|
-
rlsModule
|
|
227
|
+
rlsModule,
|
|
188
228
|
domains: [],
|
|
189
229
|
databaseId: row.database_id,
|
|
190
230
|
isPublic: row.is_public,
|
|
@@ -219,9 +259,24 @@ const queryApiList = async (pool, isPublic) => {
|
|
|
219
259
|
const result = await pool.query(API_LIST_SQL, [isPublic]);
|
|
220
260
|
return result.rows;
|
|
221
261
|
};
|
|
222
|
-
const
|
|
262
|
+
const queryRlsSettings = async (pool, databaseId) => {
|
|
263
|
+
try {
|
|
264
|
+
const result = await pool.query(RLS_SETTINGS_SQL, [databaseId]);
|
|
265
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
const queryRlsModuleLegacy = async (pool, apiId) => {
|
|
223
272
|
const result = await pool.query(RLS_MODULE_SQL, [apiId]);
|
|
224
|
-
return result.rows[0] ?? null;
|
|
273
|
+
return toRlsModule(result.rows[0] ?? null);
|
|
274
|
+
};
|
|
275
|
+
const queryRlsModule = async (pool, databaseId, apiId) => {
|
|
276
|
+
const fromSettings = await queryRlsSettings(pool, databaseId);
|
|
277
|
+
if (fromSettings)
|
|
278
|
+
return fromSettings;
|
|
279
|
+
return queryRlsModuleLegacy(pool, apiId);
|
|
225
280
|
};
|
|
226
281
|
/**
|
|
227
282
|
* Load server-relevant auth settings from the tenant DB.
|
|
@@ -299,7 +354,7 @@ const resolveApiNameHeader = async (ctx) => {
|
|
|
299
354
|
log.debug(`[api-name-lookup] No API found for databaseId=${headers.databaseId} name=${headers.apiName}`);
|
|
300
355
|
return null;
|
|
301
356
|
}
|
|
302
|
-
const rlsModule = await queryRlsModule(pool, row.api_id);
|
|
357
|
+
const rlsModule = await queryRlsModule(pool, row.database_id, row.api_id);
|
|
303
358
|
const authSettings = await queryAuthSettings(opts, row.dbname);
|
|
304
359
|
log.debug(`[api-name-lookup] resolved schemas: [${row.schemas?.join(', ')}], rlsModule: ${rlsModule ? 'found' : 'none'}, authSettings: ${authSettings ? 'found' : 'none'}`);
|
|
305
360
|
return toApiStructure(row, opts, rlsModule, authSettings);
|
|
@@ -316,7 +371,7 @@ const resolveDomainLookup = async (ctx) => {
|
|
|
316
371
|
log.debug(`[domain-lookup] No API found for domain=${domain} subdomain=${subdomain}`);
|
|
317
372
|
return null;
|
|
318
373
|
}
|
|
319
|
-
const rlsModule = await queryRlsModule(pool, row.api_id);
|
|
374
|
+
const rlsModule = await queryRlsModule(pool, row.database_id, row.api_id);
|
|
320
375
|
const authSettings = await queryAuthSettings(opts, row.dbname);
|
|
321
376
|
log.debug(`[domain-lookup] resolved schemas: [${row.schemas?.join(', ')}], rlsModule: ${rlsModule ? 'found' : 'none'}, authSettings: ${authSettings ? 'found' : 'none'}`);
|
|
322
377
|
return toApiStructure(row, opts, rlsModule, authSettings);
|
package/middleware/upload.js
CHANGED
|
@@ -74,6 +74,51 @@ const RLS_MODULE_BY_DBNAME_SQL = `
|
|
|
74
74
|
ORDER BY a.id
|
|
75
75
|
LIMIT 1
|
|
76
76
|
`;
|
|
77
|
+
const RLS_SETTINGS_BY_DATABASE_ID_SQL = `
|
|
78
|
+
SELECT
|
|
79
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
80
|
+
role_schema.schema_name AS role_schema,
|
|
81
|
+
auth_fn.name AS authenticate,
|
|
82
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
83
|
+
role_fn.name AS current_role,
|
|
84
|
+
role_id_fn.name AS current_role_id,
|
|
85
|
+
ua_fn.name AS current_user_agent,
|
|
86
|
+
ip_fn.name AS current_ip_address
|
|
87
|
+
FROM services_public.rls_settings rs
|
|
88
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
89
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
90
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
91
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
92
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
93
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
94
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
95
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
96
|
+
WHERE rs.database_id = $1
|
|
97
|
+
LIMIT 1
|
|
98
|
+
`;
|
|
99
|
+
const RLS_SETTINGS_BY_DBNAME_SQL = `
|
|
100
|
+
SELECT
|
|
101
|
+
auth_schema.schema_name AS authenticate_schema,
|
|
102
|
+
role_schema.schema_name AS role_schema,
|
|
103
|
+
auth_fn.name AS authenticate,
|
|
104
|
+
auth_strict_fn.name AS authenticate_strict,
|
|
105
|
+
role_fn.name AS current_role,
|
|
106
|
+
role_id_fn.name AS current_role_id,
|
|
107
|
+
ua_fn.name AS current_user_agent,
|
|
108
|
+
ip_fn.name AS current_ip_address
|
|
109
|
+
FROM services_public.rls_settings rs
|
|
110
|
+
JOIN services_public.apis a ON rs.database_id = a.database_id
|
|
111
|
+
LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
|
|
112
|
+
LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
|
|
113
|
+
LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
|
|
114
|
+
LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
|
|
115
|
+
LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
|
|
116
|
+
LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
|
|
117
|
+
LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
|
|
118
|
+
LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
|
|
119
|
+
WHERE a.dbname = $1
|
|
120
|
+
LIMIT 1
|
|
121
|
+
`;
|
|
77
122
|
const toRlsModule = (row) => {
|
|
78
123
|
if (!row?.data)
|
|
79
124
|
return undefined;
|
|
@@ -89,6 +134,20 @@ const toRlsModule = (row) => {
|
|
|
89
134
|
currentUserAgent: d.current_user_agent,
|
|
90
135
|
};
|
|
91
136
|
};
|
|
137
|
+
const toRlsModuleFromSettings = (row) => {
|
|
138
|
+
if (!row)
|
|
139
|
+
return undefined;
|
|
140
|
+
return {
|
|
141
|
+
authenticate: row.authenticate,
|
|
142
|
+
authenticateStrict: row.authenticate_strict,
|
|
143
|
+
privateSchema: { schemaName: row.authenticate_schema },
|
|
144
|
+
publicSchema: { schemaName: row.role_schema },
|
|
145
|
+
currentRole: row.current_role,
|
|
146
|
+
currentRoleId: row.current_role_id,
|
|
147
|
+
currentIpAddress: row.current_ip_address,
|
|
148
|
+
currentUserAgent: row.current_user_agent,
|
|
149
|
+
};
|
|
150
|
+
};
|
|
92
151
|
const getBearerToken = (authorization) => {
|
|
93
152
|
if (!authorization)
|
|
94
153
|
return null;
|
|
@@ -98,7 +157,28 @@ const getBearerToken = (authorization) => {
|
|
|
98
157
|
}
|
|
99
158
|
return authToken;
|
|
100
159
|
};
|
|
160
|
+
const queryRlsSettingsByDatabaseId = async (pool, databaseId) => {
|
|
161
|
+
try {
|
|
162
|
+
const result = await pool.query(RLS_SETTINGS_BY_DATABASE_ID_SQL, [databaseId]);
|
|
163
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const queryRlsSettingsByDbname = async (pool, dbname) => {
|
|
170
|
+
try {
|
|
171
|
+
const result = await pool.query(RLS_SETTINGS_BY_DBNAME_SQL, [dbname]);
|
|
172
|
+
return toRlsModuleFromSettings(result.rows[0] ?? null);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
101
178
|
const queryRlsModuleByDatabaseId = async (pool, databaseId) => {
|
|
179
|
+
const fromSettings = await queryRlsSettingsByDatabaseId(pool, databaseId);
|
|
180
|
+
if (fromSettings)
|
|
181
|
+
return fromSettings;
|
|
102
182
|
const result = await pool.query(RLS_MODULE_BY_DATABASE_ID_SQL, [databaseId]);
|
|
103
183
|
return toRlsModule(result.rows[0] ?? null);
|
|
104
184
|
};
|
|
@@ -107,6 +187,9 @@ const queryRlsModuleByApiId = async (pool, apiId) => {
|
|
|
107
187
|
return toRlsModule(result.rows[0] ?? null);
|
|
108
188
|
};
|
|
109
189
|
const queryRlsModuleByDbname = async (pool, dbname) => {
|
|
190
|
+
const fromSettings = await queryRlsSettingsByDbname(pool, dbname);
|
|
191
|
+
if (fromSettings)
|
|
192
|
+
return fromSettings;
|
|
110
193
|
const result = await pool.query(RLS_MODULE_BY_DBNAME_SQL, [dbname]);
|
|
111
194
|
return toRlsModule(result.rows[0] ?? null);
|
|
112
195
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-server",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.26.1",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive GraphQL Server",
|
|
6
6
|
"main": "index.js",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"graphile-build-pg": "5.0.0",
|
|
64
64
|
"graphile-cache": "^3.8.0",
|
|
65
65
|
"graphile-config": "1.0.0",
|
|
66
|
-
"graphile-settings": "^4.30.
|
|
66
|
+
"graphile-settings": "^4.30.2",
|
|
67
67
|
"graphile-utils": "5.0.0",
|
|
68
68
|
"graphql": "16.13.0",
|
|
69
69
|
"graphql-upload": "^13.0.0",
|
|
@@ -85,10 +85,10 @@
|
|
|
85
85
|
"@types/multer": "^2.1.0",
|
|
86
86
|
"@types/pg": "^8.18.0",
|
|
87
87
|
"@types/request-ip": "^0.0.41",
|
|
88
|
-
"graphile-test": "4.12.
|
|
88
|
+
"graphile-test": "4.12.1",
|
|
89
89
|
"makage": "^0.3.0",
|
|
90
90
|
"nodemon": "^3.1.14",
|
|
91
91
|
"ts-node": "^10.9.2"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "0fcb26c8f3379de5c2bf486e7ad78bb61a76e497"
|
|
94
94
|
}
|