mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
feat: usergrant (#489)
* fix: search usergrants only for allowed projects * fix: check permissions * fix: check permissions * fix: check permissions * Update internal/management/repository/eventsourcing/eventstore/project.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix: merge request changes * fix: variable name Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
@@ -98,7 +98,19 @@ func HasGlobalPermission(perms []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func GetPermissionCtxIDs(perms []string) []string {
|
||||
func HasGlobalExplicitPermission(perms []string, permToCheck string) bool {
|
||||
for _, perm := range perms {
|
||||
p, ctxID := SplitPermission(perm)
|
||||
if p == permToCheck {
|
||||
if ctxID == "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetAllPermissionCtxIDs(perms []string) []string {
|
||||
ctxIDs := make([]string, 0)
|
||||
for _, perm := range perms {
|
||||
_, ctxID := SplitPermission(perm)
|
||||
@@ -108,3 +120,16 @@ func GetPermissionCtxIDs(perms []string) []string {
|
||||
}
|
||||
return ctxIDs
|
||||
}
|
||||
|
||||
func GetExplicitPermissionCtxIDs(perms []string, searchPerm string) []string {
|
||||
ctxIDs := make([]string, 0)
|
||||
for _, perm := range perms {
|
||||
p, ctxID := SplitPermission(perm)
|
||||
if p == searchPerm {
|
||||
if ctxID != "" {
|
||||
ctxIDs = append(ctxIDs, ctxID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ctxIDs
|
||||
}
|
||||
|
@@ -269,7 +269,7 @@ func Test_GetPermissionCtxIDs(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := GetPermissionCtxIDs(tt.args.perms)
|
||||
result := GetAllPermissionCtxIDs(tt.args.perms)
|
||||
if !equalStringArray(result, tt.result) {
|
||||
t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result)
|
||||
}
|
||||
|
@@ -10,8 +10,9 @@ import (
|
||||
type key int
|
||||
|
||||
const (
|
||||
permissionsKey key = 1
|
||||
dataKey key = 2
|
||||
requestPermissionsKey key = 1
|
||||
dataKey key = 2
|
||||
allPermissionsKey key = 3
|
||||
)
|
||||
|
||||
type CtxData struct {
|
||||
@@ -59,7 +60,12 @@ func GetCtxData(ctx context.Context) CtxData {
|
||||
return ctxData
|
||||
}
|
||||
|
||||
func GetPermissionsFromCtx(ctx context.Context) []string {
|
||||
ctxPermission, _ := ctx.Value(permissionsKey).([]string)
|
||||
func GetRequestPermissionsFromCtx(ctx context.Context) []string {
|
||||
ctxPermission, _ := ctx.Value(requestPermissionsKey).([]string)
|
||||
return ctxPermission
|
||||
}
|
||||
|
||||
func GetAllPermissionsFromCtx(ctx context.Context) []string {
|
||||
ctxPermission, _ := ctx.Value(allPermissionsKey).([]string)
|
||||
return ctxPermission
|
||||
}
|
||||
|
@@ -16,34 +16,40 @@ func getUserMethodPermissions(ctx context.Context, t *TokenVerifier, requiredPer
|
||||
return nil, nil, err
|
||||
}
|
||||
if grant == nil {
|
||||
return context.WithValue(ctx, permissionsKey, []string{}), []string{}, nil
|
||||
return context.WithValue(ctx, requestPermissionsKey, []string{}), []string{}, nil
|
||||
}
|
||||
permissions := mapGrantToPermissions(requiredPerm, grant, authConfig)
|
||||
return context.WithValue(ctx, permissionsKey, permissions), permissions, nil
|
||||
requestPermissions, allPermissions := mapGrantToPermissions(requiredPerm, grant, authConfig)
|
||||
ctx = context.WithValue(ctx, allPermissionsKey, allPermissions)
|
||||
return context.WithValue(ctx, requestPermissionsKey, requestPermissions), requestPermissions, nil
|
||||
}
|
||||
|
||||
func mapGrantToPermissions(requiredPerm string, grant *Grant, authConfig Config) []string {
|
||||
resolvedPermissions := make([]string, 0)
|
||||
func mapGrantToPermissions(requiredPerm string, grant *Grant, authConfig Config) ([]string, []string) {
|
||||
requestPermissions := make([]string, 0)
|
||||
allPermissions := make([]string, 0)
|
||||
for _, role := range grant.Roles {
|
||||
resolvedPermissions = mapRoleToPerm(requiredPerm, role, authConfig, resolvedPermissions)
|
||||
requestPermissions, allPermissions = mapRoleToPerm(requiredPerm, role, authConfig, requestPermissions, allPermissions)
|
||||
}
|
||||
|
||||
return resolvedPermissions
|
||||
return requestPermissions, allPermissions
|
||||
}
|
||||
|
||||
func mapRoleToPerm(requiredPerm, actualRole string, authConfig Config, resolvedPermissions []string) []string {
|
||||
func mapRoleToPerm(requiredPerm, actualRole string, authConfig Config, requestPermissions, allPermissions []string) ([]string, []string) {
|
||||
roleName, roleContextID := SplitPermission(actualRole)
|
||||
perms := authConfig.getPermissionsFromRole(roleName)
|
||||
|
||||
for _, p := range perms {
|
||||
permWithCtx := addRoleContextIDToPerm(p, roleContextID)
|
||||
if !ExistsPerm(allPermissions, permWithCtx) {
|
||||
allPermissions = append(allPermissions, permWithCtx)
|
||||
}
|
||||
|
||||
if p == requiredPerm {
|
||||
p = addRoleContextIDToPerm(p, roleContextID)
|
||||
if !ExistsPerm(resolvedPermissions, p) {
|
||||
resolvedPermissions = append(resolvedPermissions, p)
|
||||
if !ExistsPerm(requestPermissions, permWithCtx) {
|
||||
requestPermissions = append(requestPermissions, permWithCtx)
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolvedPermissions
|
||||
return requestPermissions, allPermissions
|
||||
}
|
||||
|
||||
func addRoleContextIDToPerm(perm, roleContextID string) string {
|
||||
|
@@ -157,9 +157,10 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
authConfig Config
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result []string
|
||||
name string
|
||||
args args
|
||||
requestPerms []string
|
||||
allPerms []string
|
||||
}{
|
||||
{
|
||||
name: "One Role existing perm",
|
||||
@@ -179,7 +180,8 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
{
|
||||
name: "One Role not existing perm",
|
||||
@@ -199,7 +201,8 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []string{},
|
||||
requestPerms: []string{},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
{
|
||||
name: "Multiple Roles one existing",
|
||||
@@ -219,7 +222,8 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
{
|
||||
name: "Multiple Roles, global and specific",
|
||||
@@ -239,14 +243,18 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []string{"project.read", "project.read:1"},
|
||||
requestPerms: []string{"project.read", "project.read:1"},
|
||||
allPerms: []string{"org.read", "project.read", "project.read:1"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := mapGrantToPermissions(tt.args.requiredPerm, tt.args.grant, tt.args.authConfig)
|
||||
if !equalStringArray(result, tt.result) {
|
||||
t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result)
|
||||
requestPerms, allPerms := mapGrantToPermissions(tt.args.requiredPerm, tt.args.grant, tt.args.authConfig)
|
||||
if !equalStringArray(requestPerms, tt.requestPerms) {
|
||||
t.Errorf("got wrong requestPerms, expecting: %v, actual: %v ", tt.requestPerms, requestPerms)
|
||||
}
|
||||
if !equalStringArray(allPerms, tt.allPerms) {
|
||||
t.Errorf("got wrong allPerms, expecting: %v, actual: %v ", tt.allPerms, allPerms)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -254,15 +262,17 @@ func Test_MapGrantsToPermissions(t *testing.T) {
|
||||
|
||||
func Test_MapRoleToPerm(t *testing.T) {
|
||||
type args struct {
|
||||
requiredPerm string
|
||||
actualRole string
|
||||
authConfig Config
|
||||
resolvedPermissions []string
|
||||
requiredPerm string
|
||||
actualRole string
|
||||
authConfig Config
|
||||
requestPerms []string
|
||||
allPerms []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result []string
|
||||
name string
|
||||
args args
|
||||
requestPerms []string
|
||||
allPerms []string
|
||||
}{
|
||||
{
|
||||
name: "first perm without context id",
|
||||
@@ -281,9 +291,11 @@ func Test_MapRoleToPerm(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
resolvedPermissions: []string{},
|
||||
requestPerms: []string{},
|
||||
allPerms: []string{},
|
||||
},
|
||||
result: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
{
|
||||
name: "existing perm without context id",
|
||||
@@ -302,9 +314,11 @@ func Test_MapRoleToPerm(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
resolvedPermissions: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
result: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
{
|
||||
name: "first perm with context id",
|
||||
@@ -323,9 +337,11 @@ func Test_MapRoleToPerm(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
resolvedPermissions: []string{},
|
||||
requestPerms: []string{},
|
||||
allPerms: []string{},
|
||||
},
|
||||
result: []string{"project.read:1"},
|
||||
requestPerms: []string{"project.read:1"},
|
||||
allPerms: []string{"project.read:1"},
|
||||
},
|
||||
{
|
||||
name: "perm with context id, existing global",
|
||||
@@ -344,16 +360,21 @@ func Test_MapRoleToPerm(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
resolvedPermissions: []string{"project.read"},
|
||||
requestPerms: []string{"project.read"},
|
||||
allPerms: []string{"org.read", "project.read"},
|
||||
},
|
||||
result: []string{"project.read", "project.read:1"},
|
||||
requestPerms: []string{"project.read", "project.read:1"},
|
||||
allPerms: []string{"org.read", "project.read", "project.read:1"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := mapRoleToPerm(tt.args.requiredPerm, tt.args.actualRole, tt.args.authConfig, tt.args.resolvedPermissions)
|
||||
if !equalStringArray(result, tt.result) {
|
||||
t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result)
|
||||
requestPerms, allPerms := mapRoleToPerm(tt.args.requiredPerm, tt.args.actualRole, tt.args.authConfig, tt.args.requestPerms, tt.args.allPerms)
|
||||
if !equalStringArray(requestPerms, tt.requestPerms) {
|
||||
t.Errorf("got wrong requestPerms, expecting: %v, actual: %v ", tt.requestPerms, requestPerms)
|
||||
}
|
||||
if !equalStringArray(allPerms, tt.allPerms) {
|
||||
t.Errorf("got wrong allPerms, expecting: %v, actual: %v ", tt.allPerms, allPerms)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -61,7 +61,7 @@ func (s *Server) ProjectByID(ctx context.Context, id *management.ProjectID) (*ma
|
||||
func (s *Server) SearchGrantedProjects(ctx context.Context, in *management.GrantedProjectSearchRequest) (*management.ProjectGrantSearchResponse, error) {
|
||||
request := grantedProjectSearchRequestsToModel(in)
|
||||
request.AppendMyOrgQuery(grpc_util.GetHeader(ctx, http.ZitadelOrgID))
|
||||
response, err := s.project.SearchProjectGrants(ctx, request)
|
||||
response, err := s.project.SearchGrantedProjects(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -27,6 +27,22 @@ func (s *Server) UserGrantByID(ctx context.Context, request *management.UserGran
|
||||
return userGrantViewFromModel(user), nil
|
||||
}
|
||||
|
||||
func (s *Server) CreateUserGrant(ctx context.Context, in *management.UserGrantCreate) (*management.UserGrant, error) {
|
||||
user, err := s.usergrant.AddUserGrant(ctx, userGrantCreateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return usergrantFromModel(user), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateUserGrant(ctx context.Context, in *management.UserGrantUpdate) (*management.UserGrant, error) {
|
||||
user, err := s.usergrant.ChangeUserGrant(ctx, userGrantUpdateToModel(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return usergrantFromModel(user), nil
|
||||
}
|
||||
|
||||
func (s *Server) DeactivateUserGrant(ctx context.Context, in *management.UserGrantID) (*management.UserGrant, error) {
|
||||
user, err := s.usergrant.DeactivateUserGrant(ctx, in.Id)
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user