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:
Tim Möhlmann
2025-04-15 19:38:25 +03:00
committed by GitHub
parent 3b8a2ab811
commit a2f60f2e7a
23 changed files with 741 additions and 172 deletions

View File

@@ -3,6 +3,8 @@ package authz
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/internal/zerrors"
)
@@ -276,3 +278,127 @@ func Test_GetPermissionCtxIDs(t *testing.T) {
})
}
}
func Test_systemMembershipsToUserPermissions(t *testing.T) {
roleMap := []RoleMapping{
{
Role: "FOO_BAR",
Permissions: []string{"foo.bar.read", "foo.bar.write"},
},
{
Role: "BAR_FOO",
Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read"},
},
}
type args struct {
memberships Memberships
roleMap []RoleMapping
}
tests := []struct {
name string
args args
want []SystemUserPermissions
}{
{
name: "nil memberships",
args: args{
memberships: nil,
roleMap: roleMap,
},
want: nil,
},
{
name: "empty memberships",
args: args{
memberships: Memberships{},
roleMap: roleMap,
},
want: []SystemUserPermissions{},
},
{
name: "single membership",
args: args{
memberships: Memberships{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Roles: []string{"FOO_BAR"},
},
},
roleMap: roleMap,
},
want: []SystemUserPermissions{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Permissions: []string{"foo.bar.read", "foo.bar.write"},
},
},
},
{
name: "multiple memberships",
args: args{
memberships: Memberships{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Roles: []string{"FOO_BAR"},
},
{
MemberType: MemberTypeIAM,
AggregateID: "1",
ObjectID: "2",
Roles: []string{"BAR_FOO"},
},
},
roleMap: roleMap,
},
want: []SystemUserPermissions{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Permissions: []string{"foo.bar.read", "foo.bar.write"},
},
{
MemberType: MemberTypeIAM,
AggregateID: "1",
ObjectID: "2",
Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read"},
},
},
},
{
name: "multiple roles",
args: args{
memberships: Memberships{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Roles: []string{"FOO_BAR", "BAR_FOO"},
},
},
roleMap: roleMap,
},
want: []SystemUserPermissions{
{
MemberType: MemberTypeSystem,
AggregateID: "1",
ObjectID: "2",
Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read", "foo.bar.write"},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := systemMembershipsToUserPermissions(tt.args.memberships, tt.args.roleMap)
assert.Equal(t, tt.want, got)
})
}
}