mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* UserService: update callers to use the UserService instead of calling sqlstore directly There is one major change hiding in this PR. UserService.Delete originally called a number of services to delete user-related records. I moved everything except the actual call to the user table, and moved those into the API. This was done to avoid dependencies cycles; many of our services depend on the user service, so the user service itself should have as few dependencies as possible.
320 lines
11 KiB
Go
320 lines
11 KiB
Go
package ossaccesscontrol
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/grafana/grafana/pkg/api/routing"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/services/team"
|
|
"github.com/grafana/grafana/pkg/services/team/teamimpl"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
type TeamPermissionsService struct {
|
|
*resourcepermissions.Service
|
|
}
|
|
|
|
var (
|
|
TeamMemberActions = []string{
|
|
accesscontrol.ActionTeamsRead,
|
|
}
|
|
|
|
TeamAdminActions = []string{
|
|
accesscontrol.ActionTeamsRead,
|
|
accesscontrol.ActionTeamsDelete,
|
|
accesscontrol.ActionTeamsWrite,
|
|
accesscontrol.ActionTeamsPermissionsRead,
|
|
accesscontrol.ActionTeamsPermissionsWrite,
|
|
}
|
|
)
|
|
|
|
func ProvideTeamPermissions(
|
|
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
|
|
ac accesscontrol.AccessControl, license models.Licensing, service accesscontrol.Service,
|
|
teamService team.Service, userService user.Service,
|
|
) (*TeamPermissionsService, error) {
|
|
options := resourcepermissions.Options{
|
|
Resource: "teams",
|
|
ResourceAttribute: "id",
|
|
OnlyManaged: true,
|
|
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error {
|
|
id, err := strconv.ParseInt(resourceID, 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = teamService.GetTeamById(context.Background(), &models.GetTeamByIdQuery{
|
|
OrgId: orgID,
|
|
Id: id,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
Assignments: resourcepermissions.Assignments{
|
|
Users: true,
|
|
Teams: false,
|
|
BuiltInRoles: false,
|
|
},
|
|
PermissionsToActions: map[string][]string{
|
|
"Member": TeamMemberActions,
|
|
"Admin": TeamAdminActions,
|
|
},
|
|
ReaderRoleName: "Team permission reader",
|
|
WriterRoleName: "Team permission writer",
|
|
RoleGroup: "Teams",
|
|
OnSetUser: func(session *sqlstore.DBSession, orgID int64, user accesscontrol.User, resourceID, permission string) error {
|
|
teamId, err := strconv.ParseInt(resourceID, 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch permission {
|
|
case "Member":
|
|
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, 0)
|
|
case "Admin":
|
|
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, models.PERMISSION_ADMIN)
|
|
case "":
|
|
return teamimpl.RemoveTeamMemberHook(session, &models.RemoveTeamMemberCommand{
|
|
OrgId: orgID,
|
|
UserId: user.ID,
|
|
TeamId: teamId,
|
|
})
|
|
default:
|
|
return fmt.Errorf("invalid team permission type %s", permission)
|
|
}
|
|
},
|
|
}
|
|
|
|
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &TeamPermissionsService{srv}, nil
|
|
}
|
|
|
|
type DashboardPermissionsService struct {
|
|
*resourcepermissions.Service
|
|
}
|
|
|
|
var DashboardViewActions = []string{dashboards.ActionDashboardsRead}
|
|
var DashboardEditActions = append(DashboardViewActions, []string{dashboards.ActionDashboardsWrite, dashboards.ActionDashboardsDelete}...)
|
|
var DashboardAdminActions = append(DashboardEditActions, []string{dashboards.ActionDashboardsPermissionsRead, dashboards.ActionDashboardsPermissionsWrite}...)
|
|
|
|
func ProvideDashboardPermissions(
|
|
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, ac accesscontrol.AccessControl,
|
|
license models.Licensing, dashboardStore dashboards.Store, service accesscontrol.Service,
|
|
teamService team.Service, userService user.Service,
|
|
) (*DashboardPermissionsService, error) {
|
|
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*models.Dashboard, error) {
|
|
query := &models.GetDashboardQuery{Uid: resourceID, OrgId: orgID}
|
|
if _, err := dashboardStore.GetDashboard(ctx, query); err != nil {
|
|
return nil, err
|
|
}
|
|
return query.Result, nil
|
|
}
|
|
|
|
options := resourcepermissions.Options{
|
|
Resource: "dashboards",
|
|
ResourceAttribute: "uid",
|
|
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error {
|
|
dashboard, err := getDashboard(ctx, orgID, resourceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if dashboard.IsFolder {
|
|
return errors.New("not found")
|
|
}
|
|
|
|
return nil
|
|
},
|
|
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) {
|
|
dashboard, err := getDashboard(ctx, orgID, resourceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if dashboard.FolderId > 0 {
|
|
query := &models.GetDashboardQuery{Id: dashboard.FolderId, OrgId: orgID}
|
|
if _, err := dashboardStore.GetDashboard(ctx, query); err != nil {
|
|
return nil, err
|
|
}
|
|
return []string{dashboards.ScopeFoldersProvider.GetResourceScopeUID(query.Result.Uid)}, nil
|
|
}
|
|
return []string{}, nil
|
|
},
|
|
Assignments: resourcepermissions.Assignments{
|
|
Users: true,
|
|
Teams: true,
|
|
BuiltInRoles: true,
|
|
},
|
|
PermissionsToActions: map[string][]string{
|
|
"View": DashboardViewActions,
|
|
"Edit": DashboardEditActions,
|
|
"Admin": DashboardAdminActions,
|
|
},
|
|
ReaderRoleName: "Dashboard permission reader",
|
|
WriterRoleName: "Dashboard permission writer",
|
|
RoleGroup: "Dashboards",
|
|
}
|
|
|
|
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &DashboardPermissionsService{srv}, nil
|
|
}
|
|
|
|
type FolderPermissionsService struct {
|
|
*resourcepermissions.Service
|
|
}
|
|
|
|
var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead}
|
|
var FolderEditActions = append(FolderViewActions, []string{
|
|
dashboards.ActionFoldersWrite,
|
|
dashboards.ActionFoldersDelete,
|
|
dashboards.ActionDashboardsCreate,
|
|
accesscontrol.ActionAlertingRuleCreate,
|
|
accesscontrol.ActionAlertingRuleUpdate,
|
|
accesscontrol.ActionAlertingRuleDelete,
|
|
}...)
|
|
var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFoldersPermissionsRead, dashboards.ActionFoldersPermissionsWrite}...)
|
|
|
|
func ProvideFolderPermissions(
|
|
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, accesscontrol accesscontrol.AccessControl,
|
|
license models.Licensing, dashboardStore dashboards.Store, service accesscontrol.Service,
|
|
teamService team.Service, userService user.Service,
|
|
) (*FolderPermissionsService, error) {
|
|
options := resourcepermissions.Options{
|
|
Resource: "folders",
|
|
ResourceAttribute: "uid",
|
|
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error {
|
|
query := &models.GetDashboardQuery{Uid: resourceID, OrgId: orgID}
|
|
if _, err := dashboardStore.GetDashboard(ctx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !query.Result.IsFolder {
|
|
return errors.New("not found")
|
|
}
|
|
|
|
return nil
|
|
},
|
|
Assignments: resourcepermissions.Assignments{
|
|
Users: true,
|
|
Teams: true,
|
|
BuiltInRoles: true,
|
|
},
|
|
PermissionsToActions: map[string][]string{
|
|
"View": append(DashboardViewActions, FolderViewActions...),
|
|
"Edit": append(DashboardEditActions, FolderEditActions...),
|
|
"Admin": append(DashboardAdminActions, FolderAdminActions...),
|
|
},
|
|
ReaderRoleName: "Folder permission reader",
|
|
WriterRoleName: "Folder permission writer",
|
|
RoleGroup: "Folders",
|
|
}
|
|
srv, err := resourcepermissions.New(options, cfg, router, license, accesscontrol, service, sql, teamService, userService)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &FolderPermissionsService{srv}, nil
|
|
}
|
|
|
|
func ProvideDatasourcePermissionsService() *DatasourcePermissionsService {
|
|
return &DatasourcePermissionsService{}
|
|
}
|
|
|
|
var _ accesscontrol.DatasourcePermissionsService = new(DatasourcePermissionsService)
|
|
|
|
type DatasourcePermissionsService struct{}
|
|
|
|
func (e DatasourcePermissionsService) GetPermissions(ctx context.Context, user *user.SignedInUser, resourceID string) ([]accesscontrol.ResourcePermission, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (e DatasourcePermissionsService) SetUserPermission(ctx context.Context, orgID int64, user accesscontrol.User, resourceID, permission string) (*accesscontrol.ResourcePermission, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (e DatasourcePermissionsService) SetTeamPermission(ctx context.Context, orgID, teamID int64, resourceID, permission string) (*accesscontrol.ResourcePermission, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (e DatasourcePermissionsService) SetBuiltInRolePermission(ctx context.Context, orgID int64, builtInRole string, resourceID string, permission string) (*accesscontrol.ResourcePermission, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...accesscontrol.SetResourcePermissionCommand) ([]accesscontrol.ResourcePermission, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (e DatasourcePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string {
|
|
return ""
|
|
}
|
|
|
|
var (
|
|
ServiceAccountEditActions = []string{
|
|
serviceaccounts.ActionRead,
|
|
serviceaccounts.ActionWrite,
|
|
}
|
|
ServiceAccountAdminActions = []string{
|
|
serviceaccounts.ActionRead,
|
|
serviceaccounts.ActionWrite,
|
|
serviceaccounts.ActionDelete,
|
|
serviceaccounts.ActionPermissionsRead,
|
|
serviceaccounts.ActionPermissionsWrite,
|
|
}
|
|
)
|
|
|
|
type ServiceAccountPermissionsService struct {
|
|
*resourcepermissions.Service
|
|
}
|
|
|
|
func ProvideServiceAccountPermissions(
|
|
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, ac accesscontrol.AccessControl,
|
|
license models.Licensing, serviceAccountStore serviceaccounts.Store, service accesscontrol.Service,
|
|
teamService team.Service, userService user.Service,
|
|
) (*ServiceAccountPermissionsService, error) {
|
|
options := resourcepermissions.Options{
|
|
Resource: "serviceaccounts",
|
|
ResourceAttribute: "id",
|
|
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error {
|
|
id, err := strconv.ParseInt(resourceID, 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = serviceAccountStore.RetrieveServiceAccount(ctx, orgID, id)
|
|
return err
|
|
},
|
|
Assignments: resourcepermissions.Assignments{
|
|
Users: true,
|
|
Teams: true,
|
|
BuiltInRoles: false,
|
|
},
|
|
PermissionsToActions: map[string][]string{
|
|
"Edit": ServiceAccountEditActions,
|
|
"Admin": ServiceAccountAdminActions,
|
|
},
|
|
ReaderRoleName: "Service account permission reader",
|
|
WriterRoleName: "Service account permission writer",
|
|
RoleGroup: "Service accounts",
|
|
}
|
|
|
|
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ServiceAccountPermissionsService{srv}, nil
|
|
}
|