206 lines
4.3 KiB
Go
206 lines
4.3 KiB
Go
package inmem
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/influxdata/influxdb"
|
|
platform "github.com/influxdata/influxdb"
|
|
)
|
|
|
|
var _ platform.UserService = (*Service)(nil)
|
|
|
|
func (s *Service) loadUser(id platform.ID) (*platform.User, *platform.Error) {
|
|
i, ok := s.userKV.Load(id.String())
|
|
if !ok {
|
|
return nil, &platform.Error{
|
|
Code: platform.ENotFound,
|
|
Msg: "user not found",
|
|
}
|
|
}
|
|
|
|
b, ok := i.(*platform.User)
|
|
if !ok {
|
|
return nil, &platform.Error{
|
|
Code: platform.EInternal,
|
|
Msg: fmt.Sprintf("type %T is not a user", i),
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func (s *Service) forEachUser(ctx context.Context, fn func(b *platform.User) bool) error {
|
|
var err error
|
|
s.userKV.Range(func(k, v interface{}) bool {
|
|
o, ok := v.(*platform.User)
|
|
if !ok {
|
|
err = fmt.Errorf("type %T is not a user", v)
|
|
return false
|
|
}
|
|
|
|
return fn(o)
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
// FindUserByID returns a single user by ID.
|
|
func (s *Service) FindUserByID(ctx context.Context, id platform.ID) (u *platform.User, err error) {
|
|
var pe *platform.Error
|
|
u, pe = s.loadUser(id)
|
|
if pe != nil {
|
|
err = &platform.Error{
|
|
Op: OpPrefix + platform.OpFindUserByID,
|
|
Err: pe,
|
|
}
|
|
}
|
|
return u, err
|
|
}
|
|
|
|
func (s *Service) findUserByName(ctx context.Context, n string) (*platform.User, error) {
|
|
return s.FindUser(ctx, platform.UserFilter{Name: &n})
|
|
}
|
|
|
|
// FindUser returns the first user that matches a filter.
|
|
func (s *Service) FindUser(ctx context.Context, filter platform.UserFilter) (*platform.User, error) {
|
|
op := OpPrefix + platform.OpFindUser
|
|
if filter.ID != nil {
|
|
u, err := s.FindUserByID(ctx, *filter.ID)
|
|
if err != nil {
|
|
return nil, &platform.Error{
|
|
Op: op,
|
|
Err: err,
|
|
}
|
|
}
|
|
return u, nil
|
|
}
|
|
|
|
if filter.Name != nil {
|
|
var u *platform.User
|
|
|
|
err := s.forEachUser(ctx, func(user *platform.User) bool {
|
|
if user.Name == *filter.Name {
|
|
u = user
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if u == nil {
|
|
return nil, &platform.Error{
|
|
Code: platform.ENotFound,
|
|
Op: op,
|
|
Msg: "user not found",
|
|
}
|
|
}
|
|
|
|
return u, nil
|
|
}
|
|
|
|
return nil, &platform.Error{
|
|
Code: platform.EInvalid,
|
|
Op: op,
|
|
Msg: "expected filter to contain name",
|
|
}
|
|
}
|
|
|
|
// FindUsers will retrieve a list of users from storage.
|
|
func (s *Service) FindUsers(ctx context.Context, filter platform.UserFilter, opt ...platform.FindOptions) ([]*platform.User, int, error) {
|
|
op := OpPrefix + platform.OpFindUsers
|
|
if filter.ID != nil {
|
|
u, err := s.FindUserByID(ctx, *filter.ID)
|
|
if err != nil {
|
|
return nil, 0, &platform.Error{
|
|
Err: err,
|
|
Op: op,
|
|
}
|
|
}
|
|
|
|
return []*platform.User{u}, 1, nil
|
|
}
|
|
if filter.Name != nil {
|
|
u, err := s.FindUser(ctx, filter)
|
|
if err != nil {
|
|
return nil, 0, &platform.Error{
|
|
Err: err,
|
|
Op: op,
|
|
}
|
|
}
|
|
|
|
return []*platform.User{u}, 1, nil
|
|
}
|
|
|
|
users := []*platform.User{}
|
|
|
|
err := s.forEachUser(ctx, func(user *platform.User) bool {
|
|
users = append(users, user)
|
|
return true
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return users, len(users), nil
|
|
}
|
|
|
|
// CreateUser will create an user into storage.
|
|
func (s *Service) CreateUser(ctx context.Context, u *platform.User) error {
|
|
if _, err := s.FindUser(ctx, platform.UserFilter{Name: &u.Name}); err == nil {
|
|
return &platform.Error{
|
|
Code: platform.EConflict,
|
|
Op: OpPrefix + platform.OpCreateUser,
|
|
Msg: fmt.Sprintf("user with name %s already exists", u.Name),
|
|
}
|
|
}
|
|
u.ID = s.IDGenerator.ID()
|
|
u.Status = influxdb.Active
|
|
s.PutUser(ctx, u)
|
|
return nil
|
|
}
|
|
|
|
// PutUser put a user into storage.
|
|
func (s *Service) PutUser(ctx context.Context, o *platform.User) error {
|
|
s.userKV.Store(o.ID.String(), o)
|
|
return nil
|
|
}
|
|
|
|
// UpdateUser update a user in storage.
|
|
func (s *Service) UpdateUser(ctx context.Context, id platform.ID, upd platform.UserUpdate) (*platform.User, error) {
|
|
o, err := s.FindUserByID(ctx, id)
|
|
if err != nil {
|
|
return nil, &platform.Error{
|
|
Err: err,
|
|
Op: OpPrefix + platform.OpUpdateUser,
|
|
}
|
|
}
|
|
|
|
if upd.Name != nil {
|
|
o.Name = *upd.Name
|
|
}
|
|
|
|
if upd.Status != nil {
|
|
o.Status = *upd.Status
|
|
}
|
|
|
|
s.userKV.Store(o.ID.String(), o)
|
|
|
|
return o, nil
|
|
}
|
|
|
|
// DeleteUser remove a user from storage.
|
|
func (s *Service) DeleteUser(ctx context.Context, id platform.ID) error {
|
|
if _, err := s.FindUserByID(ctx, id); err != nil {
|
|
return &platform.Error{
|
|
Err: err,
|
|
Op: OpPrefix + platform.OpDeleteUser,
|
|
}
|
|
}
|
|
s.userKV.Delete(id.String())
|
|
return nil
|
|
}
|