Thomas Valloo
01/21/2025, 4:22 PMJan
01/21/2025, 4:43 PMJan
01/21/2025, 4:43 PMThomas Valloo
01/21/2025, 4:46 PMJan
01/21/2025, 4:47 PMThomas Valloo
01/21/2025, 4:48 PMThomas Valloo
01/21/2025, 6:13 PMJan
01/21/2025, 7:15 PMThomas Valloo
01/22/2025, 6:52 PMMaanrifa Bacar Ali
01/23/2025, 12:52 PMThomas Valloo
01/24/2025, 2:50 PMMaanrifa Bacar Ali
01/25/2025, 1:51 AMMaanrifa Bacar Ali
01/25/2025, 1:54 AMThomas Valloo
01/31/2025, 8:34 AMimport * as postgres from '<https://deno.land/x/postgres@v0.19.3/mod.ts>'
export async function getUserDbClient(userId) {
const databaseUrl = Deno.env.get('SUPABASE_DB_URL')
const client = new postgres.Client(databaseUrl);
await client.connect();
await client.queryObject(`SET my.current_user_id TO '${userId}';`)
await client.queryObject(`SET SESSION ROLE 'authenticated';`)
return client
}
Expose the javascript objects in Kotlin :
@JsName("getUserDbClient")
external suspend fun getUserDbClient(userId: String): Promise<Client>
// <https://github.com/denodrivers/postgres/blob/main/client.ts>
external class Client : DbConnection {
fun createTransaction(name: String): Transaction
override suspend fun queryObject(query: String): Promise<QueryObjectResult>
suspend fun end()
}
// <https://github.com/denodrivers/postgres/blob/main/query/query.ts>
external class QueryObjectResult {
val rows: Array<Record<String, Any>>
}
// <https://github.com/denodrivers/postgres/blob/main/query/transaction.ts>
external class Transaction : DbConnection {
/**
* The begin method will officially begin the transaction, and it must be called before
* any query or transaction operation is executed in order to lock the session.
*/
suspend fun begin(): Promise<Unit>
/**
* The commit method will make permanent all changes made to the database in the
* current transaction and end the current transaction.
*/
suspend fun commit(): Promise<Unit>
override suspend fun queryObject(query: String): Promise<QueryObjectResult>
}
external interface Record<T, R>
you can then use this connection in your kotlin code.
To get userId in the edge function, use the jwt token and import user :
val supabase = provideSupabaseAnonClient()
supabase.auth.importAuthToken(jwt, retrieveUser = true)
val userInfo = supabase.auth.currentUserOrNull()
To use it in tour RLS policies, create this sql function :
CREATE OR REPLACE FUNCTION get_current_user_id() RETURNS TEXT AS $$
DECLARE
user_id TEXT;
BEGIN
BEGIN
SELECT auth.uid()::text INTO user_id;
EXCEPTION WHEN others THEN
user_id := NULL;
END;
IF user_id IS NULL THEN
user_id := current_setting('my.current_user_id');
END IF;
RETURN user_id;
END;
$$ LANGUAGE plpgsql;
and for the policies, instead of calling auth.uid()
, call get_current_user_id()
create policy "Users can update."
on your_table for UPDATE
to authenticated
using ((select get_current_user_id()) = user_id)
with check ((select get_current_user_id()) = user_id);
That way, you can work directly on your postgres database from your edge function, or use the supabase API from the client, RLS policies will work the same.
Hope it helps, tell me if you find anything suspicious.Maanrifa Bacar Ali
02/03/2025, 9:34 PM