@@ -86,6 +86,29 @@ const RLS_MODULE_SQL = `
8686 LIMIT 1
8787` ;
8888
89+ const RLS_SETTINGS_SQL = `
90+ SELECT
91+ auth_schema.schema_name AS authenticate_schema,
92+ role_schema.schema_name AS role_schema,
93+ auth_fn.name AS authenticate,
94+ auth_strict_fn.name AS authenticate_strict,
95+ role_fn.name AS current_role,
96+ role_id_fn.name AS current_role_id,
97+ ua_fn.name AS current_user_agent,
98+ ip_fn.name AS current_ip_address
99+ FROM services_public.rls_settings rs
100+ LEFT JOIN metaschema_public.schema auth_schema ON rs.authenticate_schema_id = auth_schema.id
101+ LEFT JOIN metaschema_public.schema role_schema ON rs.role_schema_id = role_schema.id
102+ LEFT JOIN metaschema_public.function auth_fn ON rs.authenticate_function_id = auth_fn.id
103+ LEFT JOIN metaschema_public.function auth_strict_fn ON rs.authenticate_strict_function_id = auth_strict_fn.id
104+ LEFT JOIN metaschema_public.function role_fn ON rs.current_role_function_id = role_fn.id
105+ LEFT JOIN metaschema_public.function role_id_fn ON rs.current_role_id_function_id = role_id_fn.id
106+ LEFT JOIN metaschema_public.function ua_fn ON rs.current_user_agent_function_id = ua_fn.id
107+ LEFT JOIN metaschema_public.function ip_fn ON rs.current_ip_address_function_id = ip_fn.id
108+ WHERE rs.database_id = $1
109+ LIMIT 1
110+ ` ;
111+
89112/**
90113 * Discover auth settings table location via public metaschema tables.
91114 * Joins sessions_module with metaschema_public.schema to resolve
@@ -249,6 +272,24 @@ const toRlsModule = (row: RlsModuleRow | null): RlsModule | undefined => {
249272 } ;
250273} ;
251274
275+ const toRlsModuleFromSettings = ( row : RlsModuleData | null ) : RlsModule | undefined => {
276+ if ( ! row ) return undefined ;
277+ return {
278+ authenticate : row . authenticate ,
279+ authenticateStrict : row . authenticate_strict ,
280+ privateSchema : {
281+ schemaName : row . authenticate_schema ,
282+ } ,
283+ publicSchema : {
284+ schemaName : row . role_schema ,
285+ } ,
286+ currentRole : row . current_role ,
287+ currentRoleId : row . current_role_id ,
288+ currentIpAddress : row . current_ip_address ,
289+ currentUserAgent : row . current_user_agent ,
290+ } ;
291+ } ;
292+
252293const toAuthSettings = ( row : AuthSettingsRow | null ) : AuthSettings | undefined => {
253294 if ( ! row ) return undefined ;
254295 return {
@@ -263,14 +304,14 @@ const toAuthSettings = (row: AuthSettingsRow | null): AuthSettings | undefined =
263304 } ;
264305} ;
265306
266- const toApiStructure = ( row : ApiRow , opts : ApiOptions , rlsModuleRow ?: RlsModuleRow | null , authSettingsRow ?: AuthSettingsRow | null ) : ApiStructure => ( {
307+ const toApiStructure = ( row : ApiRow , opts : ApiOptions , rlsModule ?: RlsModule , authSettingsRow ?: AuthSettingsRow | null ) : ApiStructure => ( {
267308 apiId : row . api_id ,
268309 dbname : row . dbname || opts . pg ?. database || '' ,
269310 anonRole : row . anon_role || 'anon' ,
270311 roleName : row . role_name || 'authenticated' ,
271312 schema : row . schemas || [ ] ,
272313 apiModules : [ ] ,
273- rlsModule : toRlsModule ( rlsModuleRow ?? null ) ,
314+ rlsModule,
274315 domains : [ ] ,
275316 databaseId : row . database_id ,
276317 isPublic : row . is_public ,
@@ -329,9 +370,24 @@ const queryApiList = async (pool: Pool, isPublic: boolean): Promise<ApiListRow[]
329370 return result . rows ;
330371} ;
331372
332- const queryRlsModule = async ( pool : Pool , apiId : string ) : Promise < RlsModuleRow | null > => {
373+ const queryRlsSettings = async ( pool : Pool , databaseId : string ) : Promise < RlsModule | undefined > => {
374+ try {
375+ const result = await pool . query < RlsModuleData > ( RLS_SETTINGS_SQL , [ databaseId ] ) ;
376+ return toRlsModuleFromSettings ( result . rows [ 0 ] ?? null ) ;
377+ } catch {
378+ return undefined ;
379+ }
380+ } ;
381+
382+ const queryRlsModuleLegacy = async ( pool : Pool , apiId : string ) : Promise < RlsModule | undefined > => {
333383 const result = await pool . query < RlsModuleRow > ( RLS_MODULE_SQL , [ apiId ] ) ;
334- return result . rows [ 0 ] ?? null ;
384+ return toRlsModule ( result . rows [ 0 ] ?? null ) ;
385+ } ;
386+
387+ const queryRlsModule = async ( pool : Pool , databaseId : string , apiId : string ) : Promise < RlsModule | undefined > => {
388+ const fromSettings = await queryRlsSettings ( pool , databaseId ) ;
389+ if ( fromSettings ) return fromSettings ;
390+ return queryRlsModuleLegacy ( pool , apiId ) ;
335391} ;
336392
337393/**
@@ -423,7 +479,7 @@ const resolveApiNameHeader = async (ctx: ResolveContext): Promise<ApiStructure |
423479 return null ;
424480 }
425481
426- const rlsModule = await queryRlsModule ( pool , row . api_id ) ;
482+ const rlsModule = await queryRlsModule ( pool , row . database_id , row . api_id ) ;
427483 const authSettings = await queryAuthSettings ( opts , row . dbname ) ;
428484 log . debug ( `[api-name-lookup] resolved schemas: [${ row . schemas ?. join ( ', ' ) } ], rlsModule: ${ rlsModule ? 'found' : 'none' } , authSettings: ${ authSettings ? 'found' : 'none' } ` ) ;
429485 return toApiStructure ( row , opts , rlsModule , authSettings ) ;
@@ -449,7 +505,7 @@ const resolveDomainLookup = async (ctx: ResolveContext): Promise<ApiStructure |
449505 return null ;
450506 }
451507
452- const rlsModule = await queryRlsModule ( pool , row . api_id ) ;
508+ const rlsModule = await queryRlsModule ( pool , row . database_id , row . api_id ) ;
453509 const authSettings = await queryAuthSettings ( opts , row . dbname ) ;
454510 log . debug ( `[domain-lookup] resolved schemas: [${ row . schemas ?. join ( ', ' ) } ], rlsModule: ${ rlsModule ? 'found' : 'none' } , authSettings: ${ authSettings ? 'found' : 'none' } ` ) ;
455511 return toApiStructure ( row , opts , rlsModule , authSettings ) ;
0 commit comments