Loggest thine Stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

244 lines
5.5 KiB

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
}