influxdb/authorization/service.go

219 lines
4.8 KiB
Go

package authorization
import (
"context"
"time"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
"github.com/influxdata/influxdb/v2/kv"
"github.com/influxdata/influxdb/v2/rand"
)
var _ influxdb.AuthorizationService = (*Service)(nil)
type Service struct {
store *Store
tokenGenerator influxdb.TokenGenerator
tenantService TenantService
}
func NewService(st *Store, ts TenantService) influxdb.AuthorizationService {
return &Service{
store: st,
tokenGenerator: rand.NewTokenGenerator(64),
tenantService: ts,
}
}
func (s *Service) CreateAuthorization(ctx context.Context, a *influxdb.Authorization) error {
if err := a.Valid(); err != nil {
return &errors.Error{
Err: err,
}
}
if _, err := s.tenantService.FindUserByID(ctx, a.UserID); err != nil {
return influxdb.ErrUnableToCreateToken
}
if _, err := s.tenantService.FindOrganizationByID(ctx, a.OrgID); err != nil {
return influxdb.ErrUnableToCreateToken
}
err := s.store.View(ctx, func(tx kv.Tx) error {
if err := s.store.uniqueAuthToken(ctx, tx, a); err != nil {
return err
}
return nil
})
if err != nil {
return ErrTokenAlreadyExistsError
}
if a.Token == "" {
token, err := s.tokenGenerator.Token()
if err != nil {
return &errors.Error{
Err: err,
}
}
a.Token = token
}
now := time.Now()
a.SetCreatedAt(now)
a.SetUpdatedAt(now)
return s.store.Update(ctx, func(tx kv.Tx) error {
return s.store.CreateAuthorization(ctx, tx, a)
})
}
func (s *Service) FindAuthorizationByID(ctx context.Context, id platform.ID) (*influxdb.Authorization, error) {
var a *influxdb.Authorization
err := s.store.View(ctx, func(tx kv.Tx) error {
auth, err := s.store.GetAuthorizationByID(ctx, tx, id)
if err != nil {
return err
}
a = auth
return nil
})
if err != nil {
return nil, err
}
return a, nil
}
// FindAuthorizationByToken returns a authorization by token for a particular authorization.
func (s *Service) FindAuthorizationByToken(ctx context.Context, n string) (*influxdb.Authorization, error) {
var a *influxdb.Authorization
err := s.store.View(ctx, func(tx kv.Tx) error {
auth, err := s.store.GetAuthorizationByToken(ctx, tx, n)
if err != nil {
return err
}
a = auth
return nil
})
if err != nil {
return nil, err
}
return a, nil
}
// FindAuthorizations retrieves all authorizations that match an arbitrary authorization filter.
// Filters using ID, or Token should be efficient.
// Other filters will do a linear scan across all authorizations searching for a match.
func (s *Service) FindAuthorizations(ctx context.Context, filter influxdb.AuthorizationFilter, opt ...influxdb.FindOptions) ([]*influxdb.Authorization, int, error) {
if filter.ID != nil {
var auth *influxdb.Authorization
err := s.store.View(ctx, func(tx kv.Tx) error {
a, e := s.store.GetAuthorizationByID(ctx, tx, *filter.ID)
if e != nil {
return e
}
auth = a
return nil
})
if err != nil {
return nil, 0, &errors.Error{
Err: err,
}
}
return []*influxdb.Authorization{auth}, 1, nil
}
if filter.Token != nil {
var auth *influxdb.Authorization
err := s.store.View(ctx, func(tx kv.Tx) error {
a, e := s.store.GetAuthorizationByToken(ctx, tx, *filter.Token)
if e != nil {
return e
}
auth = a
return nil
})
if err != nil {
return nil, 0, &errors.Error{
Err: err,
}
}
return []*influxdb.Authorization{auth}, 1, nil
}
as := []*influxdb.Authorization{}
err := s.store.View(ctx, func(tx kv.Tx) error {
auths, err := s.store.ListAuthorizations(ctx, tx, filter)
if err != nil {
return err
}
as = auths
return nil
})
if err != nil {
return nil, 0, &errors.Error{
Err: err,
}
}
return as, len(as), nil
}
// UpdateAuthorization updates the status and description if available.
func (s *Service) UpdateAuthorization(ctx context.Context, id platform.ID, upd *influxdb.AuthorizationUpdate) (*influxdb.Authorization, error) {
var auth *influxdb.Authorization
err := s.store.View(ctx, func(tx kv.Tx) error {
a, e := s.store.GetAuthorizationByID(ctx, tx, id)
if e != nil {
return e
}
auth = a
return nil
})
if err != nil {
return nil, &errors.Error{
Code: errors.ENotFound,
Err: err,
}
}
if upd.Status != nil {
auth.Status = *upd.Status
}
if upd.Description != nil {
auth.Description = *upd.Description
}
auth.SetUpdatedAt(time.Now())
err = s.store.Update(ctx, func(tx kv.Tx) error {
a, e := s.store.UpdateAuthorization(ctx, tx, id, auth)
if e != nil {
return e
}
auth = a
return nil
})
return auth, err
}
func (s *Service) DeleteAuthorization(ctx context.Context, id platform.ID) error {
return s.store.Update(ctx, func(tx kv.Tx) (err error) {
return s.store.DeleteAuthorization(ctx, tx, id)
})
}