portainer/portainer

View on GitHub
api/internal/authorization/authorizations.go

Summary

Maintainability
D
1 day
Test Coverage
package authorization

import (
    portainer "github.com/portainer/portainer/api"
    "github.com/portainer/portainer/api/dataservices"
    "github.com/portainer/portainer/api/kubernetes/cli"
)

// Service represents a service used to
// update authorizations associated to a user or team.
type Service struct {
    dataStore        dataservices.DataStoreTx
    K8sClientFactory *cli.ClientFactory
}

// NewService returns a point to a new Service instance.
func NewService(dataStore dataservices.DataStoreTx) *Service {
    return &Service{
        dataStore: dataStore,
    }
}

// DefaultEndpointAuthorizationsForEndpointAdministratorRole returns the default environment(endpoint) authorizations
// associated to the environment(endpoint) administrator role.
func DefaultEndpointAuthorizationsForEndpointAdministratorRole() portainer.Authorizations {
    return map[portainer.Authorization]bool{
        portainer.OperationDockerContainerArchiveInfo:         true,
        portainer.OperationDockerContainerList:                true,
        portainer.OperationDockerContainerExport:              true,
        portainer.OperationDockerContainerChanges:             true,
        portainer.OperationDockerContainerInspect:             true,
        portainer.OperationDockerContainerTop:                 true,
        portainer.OperationDockerContainerLogs:                true,
        portainer.OperationDockerContainerStats:               true,
        portainer.OperationDockerContainerAttachWebsocket:     true,
        portainer.OperationDockerContainerArchive:             true,
        portainer.OperationDockerContainerCreate:              true,
        portainer.OperationDockerContainerPrune:               true,
        portainer.OperationDockerContainerKill:                true,
        portainer.OperationDockerContainerPause:               true,
        portainer.OperationDockerContainerUnpause:             true,
        portainer.OperationDockerContainerRestart:             true,
        portainer.OperationDockerContainerStart:               true,
        portainer.OperationDockerContainerStop:                true,
        portainer.OperationDockerContainerWait:                true,
        portainer.OperationDockerContainerResize:              true,
        portainer.OperationDockerContainerAttach:              true,
        portainer.OperationDockerContainerExec:                true,
        portainer.OperationDockerContainerRename:              true,
        portainer.OperationDockerContainerUpdate:              true,
        portainer.OperationDockerContainerPutContainerArchive: true,
        portainer.OperationDockerContainerDelete:              true,
        portainer.OperationDockerImageList:                    true,
        portainer.OperationDockerImageSearch:                  true,
        portainer.OperationDockerImageGetAll:                  true,
        portainer.OperationDockerImageGet:                     true,
        portainer.OperationDockerImageHistory:                 true,
        portainer.OperationDockerImageInspect:                 true,
        portainer.OperationDockerImageLoad:                    true,
        portainer.OperationDockerImageCreate:                  true,
        portainer.OperationDockerImagePrune:                   true,
        portainer.OperationDockerImagePush:                    true,
        portainer.OperationDockerImageTag:                     true,
        portainer.OperationDockerImageDelete:                  true,
        portainer.OperationDockerImageCommit:                  true,
        portainer.OperationDockerImageBuild:                   true,
        portainer.OperationDockerNetworkList:                  true,
        portainer.OperationDockerNetworkInspect:               true,
        portainer.OperationDockerNetworkCreate:                true,
        portainer.OperationDockerNetworkConnect:               true,
        portainer.OperationDockerNetworkDisconnect:            true,
        portainer.OperationDockerNetworkPrune:                 true,
        portainer.OperationDockerNetworkDelete:                true,
        portainer.OperationDockerVolumeList:                   true,
        portainer.OperationDockerVolumeInspect:                true,
        portainer.OperationDockerVolumeCreate:                 true,
        portainer.OperationDockerVolumePrune:                  true,
        portainer.OperationDockerVolumeDelete:                 true,
        portainer.OperationDockerExecInspect:                  true,
        portainer.OperationDockerExecStart:                    true,
        portainer.OperationDockerExecResize:                   true,
        portainer.OperationDockerSwarmInspect:                 true,
        portainer.OperationDockerSwarmUnlockKey:               true,
        portainer.OperationDockerSwarmInit:                    true,
        portainer.OperationDockerSwarmJoin:                    true,
        portainer.OperationDockerSwarmLeave:                   true,
        portainer.OperationDockerSwarmUpdate:                  true,
        portainer.OperationDockerSwarmUnlock:                  true,
        portainer.OperationDockerNodeList:                     true,
        portainer.OperationDockerNodeInspect:                  true,
        portainer.OperationDockerNodeUpdate:                   true,
        portainer.OperationDockerNodeDelete:                   true,
        portainer.OperationDockerServiceList:                  true,
        portainer.OperationDockerServiceInspect:               true,
        portainer.OperationDockerServiceLogs:                  true,
        portainer.OperationDockerServiceCreate:                true,
        portainer.OperationDockerServiceUpdate:                true,
        portainer.OperationDockerServiceDelete:                true,
        portainer.OperationDockerSecretList:                   true,
        portainer.OperationDockerSecretInspect:                true,
        portainer.OperationDockerSecretCreate:                 true,
        portainer.OperationDockerSecretUpdate:                 true,
        portainer.OperationDockerSecretDelete:                 true,
        portainer.OperationDockerConfigList:                   true,
        portainer.OperationDockerConfigInspect:                true,
        portainer.OperationDockerConfigCreate:                 true,
        portainer.OperationDockerConfigUpdate:                 true,
        portainer.OperationDockerConfigDelete:                 true,
        portainer.OperationDockerTaskList:                     true,
        portainer.OperationDockerTaskInspect:                  true,
        portainer.OperationDockerTaskLogs:                     true,
        portainer.OperationDockerPluginList:                   true,
        portainer.OperationDockerPluginPrivileges:             true,
        portainer.OperationDockerPluginInspect:                true,
        portainer.OperationDockerPluginPull:                   true,
        portainer.OperationDockerPluginCreate:                 true,
        portainer.OperationDockerPluginEnable:                 true,
        portainer.OperationDockerPluginDisable:                true,
        portainer.OperationDockerPluginPush:                   true,
        portainer.OperationDockerPluginUpgrade:                true,
        portainer.OperationDockerPluginSet:                    true,
        portainer.OperationDockerPluginDelete:                 true,
        portainer.OperationDockerSessionStart:                 true,
        portainer.OperationDockerDistributionInspect:          true,
        portainer.OperationDockerBuildPrune:                   true,
        portainer.OperationDockerBuildCancel:                  true,
        portainer.OperationDockerPing:                         true,
        portainer.OperationDockerInfo:                         true,
        portainer.OperationDockerVersion:                      true,
        portainer.OperationDockerEvents:                       true,
        portainer.OperationDockerSystem:                       true,
        portainer.OperationDockerUndefined:                    true,
        portainer.OperationDockerAgentPing:                    true,
        portainer.OperationDockerAgentList:                    true,
        portainer.OperationDockerAgentHostInfo:                true,
        portainer.OperationDockerAgentBrowseDelete:            true,
        portainer.OperationDockerAgentBrowseGet:               true,
        portainer.OperationDockerAgentBrowseList:              true,
        portainer.OperationDockerAgentBrowsePut:               true,
        portainer.OperationDockerAgentBrowseRename:            true,
        portainer.OperationDockerAgentUndefined:               true,
        portainer.OperationPortainerResourceControlCreate:     true,
        portainer.OperationPortainerResourceControlUpdate:     true,
        portainer.OperationPortainerRegistryUpdateAccess:      true,
        portainer.OperationPortainerStackList:                 true,
        portainer.OperationPortainerStackInspect:              true,
        portainer.OperationPortainerStackFile:                 true,
        portainer.OperationPortainerStackCreate:               true,
        portainer.OperationPortainerStackMigrate:              true,
        portainer.OperationPortainerStackUpdate:               true,
        portainer.OperationPortainerStackDelete:               true,
        portainer.OperationPortainerWebsocketExec:             true,
        portainer.OperationPortainerWebhookList:               true,
        portainer.OperationPortainerWebhookCreate:             true,
        portainer.OperationPortainerWebhookDelete:             true,
        portainer.EndpointResourcesAccess:                     true,
    }
}

