influxdb/inmem/auth_service.go

251 lines
5.7 KiB
Go

package inmem
import (
"context"
platform "github.com/influxdata/influxdb"
)
func (s *Service) loadAuthorization(ctx context.Context, id platform.ID) (*platform.Authorization, *platform.Error) {
i, ok := s.authorizationKV.Load(id.String())
if !ok {
return nil, &platform.Error{
Code: platform.ENotFound,
Msg: "authorization not found",
}
}
a, ok := i.(platform.Authorization)
if !ok {
return nil, &platform.Error{
Code: platform.EInternal,
Msg: "value found in map is not an authorization",
}
}
if a.Status == "" {
a.Status = platform.Active
}
return &a, nil
}
// PutAuthorization overwrites the authorization with the contents of a.
func (s *Service) PutAuthorization(ctx context.Context, a *platform.Authorization) error {
if a.Status == "" {
a.Status = platform.Active
}
s.authorizationKV.Store(a.ID.String(), *a)
return nil
}
// FindAuthorizationByID returns an authorization given an ID.
func (s *Service) FindAuthorizationByID(ctx context.Context, id platform.ID) (*platform.Authorization, error) {
var err error
a, pe := s.loadAuthorization(ctx, id)
if pe != nil {
pe.Op = OpPrefix + platform.OpFindAuthorizationByID
err = pe
}
return a, err
}
// FindAuthorizationByToken returns an authorization given a token.
func (s *Service) FindAuthorizationByToken(ctx context.Context, t string) (*platform.Authorization, error) {
var err error
op := OpPrefix + platform.OpFindAuthorizationByToken
var n int
var as []*platform.Authorization
as, n, err = s.FindAuthorizations(ctx, platform.AuthorizationFilter{Token: &t})
if err != nil {
return nil, &platform.Error{
Err: err,
Op: op,
}
}
if n < 1 {
return nil, &platform.Error{
Code: platform.ENotFound,
Msg: "authorization not found",
Op: op,
}
}
return as[0], nil
}
func filterAuthorizationsFn(filter platform.AuthorizationFilter) func(a *platform.Authorization) bool {
if filter.ID != nil {
return func(a *platform.Authorization) bool {
return a.ID == *filter.ID
}
}
if filter.Token != nil {
return func(a *platform.Authorization) bool {
return a.Token == *filter.Token
}
}
// Filter by org and user
if filter.OrgID != nil && filter.UserID != nil {
return func(a *platform.Authorization) bool {
return a.OrgID == *filter.OrgID && a.UserID == *filter.UserID
}
}
if filter.OrgID != nil {
return func(a *platform.Authorization) bool {
return a.OrgID == *filter.OrgID
}
}
if filter.UserID != nil {
return func(a *platform.Authorization) bool {
return a.UserID == *filter.UserID
}
}
return func(a *platform.Authorization) bool { return true }
}
// FindAuthorizations returns all authorizations matching the filter.
func (s *Service) FindAuthorizations(ctx context.Context, filter platform.AuthorizationFilter, opt ...platform.FindOptions) ([]*platform.Authorization, int, error) {
op := OpPrefix + platform.OpFindAuthorizations
if filter.ID != nil {
a, err := s.FindAuthorizationByID(ctx, *filter.ID)
if err != nil {
return nil, 0, &platform.Error{
Err: err,
Op: op,
}
}
return []*platform.Authorization{a}, 1, nil
}
var as []*platform.Authorization
if filter.User != nil {
u, err := s.findUserByName(ctx, *filter.User)
if err != nil {
return nil, 0, &platform.Error{
Op: op,
Err: err,
}
}
filter.UserID = &u.ID
}
if filter.Org != nil {
o, err := s.findOrganizationByName(ctx, *filter.Org)
if err != nil {
return nil, 0, &platform.Error{
Op: op,
Err: err,
}
}
filter.OrgID = &o.ID
}
var err error
filterF := filterAuthorizationsFn(filter)
s.authorizationKV.Range(func(k, v interface{}) bool {
a, ok := v.(platform.Authorization)
if !ok {
err = &platform.Error{
Code: platform.EInternal,
Msg: "value found in map is not an authorization",
Op: op,
}
return false
}
if filterF(&a) {
as = append(as, &a)
}
return true
})
if err != nil {
return nil, 0, err
}
return as, len(as), nil
}
// CreateAuthorization sets a.Token and a.ID and creates an platform.Authorization
func (s *Service) CreateAuthorization(ctx context.Context, a *platform.Authorization) error {
op := OpPrefix + platform.OpCreateAuthorization
_, pErr := s.FindUserByID(ctx, a.UserID)
if pErr != nil {
return platform.ErrUnableToCreateToken
}
_, pErr = s.FindOrganizationByID(ctx, a.OrgID)
if pErr != nil {
return platform.ErrUnableToCreateToken
}
if a.Token == "" {
var err error
a.Token, err = s.TokenGenerator.Token()
if err != nil {
return &platform.Error{
Err: err,
Op: op,
}
}
}
a.ID = s.IDGenerator.ID()
a.Status = platform.Active
return s.PutAuthorization(ctx, a)
}
// DeleteAuthorization deletes an authorization associated with id.
func (s *Service) DeleteAuthorization(ctx context.Context, id platform.ID) error {
if _, err := s.FindAuthorizationByID(ctx, id); err != nil {
return &platform.Error{
Err: err,
Op: OpPrefix + platform.OpDeleteAuthorization,
}
}
s.authorizationKV.Delete(id.String())
return nil
}
// UpdateAuthorization updates the status and description if available.
func (s *Service) UpdateAuthorization(ctx context.Context, id platform.ID, upd *platform.AuthorizationUpdate) (*platform.Authorization, error) {
op := OpPrefix + platform.OpUpdateAuthorization
a, err := s.FindAuthorizationByID(ctx, id)
if err != nil {
return nil, &platform.Error{
Err: err,
Op: op,
}
}
if upd.Status != nil {
status := *upd.Status
switch status {
case platform.Active, platform.Inactive:
default:
return nil, &platform.Error{
Code: platform.EInvalid,
Msg: "unknown authorization status",
Op: op,
}
}
a.Status = status
}
if upd.Description != nil {
a.Description = *upd.Description
}
return a, s.PutAuthorization(ctx, a)
}