Loggest thy 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.
 
 
 
 
 
 

278 lines
6.1 KiB

package mysql
import (
"context"
"database/sql"
"encoding/json"
"git.aiterp.net/stufflog3/stufflog3-api/internal/database/mysql/mysqlcore"
"git.aiterp.net/stufflog3/stufflog3-api/internal/models"
"git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
"golang.org/x/sync/errgroup"
"sort"
)
type scopeRepository struct {
db *sql.DB
q *mysqlcore.Queries
}
func (r *scopeRepository) Find(ctx context.Context, id int, full bool) (*models.Scope, error) {
scope, err := r.q.GetScope(ctx, id)
if err != nil {
if err == sql.ErrNoRows {
return nil, slerrors.NotFound("Scope")
}
return nil, err
}
res := &models.Scope{
ScopeEntry: models.ScopeEntry{
ID: scope.ID,
Name: scope.Name,
Abbreviation: scope.Abbreviation,
},
Members: []models.ScopeMember{},
Projects: []models.ProjectEntry{},
Stats: []models.Stat{},
StatusLabels: make(map[models.Status]string),
}
eg, ctx := errgroup.WithContext(ctx)
if full {
eg.Go(func() error {
projects, err := r.q.ListProjectEntries(ctx, id)
if err != nil && err != sql.ErrNoRows {
return err
}
for _, project := range projects {
res.Projects = append(res.Projects, models.ProjectEntry{
ID: project.ID,
OwnerID: project.AuthorID,
CreatedTime: project.CreatedTime,
Name: project.Name,
Status: models.Status(project.Status),
})
}
return nil
})
eg.Go(func() error {
stats, err := r.q.ListStats(ctx, id)
if err != nil && err != sql.ErrNoRows {
return err
}
for _, stat := range stats {
var amounts map[string]int
if stat.AllowedAmounts.Valid {
amounts = make(map[string]int)
err := json.Unmarshal(stat.AllowedAmounts.RawMessage, &amounts)
if err != nil {
return err
}
}
res.Stats = append(res.Stats, models.Stat{
StatEntry: models.StatEntry{
ID: stat.ID,
Name: stat.Name,
Weight: stat.Weight,
},
Description: stat.Description,
AllowedAmounts: amounts,
})
}
return nil
})
}
eg.Go(func() error {
members, err := r.q.ListScopeMembers(ctx, id)
if err != nil && err != sql.ErrNoRows {
return err
}
for _, member := range members {
res.Members = append(res.Members, models.ScopeMember{
ID: member.UserID,
Name: member.Name,
Owner: member.Owner,
})
}
return nil
})
err = eg.Wait()
if err != nil {
return nil, err
}
return res, nil
}
func (r *scopeRepository) List(ctx context.Context) ([]models.ScopeEntry, error) {
scopes, err := r.q.ListScopes(ctx)
if err != nil {
return nil, err
}
res := make([]models.ScopeEntry, 0, len(scopes))
for _, scope := range scopes {
res = append(res, models.ScopeEntry{
ID: scope.ID,
Name: scope.Name,
Abbreviation: scope.Abbreviation,
})
}
return res, nil
}
func (r *scopeRepository) ListByUser(ctx context.Context, userID string) ([]models.ScopeEntry, error) {
scopes, err := r.q.ListScopesByUser(ctx, userID)
if err != nil {
return nil, err
}
res := make([]models.ScopeEntry, 0, len(scopes))
for _, scope := range scopes {
res = append(res, models.ScopeEntry{
ID: scope.ID,
Name: scope.Name,
Abbreviation: scope.Abbreviation,
})
}
return res, nil
}
func (r *scopeRepository) Create(ctx context.Context, scope models.ScopeEntry, owner models.ScopeMember) (*models.Scope, error) {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
res, err := q.InsertScope(ctx, mysqlcore.InsertScopeParams(scope))
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
err = q.UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
ScopeID: int(id),
UserID: owner.ID,
Name: owner.Name,
Owner: true,
})
err = tx.Commit()
if err != nil {
return nil, err
}
return &models.Scope{
ScopeEntry: models.ScopeEntry{
ID: int(id),
Name: scope.Name,
Abbreviation: scope.Abbreviation,
},
DisplayName: owner.Name,
Members: []models.ScopeMember{
{
ID: owner.ID,
Name: owner.Name,
Owner: true,
},
},
Projects: []models.ProjectEntry{},
Stats: []models.Stat{},
}, nil
}
func (r *scopeRepository) Update(ctx context.Context, scope models.ScopeEntry) error {
return mysqlcore.New(r.db).UpdateScope(ctx, mysqlcore.UpdateScopeParams{
Name: scope.Name,
Abbreviation: scope.Abbreviation,
ID: scope.ID,
})
}
func (r *scopeRepository) Delete(ctx context.Context, scope models.Scope) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
err = q.DeleteAllScopeMembers(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteScope(ctx, scope.ID)
if err != nil {
return err
}
return tx.Commit()
}
func (r *scopeRepository) UpdateMember(ctx context.Context, scope models.Scope, member models.ScopeMember) (*models.Scope, error) {
err := mysqlcore.New(r.db).UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
ScopeID: scope.ID,
UserID: member.ID,
Name: member.Name,
Owner: member.Owner,
})
if err != nil {
return nil, err
}
found := false
scope.Members = append(scope.Members[:0:0], scope.Members...)
for i, member2 := range scope.Members {
if member2.ID == member.ID {
scope.Members[i] = member2
found = true
}
}
if !found {
scope.Members = append(scope.Members, member)
sort.Slice(scope.Members, func(i, j int) bool {
return scope.Members[i].Name < scope.Members[j].Name
})
}
return &scope, nil
}
func (r *scopeRepository) DeleteMember(ctx context.Context, scope models.Scope, userID string) (*models.Scope, error) {
err := mysqlcore.New(r.db).DeleteScopeMember(ctx, mysqlcore.DeleteScopeMemberParams{
ScopeID: scope.ID,
UserID: userID,
})
if err != nil {
return nil, err
}
newMembers := make([]models.ScopeMember, 0, len(scope.Members)-1)
for _, member := range scope.Members {
if member.ID != userID {
newMembers = append(newMembers, member)
}
}
scope.Members = newMembers
return &scope, nil
}