// DefaultEndpointAuthorizationsForHelpDeskRole returns the default environment(endpoint) authorizations
// associated to the helpdesk role.
func DefaultEndpointAuthorizationsForHelpDeskRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
    authorizations := map[portainer.Authorization]bool{
        portainer.OperationDockerContainerArchiveInfo: true,
        portainer.OperationDockerContainerList:        true,
        portainer.OperationDockerContainerChanges:     true,
        portainer.OperationDockerContainerInspect:     true,
        portainer.OperationDockerContainerTop:         true,
        portainer.OperationDockerContainerLogs:        true,
        portainer.OperationDockerContainerStats:       true,
        portainer.OperationDockerImageList:            true,
        portainer.OperationDockerImageSearch:          true,
        portainer.OperationDockerImageGetAll:          true,
        portainer.OperationDockerImageGet:             true,
        portainer.OperationDockerImageHistory:         true,
        portainer.OperationDockerImageInspect:         true,
        portainer.OperationDockerNetworkList:          true,
        portainer.OperationDockerNetworkInspect:       true,
        portainer.OperationDockerVolumeList:           true,
        portainer.OperationDockerVolumeInspect:        true,
        portainer.OperationDockerSwarmInspect:         true,
        portainer.OperationDockerNodeList:             true,
        portainer.OperationDockerNodeInspect:          true,
        portainer.OperationDockerServiceList:          true,
        portainer.OperationDockerServiceInspect:       true,
        portainer.OperationDockerServiceLogs:          true,
        portainer.OperationDockerSecretList:           true,
        portainer.OperationDockerSecretInspect:        true,
        portainer.OperationDockerConfigList:           true,
        portainer.OperationDockerConfigInspect:        true,
        portainer.OperationDockerTaskList:             true,
        portainer.OperationDockerTaskInspect:          true,
        portainer.OperationDockerTaskLogs:             true,
        portainer.OperationDockerPluginList:           true,
        portainer.OperationDockerDistributionInspect:  true,
        portainer.OperationDockerPing:                 true,
        portainer.OperationDockerInfo:                 true,
        portainer.OperationDockerVersion:              true,
        portainer.OperationDockerEvents:               true,
        portainer.OperationDockerSystem:               true,
        portainer.OperationDockerAgentPing:            true,
        portainer.OperationDockerAgentList:            true,
        portainer.OperationDockerAgentHostInfo:        true,
        portainer.OperationPortainerStackList:         true,
        portainer.OperationPortainerStackInspect:      true,
        portainer.OperationPortainerStackFile:         true,
        portainer.OperationPortainerWebhookList:       true,
        portainer.EndpointResourcesAccess:             true,
    }

    if volumeBrowsingAuthorizations {
        authorizations[portainer.OperationDockerAgentBrowseGet] = true
        authorizations[portainer.OperationDockerAgentBrowseList] = true
    }

    return authorizations
}

