mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 10:37:32 +00:00
perf(query): org permission function for resources (#9677)
# Which Problems Are Solved Classic permission checks execute for every returned row on resource based search APIs. Complete background and problem definition can be found here: https://github.com/zitadel/zitadel/issues/9188 # How the Problems Are Solved - PermissionClause function now support dynamic query building, so it supports multiple cases. - PermissionClause is applied to all list resources which support org level permissions. - Wrap permission logic into wrapper functions so we keep the business logic clean. # Additional Changes - Handle org ID optimization in the query package, so it is reusable for all resources, instead of extracting the filter in the API. - Cleanup and test system user conversion in the authz package. (context middleware) - Fix: `core_integration_db_up` make recipe was missing the postgres service. # Additional Context - Related to https://github.com/zitadel/zitadel/issues/9190
This commit is contained in:
@@ -132,6 +132,19 @@ func usersCheckPermission(ctx context.Context, users *Users, permissionCheck dom
|
||||
)
|
||||
}
|
||||
|
||||
func userPermissionCheckV2(ctx context.Context, query sq.SelectBuilder, enabled bool, queries *UserSearchQueries) sq.SelectBuilder {
|
||||
if !enabled {
|
||||
return query
|
||||
}
|
||||
return query.Where(PermissionClause(
|
||||
ctx,
|
||||
UserResourceOwnerCol,
|
||||
domain.PermissionUserRead,
|
||||
SingleOrgPermissionOption(queries.Queries),
|
||||
OwnedRowsPermissionOption(UserIDCol),
|
||||
))
|
||||
}
|
||||
|
||||
type UserSearchQueries struct {
|
||||
SearchRequest
|
||||
Queries []SearchQuery
|
||||
@@ -606,8 +619,9 @@ func (q *Queries) CountUsers(ctx context.Context, queries *UserSearchQueries) (c
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, filterOrgIds string, permissionCheck domain.PermissionCheck) (*Users, error) {
|
||||
users, err := q.searchUsers(ctx, queries, filterOrgIds, permissionCheck != nil && authz.GetFeatures(ctx).PermissionCheckV2)
|
||||
func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, permissionCheck domain.PermissionCheck) (*Users, error) {
|
||||
permissionCheckV2 := PermissionV2(ctx, permissionCheck)
|
||||
users, err := q.searchUsers(ctx, queries, permissionCheckV2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -617,22 +631,15 @@ func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, f
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (q *Queries) searchUsers(ctx context.Context, queries *UserSearchQueries, filterOrgIds string, permissionCheckV2 bool) (users *Users, err error) {
|
||||
func (q *Queries) searchUsers(ctx context.Context, queries *UserSearchQueries, permissionCheckV2 bool) (users *Users, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
query, scan := prepareUsersQuery()
|
||||
query = queries.toQuery(query).Where(sq.Eq{
|
||||
query = userPermissionCheckV2(ctx, query, permissionCheckV2, queries)
|
||||
stmt, args, err := queries.toQuery(query).Where(sq.Eq{
|
||||
UserInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
})
|
||||
if permissionCheckV2 {
|
||||
query, err = wherePermittedOrgsOrCurrentUser(ctx, query, filterOrgIds, UserResourceOwnerCol.identifier(), UserIDCol.identifier(), domain.PermissionUserRead)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "AUTHZ-HS4us", "Errors.Internal")
|
||||
}
|
||||
}
|
||||
|
||||
stmt, args, err := query.ToSql()
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-Dgbg2", "Errors.Query.SQLStatment")
|
||||
}
|
||||
|
Reference in New Issue
Block a user