DB의 policies 를 살펴보면, 사용자에 따라 접근권한을 설정할때, auth.uid() 같은 함수를 이용해서 현 사용자만 접근 가능하도록 할 수 있죠.
그런데 만약 같은 팀원만 볼수 있게 하고 싶다면, 음.. 일단 RLS에서 team에 대한 table join 해서 팀에 소속되어있는지 확인해야 합니다.
(예제에도 그렇게 되어있죠)
그런데 table join이 들어간 코드와 아닌코드의 성능 차이기 약 99% 차이가 난다고 예제에 나와있어요.
table join이 빠지면 99% 성능 향상 ..
그런데 만약 auth token에 추가정보를 담고, RLS에서 auth token에 있는 정보를 활용해서 필터링 할 수 있다고 한다면, (가정입니다. 지금 시도해보고 있음), ㅅa
table join없이 처리가 가능합니다. 즉 향상된 성능으로 처리할 수 있다는 것이죠.
0. custom_jwt_token_hook 추가하기
custom_jwt_token_hook 구현
private schema 를 만들어서 추가 (public schema는노출 되어있기 때문에 피하는 것이 좋다. )
1. custom jwt를 통해서 token에 추가정보가 들어간것 확인했습니다.
=> 정상적으로 설정이 완료 되면 token에 정보가 들어간 것을 볼 수 있다.
2. 서버에서 RLS 로직에서 추가정보를 꺼내올 수 있는지 확인 필요.
=> 확인 중인 사항
(select auth.jwt() -> 'app_metadata' -> 'teams')
아래처럼 org_id 값을 비교하고 싶을때, org_id가 int8 (숫자)인경우라면, 숫자를 문자로 변경해서 비교 해야함.
ALTER POLICY "Enable read access for same org"
ON "public"."devices"
TO authenticated
USING (
(auth.jwt() ->> 'org_id')::text = org_id::text
);
3.테스트를 위해서 local pc에서 custom jwt 를 테스트 해 볼 수 있는 환경 구축..
가이드에 이렇게 적혀있음
# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used.
# [auth.hook.custom_access_token]
# enabled = true
# uri = "pg-functions://<database>/<schema>/<hook_name>"
config.toml 에 다음 과 같이 내용 추가.
[auth.hook.custom_access_token]
enabled = true
uri = "pg-functions://postgres/private/custom_jwt_token_hook"
Supabase Authentication을 hooking 해서 사용해야 하는 경우가 있습니다.
이때 sql query 함수를 개발하고 테스트를 보통은 cli를 통해서 진행할텐데, cli에 extension이 활성화 안되어있는 경우 검토가 힘들어지겠죠.
저도 역시 plv8이 활성화 안되어있어서 , 문제였습니다.
해결책은 다음 과 같이 찾아서 정리해봤습니다.
1. supabase에 기본적으로 extension으로 plv8이 있는 거 같음.
2. 그래서 이를 활성화 시키는 방법을 찾아서 실행.
3. 활성화 된것 확인
extension 활성화
CREATE EXTENSION plv8;
설치 확인
SELECT * FROM pg_available_extensions WHERE name = 'plv8';
코드 작성...
create or replace function custom_jwt_token_hook(event jsonb)
returns jsonb
language plv8
as $$
var org_id, role, org_depart_id;
-- Fetch the current user's level from the profiles table
var result = plv8.execute("select org_id, role, org_depart_id from public.user_profiles where user_id = $1", [event.user_id]);
if (result.length > 0) {
org_id = result[0].org_id;
org_depart_id = result[0].org_depart_id;
role = result[0].role;
} else {
org_id = 0;
org_depart_id = 0;
role = '';
}
-- Check if 'claims' exists in the event object; if not, initialize it
if (!event.claims) {
event.claims = {};
}
-- Update the level in the claims
event.claims.org_id = org_id;
event.claims.org_depart_id = org_depart_id;
event.claims.role = role;
return event;
$$;
grant all
on table public.user_profiles
to supabase_auth_admin;
revoke all
on table public.user_profiles
from authenticated, anon, public;
~/supabase$ npx supabse login
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/supabse - Not found
npm ERR! 404
npm ERR! 404 'supabse@*' is not in this registry.
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/netplant/.npm/_logs/2024-12-16T07_31_12_169Z-debug-0.log
netplant@netplant01:~/supabase$ npx supabase login
Hello from Supabase! Press Enter to open browser and login automatically.
엔터를 치면,
브라우저가 뜨고 supabse 에 로그인 화면이 나타납니다.
로그인을 합니다.
2. 로그인 하고나면,
supabase verify 코드가 보이게 됩니다.
3.이 코드를 가지고 terminal에 입력합니다.
- Enter your verification code: f16d4f38
3.. 함수 개발해보기
함수를 하나 만들어보자.
Edge function을 개발하기 위해서는 Cli를 이용해서 Edge Function을 만들어 줍니다.
supabase functions new my-function --no-verify-jwt
또는
npx supabase functions new my-function --no-verify-jwt
테스트를 위한 것이니 --no-verify-jwt 를 옵션으로 입력했습니다.
그러면 간단한 샘플코드와 함께 함수 폴더가 만들어 집니다.
supabase 밑에 functions 라는 폴더가 생기고, 그 아래 my-function이라는 폴더가 만들어 지죠.
폴더 위치 : supabase/functions/my-function
생성된 예제 코드
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
console.log("Hello from Functions!")
Deno.serve(async (req) => {
const { name } = await req.json()
const data = {
message: `Hello ${name}!`,
}
return new Response(
JSON.stringify(data),
{ headers: { "Content-Type": "application/json" } },
)
})
/* To invoke locally:
1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start)
2. Make an HTTP request:
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/my-function' \
--header 'Authorization: Bearer -sdjfklsdfjskldf-sdlfkasm23324l234dsdfk' \
--header 'Content-Type: application/json' \
--data '{"name":"Functions"}'
*/