11-- The previous user_has_project_permission function is called on _every_ project when doing global omnisearch,
22-- which is too slow.
33
4- -- Create a view which serves as join table for finding projects we should consider in search, it's much faster
5- -- than running a permission check for every private project.
6- CREATE FUNCTION projects_searchable_by_user (arg_user_id UUID)
4+ -- Create a view which serves as join table for finding projects for which the user has a given permission, it's much faster
5+ -- than running a permission check for every private project when we need to discover the list of all projects a user
6+ -- has access to.
7+ --
8+ -- This special-cases the 'project:view' permission to be even faster, it's the most common case.
9+ CREATE FUNCTION projects_by_user_permission (arg_user_id UUID, arg_permission permission)
710-- Returns a subset of the projects table
811RETURNS SETOF projects AS $$
912 -- Get all public projects and projects owned by the user,
1013 -- as well as all public projects.
1114 SELECT p.*
1215 FROM projects p
1316 WHERE p .owner_user_id = arg_user_id
14- OR NOT p .private
17+ OR (arg_permission = ' project:view ' AND NOT p .private )
1518UNION
1619 SELECT
1720 p.*
2023 ON om .organization_user_id = p .owner_user_id
2124 JOIN roles r ON om .role_id = r .id
2225 WHERE om .member_user_id = arg_user_id
23- AND ' project:view ' = ANY(r .permissions )
24- -- All public projects are already included above
25- AND p .private
26+ AND arg_permission = ANY(r .permissions )
27+ -- All public projects are already included above if the permission is 'project:view'
28+ AND ( p .private OR arg_permission <> ' project:view ' )
2629 UNION
2730 -- Include projects the user is a direct maintainer of
2831 SELECT
@@ -32,18 +35,11 @@ UNION
3235 JOIN roles r ON rm .role_id = r .id
3336 JOIN projects p ON rm .resource_id = p .resource_id
3437 WHERE u .id = arg_user_id
35- AND ' project:view' = ANY(r .permissions )
36- AND p .private ;
38+ AND arg_permission = ANY(r .permissions )
39+ -- All public projects are already included above if the permission is 'project:view'
40+ AND (p .private OR arg_permission <> ' project:view' )
3741$$ LANGUAGE sql STABLE PARALLEL SAFE;
3842
3943-- A better index for this query.
40- -- CREATE INDEX idx_projects_by_owner_and_privacy
41- -- ON projects (private, owner_user_id);
42-
43- CREATE INDEX idx_public_projects_by_owner
44- ON projects (owner_user_id)
45- WHERE NOT private;
46-
47- CREATE INDEX idx_private_projects_by_owner
48- ON projects (owner_user_id)
49- WHERE private;
44+ CREATE INDEX idx_projects_by_owner_and_privacy
45+ ON projects (private, owner_user_id);
0 commit comments