Some checks failed
Build Docker Image / Build-Docker-Image (push) Has been cancelled
159 lines
3.0 KiB
Go
159 lines
3.0 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
|
|
"spend-sparrow/db"
|
|
"spend-sparrow/log"
|
|
"spend-sparrow/types"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
var (
|
|
safeInputRegex = regexp.MustCompile(`^[a-zA-Z0-9-]+$`)
|
|
)
|
|
|
|
type Account interface {
|
|
Add(user *types.User, name string) (*types.Account, error)
|
|
Update(user *types.User, id uuid.UUID, name string) (*types.Account, error)
|
|
Get(user *types.User) ([]*types.Account, error)
|
|
Delete(user *types.User, id uuid.UUID) error
|
|
}
|
|
|
|
type AccountImpl struct {
|
|
db db.Account
|
|
clock Clock
|
|
random Random
|
|
settings *types.Settings
|
|
}
|
|
|
|
func NewAccountImpl(db db.Account, random Random, clock Clock, settings *types.Settings) Account {
|
|
return AccountImpl{
|
|
db: db,
|
|
clock: clock,
|
|
random: NewRandomImpl(),
|
|
settings: settings,
|
|
}
|
|
}
|
|
|
|
func (service AccountImpl) Add(user *types.User, name string) (*types.Account, error) {
|
|
if user == nil {
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
newId, err := service.random.UUID()
|
|
if err != nil {
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
err = service.validateAccount(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
account := &types.Account{
|
|
Id: newId,
|
|
GroupId: user.Id,
|
|
|
|
Name: name,
|
|
|
|
CurrentBalance: 0,
|
|
LastTransaction: nil,
|
|
OinkBalance: 0,
|
|
|
|
CreatedAt: service.clock.Now(),
|
|
CreatedBy: user.Id,
|
|
UpdatedAt: nil,
|
|
UpdatedBy: nil,
|
|
}
|
|
|
|
err = service.db.Insert(account)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
savedAccount, err := service.db.Get(user.Id, newId)
|
|
if err != nil {
|
|
if errors.Is(err, db.ErrNotFound) {
|
|
log.Error("Account not found after insert: %v", err)
|
|
}
|
|
return nil, types.ErrInternal
|
|
}
|
|
return savedAccount, nil
|
|
}
|
|
|
|
func (service AccountImpl) Update(user *types.User, id uuid.UUID, name string) (*types.Account, error) {
|
|
if user == nil {
|
|
return nil, types.ErrInternal
|
|
}
|
|
err := service.validateAccount(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
account, err := service.db.Get(user.Id, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
timestamp := service.clock.Now()
|
|
account.Name = name
|
|
account.UpdatedAt = ×tamp
|
|
account.UpdatedBy = &user.Id
|
|
|
|
err = service.db.Update(account)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return account, nil
|
|
}
|
|
|
|
func (service AccountImpl) Get(user *types.User) ([]*types.Account, error) {
|
|
|
|
if user == nil {
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
accounts, err := service.db.GetAll(user.GroupId)
|
|
if err != nil {
|
|
return nil, types.ErrInternal
|
|
}
|
|
|
|
return accounts, nil
|
|
}
|
|
|
|
func (service AccountImpl) Delete(user *types.User, id uuid.UUID) error {
|
|
if user == nil {
|
|
return types.ErrInternal
|
|
}
|
|
|
|
account, err := service.db.Get(user.GroupId, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if account.GroupId != user.GroupId {
|
|
return types.ErrUnauthorized
|
|
}
|
|
|
|
err = service.db.Delete(account.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (service AccountImpl) validateAccount(name string) error {
|
|
if name == "" {
|
|
return errors.New("Please enter a value for the \"name\" field.")
|
|
} else if !safeInputRegex.MatchString(name) {
|
|
return errors.New("Please use only letters, dashes or numbers for \"name\".")
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|