add logging.
This commit is contained in:
@@ -5,7 +5,6 @@ package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/stufflog/server/graph/graphcore"
|
||||
"git.aiterp.net/stufflog/server/graph/graphutil"
|
||||
"git.aiterp.net/stufflog/server/graph/loaders"
|
||||
@@ -94,6 +93,16 @@ func (r *issueResolver) Items(ctx context.Context, obj *models.Issue, filter *mo
|
||||
return r.Database.IssueItems().List(ctx, *filter)
|
||||
}
|
||||
|
||||
func (r *issueResolver) Logs(ctx context.Context, obj *models.Issue) ([]*models.Log, error) {
|
||||
logs, err := r.Database.Logs().List(ctx, models.LogFilter{IssueIDs: []string{obj.ID}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.Auth.FilterLogList(ctx, &logs)
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
// Issue returns graphcore.IssueResolver implementation.
|
||||
func (r *Resolver) Issue() graphcore.IssueResolver { return &issueResolver{r} }
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package resolvers
|
||||
|
||||
// This file will be automatically regenerated based on the schema, any resolver implementations
|
||||
// will be copied through when generating and any unknown code will be moved to the end.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/stufflog/server/graph/graphcore"
|
||||
"git.aiterp.net/stufflog/server/models"
|
||||
)
|
||||
|
||||
func (r *logResolver) User(ctx context.Context, obj *models.Log) (*models.User, error) {
|
||||
return r.Database.Users().Find(ctx, obj.UserID)
|
||||
}
|
||||
|
||||
func (r *logItemResolver) Issue(ctx context.Context, obj *models.LogItem) (*models.Issue, error) {
|
||||
return r.Database.Issues().Find(ctx, obj.IssueID)
|
||||
}
|
||||
|
||||
func (r *logItemResolver) Item(ctx context.Context, obj *models.LogItem) (*models.IssueItem, error) {
|
||||
return r.Database.IssueItems().Find(ctx, obj.IssueItemID)
|
||||
}
|
||||
|
||||
func (r *logTaskResolver) Issue(ctx context.Context, obj *models.LogTask) (*models.Issue, error) {
|
||||
return r.Database.Issues().Find(ctx, obj.IssueID)
|
||||
}
|
||||
|
||||
func (r *logTaskResolver) Task(ctx context.Context, obj *models.LogTask) (*models.IssueTask, error) {
|
||||
return r.Database.IssueTasks().Find(ctx, obj.IssueTaskID)
|
||||
}
|
||||
|
||||
// Log returns graphcore.LogResolver implementation.
|
||||
func (r *Resolver) Log() graphcore.LogResolver { return &logResolver{r} }
|
||||
|
||||
// LogItem returns graphcore.LogItemResolver implementation.
|
||||
func (r *Resolver) LogItem() graphcore.LogItemResolver { return &logItemResolver{r} }
|
||||
|
||||
// LogTask returns graphcore.LogTaskResolver implementation.
|
||||
func (r *Resolver) LogTask() graphcore.LogTaskResolver { return &logTaskResolver{r} }
|
||||
|
||||
type logResolver struct{ *Resolver }
|
||||
type logItemResolver struct{ *Resolver }
|
||||
type logTaskResolver struct{ *Resolver }
|
||||
@@ -475,6 +475,162 @@ func (r *mutationResolver) EditIssueItem(ctx context.Context, input graphcore.Is
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) CreateLog(ctx context.Context, input graphcore.LogCreateInput) (*models.Log, error) {
|
||||
user := r.Auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, slerrors.PermissionDenied
|
||||
}
|
||||
|
||||
log := &models.Log{
|
||||
UserID: user.ID,
|
||||
Date: input.Date,
|
||||
Description: input.Description,
|
||||
Items: make([]models.LogItem, 0, len(input.Items)),
|
||||
Tasks: make([]models.LogTask, 0, len(input.Tasks)),
|
||||
}
|
||||
|
||||
for _, itemInput := range input.Items {
|
||||
item, err := r.Database.IssueItems().Find(ctx, itemInput.IssueItemID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
issue, err := r.Database.Issues().Find(ctx, item.IssueID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Auth.IssuePermission(ctx, *issue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Items = append(log.Items, models.LogItem{
|
||||
IssueID: item.IssueID,
|
||||
IssueItemID: item.ID,
|
||||
Amount: itemInput.Amount,
|
||||
})
|
||||
}
|
||||
for _, taskInput := range input.Tasks {
|
||||
task, err := r.Database.IssueTasks().Find(ctx, taskInput.IssueTaskID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
issue, err := r.Database.Issues().Find(ctx, task.IssueID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Auth.IssuePermission(ctx, *issue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Tasks = append(log.Tasks, models.LogTask{
|
||||
IssueID: task.IssueID,
|
||||
IssueTaskID: task.ID,
|
||||
Duration: taskInput.Duration,
|
||||
Units: taskInput.Units,
|
||||
})
|
||||
}
|
||||
|
||||
return r.Database.Logs().Insert(ctx, *log)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditLog(ctx context.Context, input graphcore.LogEditInput) (*models.Log, error) {
|
||||
user := r.Auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, slerrors.PermissionDenied
|
||||
}
|
||||
|
||||
log, err := r.Database.Logs().Find(ctx, input.LogID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
removeItems := append([]string{}, input.RemoveItems...)
|
||||
for _, itemInput := range input.UpdateItems {
|
||||
removeItems = append(removeItems, itemInput.IssueItemID)
|
||||
}
|
||||
removeTasks := append([]string{}, input.RemoveTasks...)
|
||||
for _, taskInput := range input.UpdateTasks {
|
||||
removeTasks = append(removeTasks, taskInput.IssueTaskID)
|
||||
}
|
||||
|
||||
if input.SetDate != nil {
|
||||
log.Date = *input.SetDate
|
||||
}
|
||||
if input.SetDescription != nil {
|
||||
log.Description = *input.SetDescription
|
||||
}
|
||||
for _, remove := range removeItems {
|
||||
for i, item := range log.Items {
|
||||
if remove == item.IssueItemID {
|
||||
log.Items = append(log.Items[:i], log.Items[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, remove := range removeTasks {
|
||||
for i, task := range log.Tasks {
|
||||
if remove == task.IssueTaskID {
|
||||
log.Tasks = append(log.Tasks[:i], log.Tasks[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, itemInput := range input.UpdateItems {
|
||||
item, err := r.Database.IssueItems().Find(ctx, itemInput.IssueItemID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
issue, err := r.Database.Issues().Find(ctx, item.IssueID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Auth.IssuePermission(ctx, *issue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Items = append(log.Items, models.LogItem{
|
||||
LogID: log.ID,
|
||||
IssueID: item.IssueID,
|
||||
IssueItemID: item.ID,
|
||||
Amount: itemInput.Amount,
|
||||
})
|
||||
}
|
||||
for _, taskInput := range input.UpdateTasks {
|
||||
task, err := r.Database.IssueTasks().Find(ctx, taskInput.IssueTaskID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
issue, err := r.Database.Issues().Find(ctx, task.IssueID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Auth.IssuePermission(ctx, *issue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Tasks = append(log.Tasks, models.LogTask{
|
||||
LogID: log.ID,
|
||||
IssueID: task.IssueID,
|
||||
IssueTaskID: task.ID,
|
||||
Duration: taskInput.Duration,
|
||||
Units: taskInput.Units,
|
||||
})
|
||||
}
|
||||
|
||||
err = r.Database.Logs().Save(ctx, *log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return log, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) LoginUser(ctx context.Context, input graphcore.UserLoginInput) (*models.User, error) {
|
||||
return r.Auth.Login(ctx, input.Username, input.Password)
|
||||
}
|
||||
|
||||
@@ -215,6 +215,46 @@ func (r *queryResolver) Projects(ctx context.Context, filter *models.ProjectFilt
|
||||
return projects, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Log(ctx context.Context, id string) (*models.Log, error) {
|
||||
user := r.Auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, slerrors.PermissionDenied
|
||||
}
|
||||
|
||||
log, err := r.Database.Logs().Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r.Auth.FilterLog(ctx, log)
|
||||
if log.Empty() {
|
||||
return nil, slerrors.NotFound("Log")
|
||||
}
|
||||
|
||||
return log, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Logs(ctx context.Context, filter *models.LogFilter) ([]*models.Log, error) {
|
||||
user := r.Auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, slerrors.PermissionDenied
|
||||
}
|
||||
|
||||
if filter == nil {
|
||||
filter = &models.LogFilter{
|
||||
UserIDs: []string{user.ID},
|
||||
}
|
||||
}
|
||||
|
||||
logs, err := r.Database.Logs().List(ctx, *filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.Auth.FilterLogList(ctx, &logs)
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Session(ctx context.Context) (*models.User, error) {
|
||||
user := r.Auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
|
||||
@@ -26,8 +26,8 @@ type Issue {
|
||||
tasks(filter: IssueTaskFilter): [IssueTask!]!
|
||||
"Issue items."
|
||||
items(filter: IssueIssueItemFilter): [IssueItem!]!
|
||||
#"Logs related to this issue."
|
||||
#logs: [Log!]!
|
||||
"Logs related to this issue."
|
||||
logs: [Log!]!
|
||||
}
|
||||
|
||||
input IssueFilter {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
"""
|
||||
A log is a chunk of logged work, on one or more issues.
|
||||
"""
|
||||
type Log {
|
||||
"The log's ID."
|
||||
id: String!
|
||||
"When the log is taking place."
|
||||
date: Time!
|
||||
"A description of the log."
|
||||
description: String!
|
||||
|
||||
"The user that logged the work."
|
||||
user: User!
|
||||
"The tasks logged."
|
||||
tasks: [LogTask!]!
|
||||
"The items changed."
|
||||
items: [LogItem!]!
|
||||
}
|
||||
|
||||
type LogTask {
|
||||
"Parent issue of the task."
|
||||
issue: Issue!
|
||||
"The issue task logged."
|
||||
task: IssueTask!
|
||||
"How many units of work is done, if applicable."
|
||||
units: Int
|
||||
"Time spent on the issue."
|
||||
duration: Duration!
|
||||
}
|
||||
|
||||
"""
|
||||
Log items are item changes related to a log.
|
||||
"""
|
||||
type LogItem {
|
||||
"Parent issue of the item."
|
||||
issue: Issue!
|
||||
"The item that has been acquired."
|
||||
item: IssueItem!
|
||||
"The amount of items acquired."
|
||||
amount: Int!
|
||||
}
|
||||
|
||||
"Filter for the logs query."
|
||||
input LogFilter {
|
||||
"Log IDs to select."
|
||||
logIds: [String!]
|
||||
"Limit to the user IDs."
|
||||
userIds: [String!]
|
||||
"The issue IDs to limit to."
|
||||
issueIds: [String!]
|
||||
"The issue task IDs to limit to."
|
||||
issueTaskIds: [String!]
|
||||
"The issue item IDs to limit to."
|
||||
issueItemIds: [String!]
|
||||
"Earliest date to get logs from (inclusive)."
|
||||
fromDate: Time
|
||||
"Latest date to get logs from (inclusive)."
|
||||
toDate: Time
|
||||
}
|
||||
|
||||
"Input for the createLog mutation."
|
||||
input LogCreateInput {
|
||||
"When did it take place."
|
||||
date: Time!
|
||||
"Describe the logged work."
|
||||
description: String!
|
||||
|
||||
"Add issue items to the log."
|
||||
items: [LogItemInput!]
|
||||
"Add issue tasks to the log."
|
||||
tasks: [LogTaskInput!]
|
||||
}
|
||||
|
||||
"Input for the editLog mutation."
|
||||
input LogEditInput {
|
||||
"The log to update."
|
||||
logId: String!
|
||||
|
||||
"Update the time of the log."
|
||||
setDate: Time
|
||||
"Update the description of the log."
|
||||
setDescription: String
|
||||
|
||||
"Add/update one or more items to the log."
|
||||
updateItems: [LogItemInput!]
|
||||
"Remove one or more items from the log."
|
||||
removeItems: [String!]
|
||||
"Add/update one or more items to the log."
|
||||
updateTasks: [LogTaskInput!]
|
||||
"Remove one or more items from the log."
|
||||
removeTasks: [String!]
|
||||
}
|
||||
|
||||
"Sub-input for the createLog and editLog mutation."
|
||||
input LogItemInput {
|
||||
"The issue item to log ID."
|
||||
issueItemId: String!
|
||||
"The amount of items acquired."
|
||||
amount: Int!
|
||||
}
|
||||
|
||||
"Sub-input for the createLog and editLog mutation."
|
||||
input LogTaskInput {
|
||||
"The issue item to log ID."
|
||||
issueTaskId: String!
|
||||
"The amount of units done, if applicable."
|
||||
units: Int
|
||||
"How long did it take?"
|
||||
duration: Duration!
|
||||
}
|
||||
@@ -30,6 +30,12 @@ type Mutation {
|
||||
editIssueItem(input: IssueItemEditInput!): IssueItem!
|
||||
|
||||
# LOG
|
||||
"Create a log."
|
||||
createLog(input: LogCreateInput!): Log!
|
||||
"Edit a log."
|
||||
editLog(input: LogEditInput!): Log!
|
||||
|
||||
# GOAL
|
||||
|
||||
# USER
|
||||
"Log in."
|
||||
|
||||
@@ -21,6 +21,11 @@ type Query {
|
||||
"List projects."
|
||||
projects(filter: ProjectFilter): [Project!]!
|
||||
|
||||
"Find log."
|
||||
log(id: String!): Log!
|
||||
"List logs."
|
||||
logs(filter: LogFilter): [Log!]!
|
||||
|
||||
"Check the user session."
|
||||
session: User
|
||||
}
|
||||
Reference in New Issue
Block a user