// DefaultEndpointAuthorizationsForStandardUserRole returns the default environment(endpoint) authorizations
// associated to the standard user role.
func DefaultEndpointAuthorizationsForStandardUserRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
    authorizations := map[portainer.Authorization]bool{
        portainer.OperationDockerContainerArchiveInfo:         true,
        portainer.OperationDockerContainerList:                true,
        portainer.OperationDockerContainerExport:              true,
        portainer.OperationDockerContainerChanges:             true,
        portainer.OperationDockerContainerInspect:             true,
        portainer.OperationDockerContainerTop:                 true,
        portainer.OperationDockerContainerLogs:                true,
        portainer.OperationDockerContainerStats:               true,
        portainer.OperationDockerContainerAttachWebsocket:     true,
        portainer.OperationDockerContainerArchive:             true,
        portainer.OperationDockerContainerCreate:              true,
        portainer.OperationDockerContainerKill:                true,
        portainer.OperationDockerContainerPause:               true,
        portainer.OperationDockerContainerUnpause:             true,
        portainer.OperationDockerContainerRestart:             true,
        portainer.OperationDockerContainerStart:               true,
        portainer.OperationDockerContainerStop:                true,
        portainer.OperationDockerContainerWait:                true,
        portainer.OperationDockerContainerResize:              true,
        portainer.OperationDockerContainerAttach:              true,
        portainer.OperationDockerContainerExec:                true,
        portainer.OperationDockerContainerRename:              true,
        portainer.OperationDockerContainerUpdate:              true,
        portainer.OperationDockerContainerPutContainerArchive: true,
        portainer.OperationDockerContainerDelete:              true,
        portainer.OperationDockerImageList:                    true,
        portainer.OperationDockerImageSearch:                  true,
        portainer.OperationDockerImageGetAll:                  true,
        portainer.OperationDockerImageGet:                     true,
        portainer.OperationDockerImageHistory:                 true,
        portainer.OperationDockerImageInspect:                 true,
        portainer.OperationDockerImageLoad:                    true,
        portainer.OperationDockerImageCreate:                  true,
        portainer.OperationDockerImagePush:                    true,
        portainer.OperationDockerImageTag:                     true,
        portainer.OperationDockerImageDelete:                  true,
        portainer.OperationDockerImageCommit:                  true,
        portainer.OperationDockerImageBuild:                   true,
        portainer.OperationDockerNetworkList:                  true,
        portainer.OperationDockerNetworkInspect:               true,
        portainer.OperationDockerNetworkCreate:                true,
        portainer.OperationDockerNetworkConnect:               true,
        portainer.OperationDockerNetworkDisconnect:            true,
        portainer.OperationDockerNetworkDelete:                true,
        portainer.OperationDockerVolumeList:                   true,
        portainer.OperationDockerVolumeInspect:                true,
        portainer.OperationDockerVolumeCreate:                 true,
        portainer.OperationDockerVolumeDelete:                 true,
        portainer.OperationDockerExecInspect:                  true,
        portainer.OperationDockerExecStart:                    true,
        portainer.OperationDockerExecResize:                   true,
        portainer.OperationDockerSwarmInspect:                 true,
        portainer.OperationDockerSwarmUnlockKey:               true,
        portainer.OperationDockerSwarmInit:                    true,
        portainer.OperationDockerSwarmJoin:                    true,
        portainer.OperationDockerSwarmLeave:                   true,
        portainer.OperationDockerSwarmUpdate:                  true,
        portainer.OperationDockerSwarmUnlock:                  true,
        portainer.OperationDockerNodeList:                     true,
        portainer.OperationDockerNodeInspect:                  true,
        portainer.OperationDockerNodeUpdate:                   true,
        portainer.OperationDockerNodeDelete:                   true,
        portainer.OperationDockerServiceList:                  true,
        portainer.OperationDockerServiceInspect:               true,
        portainer.OperationDockerServiceLogs:                  true,
        portainer.OperationDockerServiceCreate:                true,
        portainer.OperationDockerServiceUpdate:                true,
        portainer.OperationDockerServiceDelete:                true,
        portainer.OperationDockerSecretList:                   true,
        portainer.OperationDockerSecretInspect:                true,
        portainer.OperationDockerSecretCreate:                 true,
        portainer.OperationDockerSecretUpdate:                 true,
        portainer.OperationDockerSecretDelete:                 true,
        portainer.OperationDockerConfigList:                   true,
        portainer.OperationDockerConfigInspect:                true,
        portainer.OperationDockerConfigCreate:                 true,
        portainer.OperationDockerConfigUpdate:                 true,
        portainer.OperationDockerConfigDelete:                 true,
        portainer.OperationDockerTaskList:                     true,
        portainer.OperationDockerTaskInspect:                  true,
        portainer.OperationDockerTaskLogs:                     true,
        portainer.OperationDockerPluginList:                   true,
        portainer.OperationDockerPluginPrivileges:             true,
        portainer.OperationDockerPluginInspect:                true,
        portainer.OperationDockerPluginPull:                   true,
        portainer.OperationDockerPluginCreate:                 true,
        portainer.OperationDockerPluginEnable:                 true,
        portainer.OperationDockerPluginDisable:                true,
        portainer.OperationDockerPluginPush:                   true,
        portainer.OperationDockerPluginUpgrade:                true,
        portainer.OperationDockerPluginSet:                    true,
        portainer.OperationDockerPluginDelete:                 true,
        portainer.OperationDockerSessionStart:                 true,
        portainer.OperationDockerDistributionInspect:          true,
        portainer.OperationDockerBuildPrune:                   true,
        portainer.OperationDockerBuildCancel:                  true,
        portainer.OperationDockerPing:                         true,
        portainer.OperationDockerInfo:                         true,
        portainer.OperationDockerVersion:                      true,
        portainer.OperationDockerEvents:                       true,
        portainer.OperationDockerSystem:                       true,
        portainer.OperationDockerUndefined:                    true,
        portainer.OperationDockerAgentPing:                    true,
        portainer.OperationDockerAgentList:                    true,
        portainer.OperationDockerAgentHostInfo:                true,
        portainer.OperationDockerAgentUndefined:               true,
        portainer.OperationPortainerResourceControlUpdate:     true,
        portainer.OperationPortainerStackList:                 true,
        portainer.OperationPortainerStackInspect:              true,
        portainer.OperationPortainerStackFile:                 true,
        portainer.OperationPortainerStackCreate:               true,
        portainer.OperationPortainerStackMigrate:              true,
        portainer.OperationPortainerStackUpdate:               true,
        portainer.OperationPortainerStackDelete:               true,
        portainer.OperationPortainerWebsocketExec:             true,
        portainer.OperationPortainerWebhookList:               true,
        portainer.OperationPortainerWebhookCreate:             true,
    }

    if volumeBrowsingAuthorizations {
        authorizations[portainer.OperationDockerAgentBrowseGet] = true
        authorizations[portainer.OperationDockerAgentBrowseList] = true
        authorizations[portainer.OperationDockerAgentBrowseDelete] = true
        authorizations[portainer.OperationDockerAgentBrowsePut] = true
        authorizations[portainer.OperationDockerAgentBrowseRename] = true
    }

    return authorizations
}

