feat(permissions): project member permission filter (#9757)

# Which Problems Are Solved

Add the possibility to filter project resources based on project member
roles.

# How the Problems Are Solved

Extend and refactor existing Pl/PgSQL functions to implement the
following:

- Solve O(n) complexity in returned resources IDs by returning a boolean
filter for instance level permissions.
- Individually permitted orgs are returned only if there was no instance
permission
- Individually permitted projects are returned only if there was no
instance permission
- Because of the multiple filter terms, use `INNER JOIN`s instead of
`WHERE` clauses.

# Additional Changes

- system permission function no longer query the organization view and
therefore can be `immutable`, giving big performance benefits for
frequently reused system users. (like our hosted login in Zitadel cloud)
- The permitted org and project functions are now defined as `stable`
because the don't modify on-disk data. This might give a small
performance gain
- The Pl/PgSQL functions are now tested using Go unit tests.

# Additional Context

- Depends on https://github.com/zitadel/zitadel/pull/9677
- Part of https://github.com/zitadel/zitadel/issues/9188
- Closes https://github.com/zitadel/zitadel/issues/9190
This commit is contained in:
Tim Möhlmann
2025-04-22 11:42:59 +03:00
committed by GitHub
parent 618143931b
commit 658ca3606b
18 changed files with 1403 additions and 225 deletions

View File

@@ -117,7 +117,7 @@ func sessionsPermissionCheckV2(ctx context.Context, query sq.SelectBuilder, enab
if !enabled {
return query
}
return query.Where(PermissionClause(
join, args := PermissionClause(
ctx,
SessionColumnResourceOwner,
domain.PermissionSessionRead,
@@ -125,8 +125,10 @@ func sessionsPermissionCheckV2(ctx context.Context, query sq.SelectBuilder, enab
OwnedRowsPermissionOption(SessionColumnCreator),
// Allow if session belongs to the user
OwnedRowsPermissionOption(SessionColumnUserID),
// Allow if session belongs to the same useragent
ConnectionPermissionOption(SessionColumnUserAgentFingerprintID, authz.GetCtxData(ctx).AgentID),
))
)
return query.JoinClause(join, args...)
}
func (q *SessionsSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder {