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
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
|
|
}
|