// DefaultEndpointAuthorizationsForReadOnlyUserRole returns the default environment(endpoint) authorizations
// associated to the readonly user role.
func DefaultEndpointAuthorizationsForReadOnlyUserRole(volumeBrowsingAuthorizations bool) portainer.Authorizations {
    authorizations := map[portainer.Authorization]bool{
        portainer.OperationDockerContainerArchiveInfo: true,
        portainer.OperationDockerContainerList:        true,
        portainer.OperationDockerContainerChanges:     true,
        portainer.OperationDockerContainerInspect:     true,
        portainer.OperationDockerContainerTop:         true,
        portainer.OperationDockerContainerLogs:        true,
        portainer.OperationDockerContainerStats:       true,
        portainer.OperationDockerImageList:            true,
        portainer.OperationDockerImageSearch:          true,
        portainer.OperationDockerImageGetAll:          true,
        portainer.OperationDockerImageGet:             true,
        portainer.OperationDockerImageHistory:         true,
        portainer.OperationDockerImageInspect:         true,
        portainer.OperationDockerNetworkList:          true,
        portainer.OperationDockerNetworkInspect:       true,
        portainer.OperationDockerVolumeList:           true,
        portainer.OperationDockerVolumeInspect:        true,
        portainer.OperationDockerSwarmInspect:         true,
        portainer.OperationDockerNodeList:             true,
        portainer.OperationDockerNodeInspect:          true,
        portainer.OperationDockerServiceList:          true,
        portainer.OperationDockerServiceInspect:       true,
        portainer.OperationDockerServiceLogs:          true,
        portainer.OperationDockerSecretList:           true,
        portainer.OperationDockerSecretInspect:        true,
        portainer.OperationDockerConfigList:           true,
        portainer.OperationDockerConfigInspect:        true,
        portainer.OperationDockerTaskList:             true,
        portainer.OperationDockerTaskInspect:          true,
        portainer.OperationDockerTaskLogs:             true,
        portainer.OperationDockerPluginList:           true,
        portainer.OperationDockerDistributionInspect:  true,
        portainer.OperationDockerPing:                 true,
        portainer.OperationDockerInfo:                 true,
        portainer.OperationDockerVersion:              true,
        portainer.OperationDockerEvents:               true,
        portainer.OperationDockerSystem:               true,
        portainer.OperationDockerAgentPing:            true,
        portainer.OperationDockerAgentList:            true,
        portainer.OperationDockerAgentHostInfo:        true,
        portainer.OperationPortainerStackList:         true,
        portainer.OperationPortainerStackInspect:      true,
        portainer.OperationPortainerStackFile:         true,
        portainer.OperationPortainerWebhookList:       true,
    }

    if volumeBrowsingAuthorizations {
        authorizations[portainer.OperationDockerAgentBrowseGet] = true
        authorizations[portainer.OperationDockerAgentBrowseList] = true
    }

    return authorizations
}

