CREATE OR REPLACE FUNCTION has_node_access(p_node_id UUID, p_user_id UUID) RETURNS BOOLEAN LANGUAGE sql STABLE AS $$ WITH RECURSIVE ancestors AS ( SELECT id, parent_id FROM files_nodes WHERE id = p_node_id AND deleted_at IS NULL UNION ALL SELECT p.id, p.parent_id FROM files_nodes p JOIN ancestors a ON a.parent_id = p.id WHERE p.deleted_at IS NULL ) SELECT EXISTS ( SELECT 1 FROM ancestors a JOIN files_access fa ON fa.node_id = a.id WHERE fa.user_id = p_user_id ); $$; CREATE OR REPLACE FUNCTION effective_node_access(p_node_id UUID, p_user_id UUID, p_subordinate_ids TEXT[]) RETURNS TEXT LANGUAGE sql STABLE AS $$ WITH RECURSIVE ancestors AS ( SELECT id, parent_id, owner_user_id FROM files_nodes WHERE id = p_node_id AND deleted_at IS NULL UNION ALL SELECT p.id, p.parent_id, p.owner_user_id FROM files_nodes p JOIN ancestors a ON a.parent_id = p.id WHERE p.deleted_at IS NULL ), direct_access AS ( SELECT fa.access_level FROM ancestors a JOIN files_access fa ON fa.node_id = a.id WHERE fa.user_id = p_user_id ) SELECT CASE WHEN EXISTS (SELECT 1 FROM files_nodes n WHERE n.id = p_node_id AND n.owner_user_id = p_user_id AND n.deleted_at IS NULL) THEN 'edit' WHEN EXISTS (SELECT 1 FROM files_nodes n WHERE n.id = p_node_id AND n.owner_user_id::text = ANY(p_subordinate_ids) AND n.deleted_at IS NULL) THEN 'view' WHEN EXISTS (SELECT 1 FROM direct_access WHERE access_level = 'edit') THEN 'edit' WHEN EXISTS (SELECT 1 FROM direct_access) THEN 'view' ELSE '' END; $$;