150 lines
4.0 KiB
Go
150 lines
4.0 KiB
Go
|
package authorizer
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"github.com/influxdata/influxdb"
|
||
|
)
|
||
|
|
||
|
var _ influxdb.MacroService = (*MacroService)(nil)
|
||
|
|
||
|
// MacroService wraps a influxdb.MacroService and authorizes actions
|
||
|
// against it appropriately.
|
||
|
type MacroService struct {
|
||
|
s influxdb.MacroService
|
||
|
}
|
||
|
|
||
|
// NewMacroService constructs an instance of an authorizing macro service.
|
||
|
func NewMacroService(s influxdb.MacroService) *MacroService {
|
||
|
return &MacroService{
|
||
|
s: s,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func newMacroPermission(a influxdb.Action, orgID, id influxdb.ID) (*influxdb.Permission, error) {
|
||
|
return influxdb.NewPermissionAtID(id, a, influxdb.MacrosResourceType, orgID)
|
||
|
}
|
||
|
|
||
|
func authorizeReadMacro(ctx context.Context, orgID, id influxdb.ID) error {
|
||
|
p, err := newMacroPermission(influxdb.ReadAction, orgID, id)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := IsAllowed(ctx, *p); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func authorizeWriteMacro(ctx context.Context, orgID, id influxdb.ID) error {
|
||
|
p, err := newMacroPermission(influxdb.WriteAction, orgID, id)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := IsAllowed(ctx, *p); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// FindMacroByID checks to see if the authorizer on context has read access to the id provided.
|
||
|
func (s *MacroService) FindMacroByID(ctx context.Context, id influxdb.ID) (*influxdb.Macro, error) {
|
||
|
m, err := s.s.FindMacroByID(ctx, id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err := authorizeReadMacro(ctx, m.OrganizationID, id); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return m, nil
|
||
|
}
|
||
|
|
||
|
// FindMacros retrieves all macros that match the provided filter and then filters the list down to only the resources that are authorized.
|
||
|
func (s *MacroService) FindMacros(ctx context.Context, filter influxdb.MacroFilter, opt ...influxdb.FindOptions) ([]*influxdb.Macro, error) {
|
||
|
// TODO: we'll likely want to push this operation into the database since fetching the whole list of data will likely be expensive.
|
||
|
ms, err := s.s.FindMacros(ctx, filter, opt...)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// This filters without allocating
|
||
|
// https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating
|
||
|
macros := ms[:0]
|
||
|
for _, m := range ms {
|
||
|
err := authorizeReadMacro(ctx, m.OrganizationID, m.ID)
|
||
|
if err != nil && influxdb.ErrorCode(err) != influxdb.EUnauthorized {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if influxdb.ErrorCode(err) == influxdb.EUnauthorized {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
macros = append(macros, m)
|
||
|
}
|
||
|
|
||
|
return macros, nil
|
||
|
}
|
||
|
|
||
|
// CreateMacro checks to see if the authorizer on context has write access to the global macro resource.
|
||
|
func (s *MacroService) CreateMacro(ctx context.Context, m *influxdb.Macro) error {
|
||
|
p, err := influxdb.NewPermission(influxdb.WriteAction, influxdb.MacrosResourceType, m.OrganizationID)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := IsAllowed(ctx, *p); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return s.s.CreateMacro(ctx, m)
|
||
|
}
|
||
|
|
||
|
// UpdateMacro checks to see if the authorizer on context has write access to the macro provided.
|
||
|
func (s *MacroService) UpdateMacro(ctx context.Context, id influxdb.ID, upd *influxdb.MacroUpdate) (*influxdb.Macro, error) {
|
||
|
m, err := s.FindMacroByID(ctx, id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err := authorizeWriteMacro(ctx, m.OrganizationID, id); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return s.s.UpdateMacro(ctx, id, upd)
|
||
|
}
|
||
|
|
||
|
// ReplaceMacro checks to see if the authorizer on context has write access to the macro provided.
|
||
|
func (s *MacroService) ReplaceMacro(ctx context.Context, m *influxdb.Macro) error {
|
||
|
m, err := s.FindMacroByID(ctx, m.ID)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := authorizeWriteMacro(ctx, m.OrganizationID, m.ID); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return s.s.ReplaceMacro(ctx, m)
|
||
|
}
|
||
|
|
||
|
// DeleteMacro checks to see if the authorizer on context has write access to the macro provided.
|
||
|
func (s *MacroService) DeleteMacro(ctx context.Context, id influxdb.ID) error {
|
||
|
m, err := s.FindMacroByID(ctx, id)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := authorizeWriteMacro(ctx, m.OrganizationID, id); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return s.s.DeleteMacro(ctx, id)
|
||
|
}
|