// DefaultPortainerAuthorizations returns the default Portainer authorizations used by non-admin users.
func DefaultPortainerAuthorizations() portainer.Authorizations {
    return map[portainer.Authorization]bool{
        portainer.OperationPortainerDockerHubInspect:  true,
        portainer.OperationPortainerEndpointGroupList: true,
        portainer.OperationPortainerEndpointList:      true,
        portainer.OperationPortainerEndpointInspect:   true,
        portainer.OperationPortainerMOTD:              true,
        portainer.OperationPortainerRegistryList:      true,
        portainer.OperationPortainerRegistryInspect:   true,
        portainer.OperationPortainerTeamList:          true,
        portainer.OperationPortainerTemplateList:      true,
        portainer.OperationPortainerTemplateInspect:   true,
        portainer.OperationPortainerUserList:          true,
        portainer.OperationPortainerUserInspect:       true,
        portainer.OperationPortainerUserMemberships:   true,
        portainer.OperationPortainerUserListToken:     true,
        portainer.OperationPortainerUserCreateToken:   true,
        portainer.OperationPortainerUserRevokeToken:   true,
    }
}

// UpdateUsersAuthorizations will trigger an update of the authorizations for all the users.
func (service *Service) UpdateUsersAuthorizations() error {
    return service.UpdateUsersAuthorizationsTx(service.dataStore)
}

