Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: user flows permissions fix #5917

Merged
merged 8 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 113 additions & 137 deletions api/auth/user/UserRestHandler.go

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions api/bean/UserRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,47 @@ type BulkDeleteRequest struct {
type UserRoleGroup struct {
RoleGroup *RoleGroup `json:"roleGroup"`
}

type RoleEntity interface {
GetAccessType() string
GetEntity() string
GetTeam() string
GetCluster() string
GetNamespace() string
GetGroup() string
GetKind() string
GetResource() string
}

// For RoleFilter
func (filter RoleFilter) GetAccessType() string {
return filter.AccessType
}

func (filter RoleFilter) GetEntity() string {
return filter.Entity
}

func (filter RoleFilter) GetTeam() string {
return filter.Team
}

func (filter RoleFilter) GetCluster() string {
return filter.Cluster
}

func (filter RoleFilter) GetNamespace() string {
return filter.Namespace
}

func (filter RoleFilter) GetGroup() string {
return filter.Group
}

func (filter RoleFilter) GetKind() string {
return filter.Kind
}

func (filter RoleFilter) GetResource() string {
return filter.Resource
}
2 changes: 1 addition & 1 deletion cmd/external-app/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions pkg/auth/user/RoleGroupService.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package user
import (
"errors"
"fmt"
helper2 "github.com/devtron-labs/devtron/pkg/auth/user/helper"
"github.com/devtron-labs/devtron/pkg/auth/user/repository/helper"
"net/http"
"strings"
Expand All @@ -39,7 +40,7 @@ import (
type RoleGroupService interface {
CreateRoleGroup(request *bean.RoleGroup) (*bean.RoleGroup, error)
UpdateRoleGroup(request *bean.RoleGroup, token string, checkRBACForGroupUpdate func(token string, groupInfo *bean.RoleGroup,
eliminatedRoleFilters []*repository.RoleModel) (isAuthorised bool, err error)) (*bean.RoleGroup, error)
eliminatedRoleFilters []*repository.RoleModel, mapOfExistingRoleFilterKey map[string]bool) (isAuthorised bool, err error)) (*bean.RoleGroup, error)
FetchDetailedRoleGroups(req *bean.ListingRequest) ([]*bean.RoleGroup, error)
FetchRoleGroupsById(id int32) (*bean.RoleGroup, error)
FetchRoleGroups() ([]*bean.RoleGroup, error)
Expand Down Expand Up @@ -369,7 +370,7 @@ func (impl RoleGroupServiceImpl) CreateOrUpdateRoleGroupForJobsEntity(roleFilter
}

func (impl RoleGroupServiceImpl) UpdateRoleGroup(request *bean.RoleGroup, token string, checkRBACForGroupUpdate func(token string, groupInfo *bean.RoleGroup,
eliminatedRoleFilters []*repository.RoleModel) (isAuthorised bool, err error)) (*bean.RoleGroup, error) {
eliminatedRoleFilters []*repository.RoleModel, mapOfExistingRoleFilterKey map[string]bool) (isAuthorised bool, err error)) (*bean.RoleGroup, error) {
dbConnection := impl.roleGroupRepository.GetConnection()
tx, err := dbConnection.Begin()
if err != nil {
Expand Down Expand Up @@ -476,7 +477,13 @@ func (impl RoleGroupServiceImpl) UpdateRoleGroup(request *bean.RoleGroup, token
}

if checkRBACForGroupUpdate != nil {
isAuthorised, err := checkRBACForGroupUpdate(token, request, eliminatedRoleModels)
existingRoleGroupData, err := impl.FetchRoleGroupsById(roleGroup.Id)
if err != nil {
impl.logger.Errorw("error encountered in Update role group", "err", err, "roleGroupId", roleGroup.Id)
return nil, err
}
mapOfExitingRoleFiltersKey := helper2.GetMapOfUniqueKeys(existingRoleGroupData.RoleFilters, util2.GetUniqueKeyForRoleFilter)
isAuthorised, err := checkRBACForGroupUpdate(token, request, eliminatedRoleModels, mapOfExitingRoleFiltersKey)
if err != nil {
impl.logger.Errorw("error in checking RBAC for role group update", "err", err, "request", request)
return nil, err
Expand Down
20 changes: 13 additions & 7 deletions pkg/auth/user/UserService.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type UserService interface {
CreateUser(userInfo *bean.UserInfo) ([]*bean.UserInfo, error)
SelfRegisterUserIfNotExists(userInfo *bean.UserInfo) ([]*bean.UserInfo, error)
UpdateUser(userInfo *bean.UserInfo, token string, checkRBACForUserUpdate func(token string, userInfo *bean.UserInfo, isUserAlreadySuperAdmin bool,
eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel) (isAuthorised bool, err error)) (*bean.UserInfo, error)
eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel, mapOfExistingRoleFilter, mapOfExistingUserGroup map[string]bool) (isAuthorised bool, err error)) (*bean.UserInfo, error)
GetById(id int32) (*bean.UserInfo, error)
GetAll() ([]bean.UserInfo, error)
GetAllWithFilters(request *bean.ListingRequest) (*bean.UserListingResponse, error)
Expand Down Expand Up @@ -572,13 +572,11 @@ func (impl *UserServiceImpl) mergeRoleFilter(oldR []bean.RoleFilter, newR []bean
Resource: role.Resource,
Workflow: role.Workflow,
})
key := fmt.Sprintf("%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", role.Entity, role.Team, role.Environment,
role.EntityName, role.Action, role.AccessType, role.Cluster, role.Namespace, role.Group, role.Kind, role.Resource, role.Workflow)
key := util3.GetUniqueKeyForRoleFilter(role)
keysMap[key] = true
}
for _, role := range newR {
key := fmt.Sprintf("%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", role.Entity, role.Team, role.Environment,
role.EntityName, role.Action, role.AccessType, role.Cluster, role.Namespace, role.Group, role.Kind, role.Resource, role.Workflow)
key := util3.GetUniqueKeyForRoleFilter(role)
if _, ok := keysMap[key]; !ok {
roleFilters = append(roleFilters, bean.RoleFilter{
Entity: role.Entity,
Expand Down Expand Up @@ -635,7 +633,7 @@ func (impl *UserServiceImpl) mergeUserRoleGroup(oldUserRoleGroups []bean.UserRol
}

func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, checkRBACForUserUpdate func(token string, userInfo *bean.UserInfo,
isUserAlreadySuperAdmin bool, eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel) (isAuthorised bool, err error)) (*bean.UserInfo, error) {
isUserAlreadySuperAdmin bool, eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel, mapOfExistingRoleFilter, mapOfExistingUserGroup map[string]bool) (isAuthorised bool, err error)) (*bean.UserInfo, error) {
//checking if request for same user is being processed
isLocked := impl.getUserReqLockStateById(userInfo.Id)
if isLocked {
Expand Down Expand Up @@ -802,7 +800,15 @@ func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, c
}

if checkRBACForUserUpdate != nil {
isAuthorised, err := checkRBACForUserUpdate(token, userInfo, isUserSuperAdmin, eliminatedRoles, eliminatedGroupRoles)
// get existing permissions for user and ignore rbac for unchanged permissions whether direct permissions or group permissions
existingUserInfo, err := impl.GetById(model.Id)
if err != nil {
impl.logger.Errorw("error while fetching user from db", "error", err)
return nil, err
}
uniqueRolefilterKeyMap := userHelper.GetMapOfUniqueKeys(existingUserInfo.RoleFilters, util3.GetUniqueKeyForRoleFilter)
existingRoleGroupKeyMap := userHelper.GetMapOfUniqueKeys(existingUserInfo.UserRoleGroup, userHelper.GetUniqueKeyForUserGroup)
isAuthorised, err := checkRBACForUserUpdate(token, userInfo, isUserSuperAdmin, eliminatedRoles, eliminatedGroupRoles, uniqueRolefilterKeyMap, existingRoleGroupKeyMap)
if err != nil {
impl.logger.Errorw("error in checking RBAC for user update", "err", err, "userInfo", userInfo)
return nil, err
Expand Down
13 changes: 13 additions & 0 deletions pkg/auth/user/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,16 @@ func CreateErrorMessageForUserRoleGroups(restrictedGroups []bean2.RestrictedGrou
}
return errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin
}

// GetMapOfUniqueKeys takes a slice of any type and a function to extract a unique key, returning a map of unique keys.
func GetMapOfUniqueKeys[T any](items []T, getKeyFunc func(T) string) map[string]bool {
uniqueKeyMap := make(map[string]bool, len(items))
for _, item := range items {
uniqueKeyMap[getKeyFunc(item)] = true
}
return uniqueKeyMap
}

func GetUniqueKeyForUserGroup(group bean2.UserRoleGroup) string {
return fmt.Sprintf("%d-%s", group.RoleGroup.Id, group.RoleGroup.Name)
}
33 changes: 33 additions & 0 deletions pkg/auth/user/repository/UserAuthRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,39 @@ type RoleModel struct {
sql.AuditLog
}

// For RoleModel
func (model RoleModel) GetAccessType() string {
return model.AccessType
}

func (model RoleModel) GetEntity() string {
return model.Entity
}

func (model RoleModel) GetTeam() string {
return model.Team
}

func (model RoleModel) GetCluster() string {
return model.Cluster
}

func (model RoleModel) GetNamespace() string {
return model.Namespace
}

func (model RoleModel) GetGroup() string {
return model.Group
}

func (model RoleModel) GetKind() string {
return model.Kind
}

func (model RoleModel) GetResource() string {
return model.Resource
}

type RolePolicyDetails struct {
Team string
Env string
Expand Down
12 changes: 11 additions & 1 deletion pkg/auth/user/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

package util

import "strings"
import (
"fmt"
"github.com/devtron-labs/devtron/api/bean"
"strings"
)

const (
ApiTokenPrefix = "API-TOKEN:"
Expand All @@ -39,3 +43,9 @@ func CheckIfAdminOrApiToken(email string) bool {
func CheckIfApiToken(email string) bool {
return strings.HasPrefix(email, ApiTokenPrefix)
}

func GetUniqueKeyForRoleFilter(role bean.RoleFilter) string {
key := fmt.Sprintf("%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", role.Entity, role.Team, role.Environment,
role.EntityName, role.Action, role.AccessType, role.Cluster, role.Namespace, role.Group, role.Kind, role.Resource, role.Workflow)
return key
}
2 changes: 1 addition & 1 deletion wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading