Files
stufflog3/usecases/scopes/service.go
T
gisle c8ca2d4344
continuous-integration/drone/push Build is passing
add all-scopes item endpoint.
2022-07-08 17:34:43 +02:00

245 lines
5.5 KiB
Go
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package scopes
import (
"context"
"git.aiterp.net/stufflog3/stufflog3/entities"
"git.aiterp.net/stufflog3/stufflog3/internal/genutils"
"git.aiterp.net/stufflog3/stufflog3/models"
"git.aiterp.net/stufflog3/stufflog3/usecases/auth"
"strings"
)
type Service struct {
Auth *auth.Service
Repository Repository
StatsLister StatsLister
contextKey struct{ B int64 }
}
func (s *Service) CreateContext(ctx context.Context, userID string, scope Result) context.Context {
return context.WithValue(ctx, &s.contextKey, &Context{
scopesRepo: s.Repository,
statsRepo: s.StatsLister,
userID: userID,
ID: scope.ID,
Scope: scope,
service: s,
})
}
func (s *Service) CreateListContext(ctx context.Context, userID string, scopes []Result) context.Context {
contextData := &Context{
scopesRepo: s.Repository,
statsRepo: s.StatsLister,
userID: userID,
scopes: scopes,
scopesError: nil,
ID: -1,
Scope: Result{
Scope: entities.Scope{ID: -1},
Members: map[string]ResultMember{},
Stats: []ResultStat{},
},
service: s,
}
contextData.scopesOnce.Do(func() { /* a lot of nothing */ })
return context.WithValue(ctx, &s.contextKey, contextData)
}
func (s *Service) Context(ctx context.Context) *Context {
v := ctx.Value(&s.contextKey)
if v == nil {
return nil
}
return v.(*Context)
}
// Find finds a scope and its members, and returns it if the logged-in user is part of this list.
func (s *Service) Find(ctx context.Context, id int) (*Result, error) {
user := s.Auth.GetUser(ctx)
if user == nil {
return nil, models.PermissionDeniedError{}
}
scope, err := s.Repository.Find(ctx, id)
if err != nil {
return nil, err
}
members, err := s.Repository.ListMembers(ctx, scope.ID)
if err != nil {
return nil, err
}
stats, err := s.StatsLister.List(ctx, scope.ID)
if err != nil {
return nil, err
}
found := false
for _, member := range members {
if member.UserID == user.ID {
found = true
break
}
}
if !found {
return nil, models.NotFoundError("Scope")
}
return generateResult(*scope, members, stats), nil
}
// List lists a scope and their members, and returns it if the logged-in user is part of this list.
func (s *Service) List(ctx context.Context) ([]Result, error) {
user := s.Auth.GetUser(ctx)
if user == nil {
return nil, models.PermissionDeniedError{}
}
scopes, err := s.Repository.ListUser(ctx, user.ID)
if err != nil {
return nil, err
}
ids := make([]int, 0, len(scopes))
for _, scope := range scopes {
ids = append(ids, scope.ID)
}
members, err := s.Repository.ListMembers(ctx, ids...)
if err != nil {
return nil, err
}
stats, err := s.StatsLister.List(ctx, ids...)
if err != nil {
return nil, err
}
return genutils.Map(scopes, func(scope entities.Scope) Result {
return *generateResult(scope, members, stats)
}), nil
}
func (s *Service) Create(ctx context.Context, scope entities.Scope, ownerName string) (*Result, error) {
user := s.Auth.GetUser(ctx)
if user == nil {
return nil, models.PermissionDeniedError{}
}
scope.Name = strings.Trim(scope.Name, "  \t\r\n")
if scope.Name == "" {
return nil, models.BadInputError{
Object: "ScopeInput",
Field: "name",
Problem: "Empty name provided",
}
}
scope.Abbreviation = strings.ToUpper(strings.Trim(scope.Abbreviation, "  \t\r\n"))
if scope.Abbreviation == "" {
return nil, models.BadInputError{
Object: "ScopeInput",
Field: "abbreviation",
Problem: "Empty abbreviation provided",
}
}
if strings.ContainsAny(scope.Abbreviation, "\t  \n\r\t") {
return nil, models.BadInputError{
Object: "ScopeInput",
Field: "abbreviation",
Problem: "Invalid abbreviation provided",
}
}
ownerName = strings.Trim(ownerName, "  \t\r\n")
if ownerName == "" {
return nil, models.BadInputError{
Object: "ScopeInput",
Field: "ownerName",
Problem: "Empty owner name provided",
}
}
owner := entities.ScopeMember{
ScopeID: -1,
UserID: user.ID,
Name: ownerName,
Owner: true,
}
newScope, err := s.Repository.Create(ctx, scope, owner)
if err != nil {
return nil, err
}
owner.ScopeID = newScope.ID
return generateResult(*newScope, []entities.ScopeMember{owner}, []entities.Stat{}), nil
}
func (s *Service) Update(ctx context.Context, scopeId int, update models.ScopeUpdate) (*Result, error) {
user := s.Auth.GetUser(ctx)
if user == nil {
return nil, models.PermissionDeniedError{}
}
scope, err := s.Find(ctx, scopeId)
if err != nil {
return nil, err
}
if !scope.Members[user.ID].Owner {
return nil, models.ForbiddenError("You do not own the scope")
}
if update.Name != nil && *update.Name == "" {
return nil, models.BadInputError{
Object: "ScopeUpdate",
Field: "name",
Problem: "Empty name provided",
}
}
if update.Abbreviation != nil && *update.Abbreviation == "" {
return nil, models.BadInputError{
Object: "ScopeUpdate",
Field: "name",
Problem: "Empty name provided",
}
}
err = s.Repository.Update(ctx, scope.Scope, update)
if err != nil {
return nil, err
}
scope.ApplyUpdate(update)
return scope, nil
}
func (s *Service) Delete(ctx context.Context, scopeId int) (*Result, error) {
user := s.Auth.GetUser(ctx)
if user == nil {
return nil, models.PermissionDeniedError{}
}
scope, err := s.Find(ctx, scopeId)
if err != nil {
return nil, err
}
if !scope.Members[user.ID].Owner {
return nil, models.ForbiddenError("You do not own the scope")
}
err = s.Repository.Delete(ctx, scope.Scope)
if err != nil {
return nil, err
}
return scope, nil
}