func (service *Service) UpdateUsersAuthorizationsTx(tx dataservices.DataStoreTx) error {
    users, err := tx.User().ReadAll()
    if err != nil {
        return err
    }

    for _, user := range users {
        err := service.updateUserAuthorizations(tx, user.ID)
        if err != nil {
            return err
        }
    }

    return nil
}

func (service *Service) updateUserAuthorizations(tx dataservices.DataStoreTx, userID portainer.UserID) error {
    user, err := tx.User().Read(userID)
    if err != nil {
        return err
    }

    endpointAuthorizations, err := service.getAuthorizations(tx, user)
    if err != nil {
        return err
    }

    user.EndpointAuthorizations = endpointAuthorizations

    return tx.User().Update(userID, user)
}

func (service *Service) getAuthorizations(tx dataservices.DataStoreTx, user *portainer.User) (portainer.EndpointAuthorizations, error) {
    endpointAuthorizations := portainer.EndpointAuthorizations{}
    if user.Role == portainer.AdministratorRole {
        return endpointAuthorizations, nil
    }

    userMemberships, err := tx.TeamMembership().TeamMembershipsByUserID(user.ID)
    if err != nil {
        return endpointAuthorizations, err
    }

    endpoints, err := tx.Endpoint().Endpoints()
    if err != nil {
        return endpointAuthorizations, err
    }

    endpointGroups, err := tx.EndpointGroup().ReadAll()
    if err != nil {
        return endpointAuthorizations, err
    }

    roles, err := tx.Role().ReadAll()
    if err != nil {
        return endpointAuthorizations, err
    }

    endpointAuthorizations = getUserEndpointAuthorizations(user, endpoints, endpointGroups, roles, userMemberships)

    return endpointAuthorizations, nil
}

