feat(rls): add multi-orgs filtering logic
This commit is contained in:
+40
-4
@@ -48,6 +48,31 @@ $$;
|
||||
COMMENT ON FUNCTION morbac.current_org_id() IS
|
||||
'Returns current organization ID from morbac.org_id session variable';
|
||||
|
||||
-- Set via: SET morbac.org_ids = '["uuid1","uuid2"]'
|
||||
CREATE OR REPLACE FUNCTION morbac.current_org_ids()
|
||||
RETURNS UUID[]
|
||||
LANGUAGE plpgsql
|
||||
STABLE
|
||||
AS $$
|
||||
DECLARE
|
||||
v_raw TEXT;
|
||||
BEGIN
|
||||
v_raw := current_setting('morbac.org_ids', TRUE);
|
||||
|
||||
IF v_raw IS NULL OR v_raw = '' THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
RETURN ARRAY(SELECT jsonb_array_elements_text(v_raw::jsonb)::UUID);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION morbac.current_org_ids() IS
|
||||
'Returns org ID list from morbac.org_ids session variable (JSON array)';
|
||||
|
||||
CREATE OR REPLACE FUNCTION morbac.get_user_orgs(p_user_id UUID)
|
||||
RETURNS TABLE(org_id UUID)
|
||||
LANGUAGE sql
|
||||
@@ -67,8 +92,8 @@ $$;
|
||||
COMMENT ON FUNCTION morbac.get_user_orgs(UUID) IS
|
||||
'Returns all org IDs the user has any direct role or active delegation in';
|
||||
|
||||
-- When p_row_org_id is provided and session org is NULL, checks permission in the row org (multi-org mode).
|
||||
-- Usage: morbac.rls_check('read', 'documents', org_id)
|
||||
-- Org scoping: morbac.org_id (single) > morbac.org_ids (list) > all orgs.
|
||||
-- Pass the row org_id column to enable scoping: rls_check('read', 'docs', org_id)
|
||||
CREATE OR REPLACE FUNCTION morbac.rls_check(
|
||||
p_activity TEXT,
|
||||
p_view TEXT,
|
||||
@@ -81,14 +106,16 @@ AS $$
|
||||
DECLARE
|
||||
v_user_id UUID;
|
||||
v_org_id UUID;
|
||||
v_org_ids UUID[];
|
||||
BEGIN
|
||||
v_user_id := morbac.current_user_id();
|
||||
v_org_id := morbac.current_org_id();
|
||||
|
||||
IF v_user_id IS NULL THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
|
||||
v_org_id := morbac.current_org_id();
|
||||
|
||||
IF v_org_id IS NOT NULL THEN
|
||||
IF p_row_org_id IS NOT NULL AND p_row_org_id <> v_org_id THEN
|
||||
RETURN FALSE;
|
||||
@@ -96,6 +123,15 @@ BEGIN
|
||||
RETURN morbac.is_allowed(v_user_id, v_org_id, p_activity, p_view);
|
||||
END IF;
|
||||
|
||||
v_org_ids := morbac.current_org_ids();
|
||||
|
||||
IF v_org_ids IS NOT NULL THEN
|
||||
IF p_row_org_id IS NULL OR NOT (p_row_org_id = ANY(v_org_ids)) THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
RETURN morbac.is_allowed(v_user_id, p_row_org_id, p_activity, p_view);
|
||||
END IF;
|
||||
|
||||
IF p_row_org_id IS NOT NULL THEN
|
||||
RETURN morbac.is_allowed(v_user_id, p_row_org_id, p_activity, p_view);
|
||||
END IF;
|
||||
@@ -105,4 +141,4 @@ END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION morbac.rls_check(TEXT, TEXT, UUID) IS
|
||||
'RLS helper: checks if current user is allowed to perform activity on view. Pass row org_id to enable multi-org mode when no session org is set.';
|
||||
'RLS helper: checks if current user is allowed to perform activity on view. Pass row org_id to enable org scoping (single org, org list, or all orgs).';
|
||||
|
||||
Reference in New Issue
Block a user