fix: generalise permission check for query user information (#8458)

# Which Problems Are Solved

IDPLinks list and other list endpoints can provide you with empty
results if the used user has no permission for the information.

# How the Problems Are Solved

List endpoints with subelements to users, and provided userIDQuery, will
return a PermissionDenied error if no permission for the user exsists.

# Additional Changes

Function to check for permission is re-used from the GetUserByID.

# Additional Context

Closes #8451
This commit is contained in:
Stefan Benz
2024-08-23 08:44:18 +02:00
committed by GitHub
parent 8051a63147
commit 2847806531
27 changed files with 552 additions and 111 deletions

View File

@@ -9,15 +9,17 @@ import (
"regexp"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors"
)
func TestUser_RemoveNoPermission(t *testing.T) {
func TestUser_usersCheckPermission(t *testing.T) {
type want struct {
users []*User
}
@@ -140,6 +142,85 @@ func TestUser_RemoveNoPermission(t *testing.T) {
}
}
func TestUser_userCheckPermission(t *testing.T) {
type args struct {
ctxData string
resourceowner string
user string
}
type perm struct {
resourceowner string
user string
}
tests := []struct {
name string
wantErr bool
args args
permissions []perm
}{
{
name: "permission, self",
args: args{
resourceowner: "org",
user: "user",
ctxData: "user",
},
permissions: []perm{},
},
{
name: "permission, user",
args: args{
resourceowner: "org1",
user: "user1",
ctxData: "user2",
},
permissions: []perm{{"org1", "user1"}},
wantErr: false,
},
{
name: "permission, org",
args: args{
resourceowner: "org1",
user: "user1",
ctxData: "user2",
},
permissions: []perm{{"org1", "user3"}},
},
{
name: "permission, none",
args: args{
resourceowner: "org1",
user: "user1",
ctxData: "user2",
},
permissions: []perm{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
checkPermission := func(ctx context.Context, permission, orgID, resourceID string) (err error) {
for _, perm := range tt.permissions {
if resourceID == perm.user {
return nil
}
if orgID == perm.resourceowner {
return nil
}
}
return errors.New("failed")
}
granted := userCheckPermission(authz.SetCtxData(context.Background(), authz.CtxData{UserID: tt.args.ctxData}), tt.args.resourceowner, tt.args.user, checkPermission)
if tt.wantErr {
assert.Error(t, granted)
} else {
assert.NoError(t, granted)
}
})
}
}
var (
loginNamesQuery = `SELECT login_names.user_id, ARRAY_AGG(login_names.login_name)::TEXT[] AS loginnames, ARRAY_AGG(LOWER(login_names.login_name))::TEXT[] AS loginnames_lower, login_names.instance_id` +
` FROM projections.login_names3 AS login_names` +