219 lines
4.8 KiB
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)
|
|
})
|
|
}
|