func getUserEndpointAuthorizations(user *portainer.User, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup, roles []portainer.Role, userMemberships []portainer.TeamMembership) portainer.EndpointAuthorizations {
    endpointAuthorizations := make(portainer.EndpointAuthorizations)

    groupUserAccessPolicies := map[portainer.EndpointGroupID]portainer.UserAccessPolicies{}
    groupTeamAccessPolicies := map[portainer.EndpointGroupID]portainer.TeamAccessPolicies{}
    for _, endpointGroup := range endpointGroups {
        groupUserAccessPolicies[endpointGroup.ID] = endpointGroup.UserAccessPolicies
        groupTeamAccessPolicies[endpointGroup.ID] = endpointGroup.TeamAccessPolicies
    }

    for _, endpoint := range endpoints {
        authorizations := getAuthorizationsFromUserEndpointPolicy(user, &endpoint, roles)
        if len(authorizations) > 0 {
            endpointAuthorizations[endpoint.ID] = authorizations

            continue
        }

        authorizations = getAuthorizationsFromUserEndpointGroupPolicy(user, &endpoint, roles, groupUserAccessPolicies)
        if len(authorizations) > 0 {
            endpointAuthorizations[endpoint.ID] = authorizations

            continue
        }

        authorizations = getAuthorizationsFromTeamEndpointPolicies(userMemberships, &endpoint, roles)
        if len(authorizations) > 0 {
            endpointAuthorizations[endpoint.ID] = authorizations

            continue
        }

        authorizations = getAuthorizationsFromTeamEndpointGroupPolicies(userMemberships, &endpoint, roles, groupTeamAccessPolicies)
        if len(authorizations) > 0 {
            endpointAuthorizations[endpoint.ID] = authorizations
        }
    }

    return endpointAuthorizations
}

func getAuthorizationsFromUserEndpointPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
    policyRoles := make([]portainer.RoleID, 0)

    policy, ok := endpoint.UserAccessPolicies[user.ID]
    if ok {
        policyRoles = append(policyRoles, policy.RoleID)
    }

    return getAuthorizationsFromRoles(policyRoles, roles)
}

func getAuthorizationsFromUserEndpointGroupPolicy(user *portainer.User, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.UserAccessPolicies) portainer.Authorizations {
    policyRoles := make([]portainer.RoleID, 0)

    policy, ok := groupAccessPolicies[endpoint.GroupID][user.ID]
    if ok {
        policyRoles = append(policyRoles, policy.RoleID)
    }

    return getAuthorizationsFromRoles(policyRoles, roles)
}

func getAuthorizationsFromTeamEndpointPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role) portainer.Authorizations {
    policyRoles := make([]portainer.RoleID, 0)

    for _, membership := range memberships {
        policy, ok := endpoint.TeamAccessPolicies[membership.TeamID]
        if ok {
            policyRoles = append(policyRoles, policy.RoleID)
        }
    }

    return getAuthorizationsFromRoles(policyRoles, roles)
}

func getAuthorizationsFromTeamEndpointGroupPolicies(memberships []portainer.TeamMembership, endpoint *portainer.Endpoint, roles []portainer.Role, groupAccessPolicies map[portainer.EndpointGroupID]portainer.TeamAccessPolicies) portainer.Authorizations {
    policyRoles := make([]portainer.RoleID, 0)

    for _, membership := range memberships {
        policy, ok := groupAccessPolicies[endpoint.GroupID][membership.TeamID]
        if ok {
            policyRoles = append(policyRoles, policy.RoleID)
        }
    }

    return getAuthorizationsFromRoles(policyRoles, roles)
}

func getAuthorizationsFromRoles(roleIdentifiers []portainer.RoleID, roles []portainer.Role) portainer.Authorizations {
    var associatedRoles []portainer.Role

    for _, id := range roleIdentifiers {
        for _, role := range roles {
            if role.ID == id {
                associatedRoles = append(associatedRoles, role)

                break
            }
        }
    }

    var authorizations portainer.Authorizations
    highestPriority := 0
    for _, role := range associatedRoles {
        if role.Priority > highestPriority {
            highestPriority = role.Priority
            authorizations = role.Authorizations
        }
    }

    return authorizations
}

func (service *Service) UserIsAdminOrAuthorized(tx dataservices.DataStoreTx, userID portainer.UserID, endpointID portainer.EndpointID, authorizations []portainer.Authorization) (bool, error) {
    user, err := tx.User().Read(userID)
    if err != nil {
        return false, err
    }

    if user.Role == portainer.AdministratorRole {
        return true, nil
    }

    for _, authorization := range authorizations {
        _, authorized := user.EndpointAuthorizations[endpointID][authorization]
        if authorized {
            return true, nil
        }
    }

    return false, nil
}