2020-04-11 04:22:22 +02:00
|
|
|
package graph
|
|
|
|
|
2020-04-10 04:40:22 +02:00
|
|
|
// 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"
|
|
|
|
"database/sql"
|
2020-04-20 05:02:55 +02:00
|
|
|
"fmt"
|
2020-04-10 04:40:22 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/jordanknott/project-citadel/api/pg"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (r *mutationResolver) CreateRefreshToken(ctx context.Context, input NewRefreshToken) (*pg.RefreshToken, error) {
|
|
|
|
userID := uuid.MustParse("0183d9ab-d0ed-4c9b-a3df-77a0cdd93dca")
|
|
|
|
refreshCreatedAt := time.Now().UTC()
|
|
|
|
refreshExpiresAt := refreshCreatedAt.AddDate(0, 0, 1)
|
|
|
|
refreshToken, err := r.Repository.CreateRefreshToken(ctx, pg.CreateRefreshTokenParams{userID, refreshCreatedAt, refreshExpiresAt})
|
|
|
|
return &refreshToken, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) CreateUserAccount(ctx context.Context, input NewUserAccount) (*pg.UserAccount, error) {
|
|
|
|
createdAt := time.Now().UTC()
|
2020-04-20 05:02:55 +02:00
|
|
|
userAccount, err := r.Repository.CreateUserAccount(ctx, pg.CreateUserAccountParams{input.FirstName, input.LastName, input.Email, input.Username, createdAt, input.Password})
|
2020-04-10 04:40:22 +02:00
|
|
|
return &userAccount, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) {
|
|
|
|
organizationID, err := uuid.Parse(input.OrganizationID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Team{}, err
|
|
|
|
}
|
|
|
|
createdAt := time.Now().UTC()
|
|
|
|
team, err := r.Repository.CreateTeam(ctx, pg.CreateTeamParams{organizationID, createdAt, input.Name})
|
|
|
|
return &team, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject) (*pg.Project, error) {
|
|
|
|
createdAt := time.Now().UTC()
|
2020-04-20 05:02:55 +02:00
|
|
|
project, err := r.Repository.CreateProject(ctx, pg.CreateProjectParams{input.UserID, input.TeamID, createdAt, input.Name})
|
2020-04-10 04:40:22 +02:00
|
|
|
return &project, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) CreateTaskGroup(ctx context.Context, input NewTaskGroup) (*pg.TaskGroup, error) {
|
|
|
|
createdAt := time.Now().UTC()
|
|
|
|
projectID, err := uuid.Parse(input.ProjectID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.TaskGroup{}, err
|
|
|
|
}
|
|
|
|
project, err := r.Repository.CreateTaskGroup(ctx,
|
|
|
|
pg.CreateTaskGroupParams{projectID, createdAt, input.Name, input.Position})
|
|
|
|
return &project, err
|
|
|
|
}
|
|
|
|
|
2020-04-11 04:47:43 +02:00
|
|
|
func (r *mutationResolver) UpdateTaskGroupLocation(ctx context.Context, input NewTaskGroupLocation) (*pg.TaskGroup, error) {
|
|
|
|
taskGroup, err := r.Repository.UpdateTaskGroupLocation(ctx, pg.UpdateTaskGroupLocationParams{
|
|
|
|
input.TaskGroupID,
|
|
|
|
input.Position,
|
|
|
|
})
|
|
|
|
return &taskGroup, err
|
|
|
|
}
|
|
|
|
|
2020-04-11 21:24:45 +02:00
|
|
|
func (r *mutationResolver) DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error) {
|
|
|
|
deletedTasks, err := r.Repository.DeleteTasksByTaskGroupID(ctx, input.TaskGroupID)
|
|
|
|
if err != nil {
|
|
|
|
return &DeleteTaskGroupPayload{}, err
|
|
|
|
}
|
|
|
|
taskGroup, err := r.Repository.GetTaskGroupByID(ctx, input.TaskGroupID)
|
|
|
|
if err != nil {
|
|
|
|
return &DeleteTaskGroupPayload{}, err
|
|
|
|
}
|
|
|
|
deletedTaskGroups, err := r.Repository.DeleteTaskGroupByID(ctx, input.TaskGroupID)
|
|
|
|
if err != nil {
|
|
|
|
return &DeleteTaskGroupPayload{}, err
|
|
|
|
}
|
|
|
|
return &DeleteTaskGroupPayload{true, int(deletedTasks + deletedTaskGroups), &taskGroup}, nil
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *mutationResolver) AddTaskLabel(ctx context.Context, input *AddTaskLabelInput) (*pg.Task, error) {
|
|
|
|
assignedDate := time.Now().UTC()
|
|
|
|
_, err := r.Repository.CreateTaskLabelForTask(ctx, pg.CreateTaskLabelForTaskParams{input.TaskID, input.LabelColorID, assignedDate})
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
|
|
|
return &task, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) RemoveTaskLabel(ctx context.Context, input *RemoveTaskLabelInput) (*pg.Task, error) {
|
|
|
|
panic(fmt.Errorf("not implemented"))
|
|
|
|
}
|
|
|
|
|
2020-04-10 04:40:22 +02:00
|
|
|
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*pg.Task, error) {
|
|
|
|
taskGroupID, err := uuid.Parse(input.TaskGroupID)
|
|
|
|
createdAt := time.Now().UTC()
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
task, err := r.Repository.CreateTask(ctx, pg.CreateTaskParams{taskGroupID, createdAt, input.Name, input.Position})
|
|
|
|
return &task, err
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *mutationResolver) UpdateTaskDescription(ctx context.Context, input UpdateTaskDescriptionInput) (*pg.Task, error) {
|
|
|
|
task, err := r.Repository.UpdateTaskDescription(ctx, pg.UpdateTaskDescriptionParams{input.TaskID, sql.NullString{String: input.Description, Valid: true}})
|
|
|
|
return &task, err
|
|
|
|
}
|
|
|
|
|
2020-04-10 04:40:22 +02:00
|
|
|
func (r *mutationResolver) UpdateTaskLocation(ctx context.Context, input NewTaskLocation) (*pg.Task, error) {
|
|
|
|
taskID, err := uuid.Parse(input.TaskID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
taskGroupID, err := uuid.Parse(input.TaskGroupID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
task, err := r.Repository.UpdateTaskLocation(ctx, pg.UpdateTaskLocationParams{taskID, taskGroupID, input.Position})
|
|
|
|
|
|
|
|
return &task, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) UpdateTaskName(ctx context.Context, input UpdateTaskName) (*pg.Task, error) {
|
|
|
|
taskID, err := uuid.Parse(input.TaskID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
task, err := r.Repository.UpdateTaskName(ctx, pg.UpdateTaskNameParams{taskID, input.Name})
|
|
|
|
return &task, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mutationResolver) DeleteTask(ctx context.Context, input DeleteTaskInput) (*DeleteTaskPayload, error) {
|
|
|
|
taskID, err := uuid.Parse(input.TaskID)
|
|
|
|
if err != nil {
|
|
|
|
return &DeleteTaskPayload{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"taskID": taskID.String(),
|
|
|
|
}).Info("deleting task")
|
|
|
|
err = r.Repository.DeleteTaskByID(ctx, taskID)
|
|
|
|
if err != nil {
|
|
|
|
return &DeleteTaskPayload{}, err
|
|
|
|
}
|
|
|
|
return &DeleteTaskPayload{taskID.String()}, nil
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *mutationResolver) AssignTask(ctx context.Context, input *AssignTaskInput) (*pg.Task, error) {
|
|
|
|
assignedDate := time.Now().UTC()
|
|
|
|
assignedTask, err := r.Repository.CreateTaskAssigned(ctx, pg.CreateTaskAssignedParams{input.TaskID, input.UserID, assignedDate})
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"userID": assignedTask.UserID,
|
|
|
|
"taskID": assignedTask.TaskID,
|
|
|
|
"assignedTaskID": assignedTask.TaskAssignedID,
|
|
|
|
}).Info("assigned task")
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Task{}, err
|
|
|
|
}
|
|
|
|
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
|
|
|
return &task, err
|
|
|
|
}
|
|
|
|
|
2020-04-11 21:24:45 +02:00
|
|
|
func (r *mutationResolver) LogoutUser(ctx context.Context, input LogoutUser) (bool, error) {
|
|
|
|
userID, err := uuid.Parse(input.UserID)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = r.Repository.DeleteRefreshTokenByUserID(ctx, userID)
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *projectResolver) Team(ctx context.Context, obj *pg.Project) (*pg.Team, error) {
|
|
|
|
team, err := r.Repository.GetTeamByID(ctx, obj.TeamID)
|
|
|
|
return &team, err
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *projectResolver) Owner(ctx context.Context, obj *pg.Project) (*ProjectMember, error) {
|
|
|
|
user, err := r.Repository.GetUserAccountByID(ctx, obj.Owner)
|
|
|
|
if err != nil {
|
|
|
|
return &ProjectMember{}, err
|
|
|
|
}
|
|
|
|
initials := string([]rune(user.FirstName)[0]) + string([]rune(user.LastName)[0])
|
|
|
|
profileIcon := &ProfileIcon{nil, &initials}
|
|
|
|
return &ProjectMember{obj.Owner, user.FirstName, user.LastName, profileIcon}, nil
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *projectResolver) TaskGroups(ctx context.Context, obj *pg.Project) ([]pg.TaskGroup, error) {
|
|
|
|
return r.Repository.GetTaskGroupsForProject(ctx, obj.ProjectID)
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *projectResolver) Members(ctx context.Context, obj *pg.Project) ([]ProjectMember, error) {
|
|
|
|
user, err := r.Repository.GetUserAccountByID(ctx, obj.Owner)
|
|
|
|
members := []ProjectMember{}
|
|
|
|
if err != nil {
|
|
|
|
return members, err
|
|
|
|
}
|
|
|
|
initials := string([]rune(user.FirstName)[0]) + string([]rune(user.LastName)[0])
|
|
|
|
profileIcon := &ProfileIcon{nil, &initials}
|
|
|
|
members = append(members, ProjectMember{obj.Owner, user.FirstName, user.LastName, profileIcon})
|
|
|
|
return members, nil
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *queryResolver) Users(ctx context.Context) ([]pg.UserAccount, error) {
|
|
|
|
return r.Repository.GetAllUserAccounts(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *queryResolver) FindUser(ctx context.Context, input FindUser) (*pg.UserAccount, error) {
|
|
|
|
userId, err := uuid.Parse(input.UserID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.UserAccount{}, err
|
|
|
|
}
|
|
|
|
account, err := r.Repository.GetUserAccountByID(ctx, userId)
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return &pg.UserAccount{}, &gqlerror.Error{
|
|
|
|
Message: "User not found",
|
|
|
|
Extensions: map[string]interface{}{
|
|
|
|
"code": "10-404",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &account, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *queryResolver) FindProject(ctx context.Context, input FindProject) (*pg.Project, error) {
|
|
|
|
projectID, err := uuid.Parse(input.ProjectID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.Project{}, err
|
|
|
|
}
|
|
|
|
project, err := r.Repository.GetProjectByID(ctx, projectID)
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return &pg.Project{}, &gqlerror.Error{
|
|
|
|
Message: "Project not found",
|
|
|
|
Extensions: map[string]interface{}{
|
|
|
|
"code": "11-404",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &project, err
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*pg.Task, error) {
|
|
|
|
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
|
|
|
return &task, err
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]pg.Project, error) {
|
|
|
|
if input != nil {
|
|
|
|
teamID, err := uuid.Parse(*input.TeamID)
|
|
|
|
if err != nil {
|
|
|
|
return []pg.Project{}, err
|
|
|
|
}
|
|
|
|
return r.Repository.GetAllProjectsForTeam(ctx, teamID)
|
|
|
|
}
|
|
|
|
return r.Repository.GetAllProjects(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *queryResolver) TaskGroups(ctx context.Context) ([]pg.TaskGroup, error) {
|
|
|
|
return r.Repository.GetAllTaskGroups(ctx)
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *queryResolver) Me(ctx context.Context) (*pg.UserAccount, error) {
|
|
|
|
userID, ok := GetUserID(ctx)
|
|
|
|
if !ok {
|
|
|
|
return &pg.UserAccount{}, fmt.Errorf("internal server error")
|
|
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"userID": userID,
|
|
|
|
}).Info("getting user account")
|
|
|
|
user, err := r.Repository.GetUserAccountByID(ctx, userID)
|
|
|
|
if err != nil {
|
|
|
|
return &pg.UserAccount{}, err
|
|
|
|
}
|
|
|
|
return &user, err
|
|
|
|
}
|
|
|
|
|
2020-04-11 04:22:22 +02:00
|
|
|
func (r *taskResolver) TaskGroup(ctx context.Context, obj *pg.Task) (*pg.TaskGroup, error) {
|
|
|
|
taskGroup, err := r.Repository.GetTaskGroupByID(ctx, obj.TaskGroupID)
|
|
|
|
return &taskGroup, err
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *taskResolver) Description(ctx context.Context, obj *pg.Task) (*string, error) {
|
|
|
|
task, err := r.Repository.GetTaskByID(ctx, obj.TaskID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if !task.Description.Valid {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return &task.Description.String, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *taskResolver) Assigned(ctx context.Context, obj *pg.Task) ([]ProjectMember, error) {
|
|
|
|
taskMemberLinks, err := r.Repository.GetAssignedMembersForTask(ctx, obj.TaskID)
|
|
|
|
taskMembers := []ProjectMember{}
|
|
|
|
if err != nil {
|
|
|
|
return taskMembers, err
|
|
|
|
}
|
|
|
|
for _, taskMemberLink := range taskMemberLinks {
|
|
|
|
user, err := r.Repository.GetUserAccountByID(ctx, taskMemberLink.UserID)
|
|
|
|
if err != nil {
|
|
|
|
return taskMembers, err
|
|
|
|
}
|
|
|
|
initials := string([]rune(user.FirstName)[0]) + string([]rune(user.LastName)[0])
|
|
|
|
profileIcon := &ProfileIcon{nil, &initials}
|
|
|
|
taskMembers = append(taskMembers, ProjectMember{taskMemberLink.UserID, user.FirstName, user.LastName, profileIcon})
|
|
|
|
}
|
|
|
|
return taskMembers, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *taskResolver) Labels(ctx context.Context, obj *pg.Task) ([]pg.TaskLabel, error) {
|
|
|
|
return r.Repository.GetTaskLabelsForTaskID(ctx, obj.TaskID)
|
|
|
|
}
|
|
|
|
|
2020-04-10 04:40:22 +02:00
|
|
|
func (r *taskGroupResolver) ProjectID(ctx context.Context, obj *pg.TaskGroup) (string, error) {
|
|
|
|
return obj.ProjectID.String(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *taskGroupResolver) Tasks(ctx context.Context, obj *pg.TaskGroup) ([]pg.Task, error) {
|
|
|
|
tasks, err := r.Repository.GetTasksForTaskGroupID(ctx, obj.TaskGroupID)
|
|
|
|
return tasks, err
|
|
|
|
}
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
func (r *taskLabelResolver) ColorHex(ctx context.Context, obj *pg.TaskLabel) (string, error) {
|
|
|
|
labelColor, err := r.Repository.GetLabelColorByID(ctx, obj.LabelColorID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return labelColor.ColorHex, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *userAccountResolver) ProfileIcon(ctx context.Context, obj *pg.UserAccount) (*ProfileIcon, error) {
|
|
|
|
initials := string([]rune(obj.FirstName)[0]) + string([]rune(obj.LastName)[0])
|
|
|
|
profileIcon := &ProfileIcon{nil, &initials}
|
|
|
|
return profileIcon, nil
|
2020-04-10 04:40:22 +02:00
|
|
|
}
|
|
|
|
|
2020-04-11 04:22:22 +02:00
|
|
|
// Mutation returns MutationResolver implementation.
|
|
|
|
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }
|
|
|
|
|
|
|
|
// Project returns ProjectResolver implementation.
|
|
|
|
func (r *Resolver) Project() ProjectResolver { return &projectResolver{r} }
|
|
|
|
|
|
|
|
// Query returns QueryResolver implementation.
|
|
|
|
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }
|
|
|
|
|
|
|
|
// Task returns TaskResolver implementation.
|
|
|
|
func (r *Resolver) Task() TaskResolver { return &taskResolver{r} }
|
|
|
|
|
|
|
|
// TaskGroup returns TaskGroupResolver implementation.
|
|
|
|
func (r *Resolver) TaskGroup() TaskGroupResolver { return &taskGroupResolver{r} }
|
|
|
|
|
2020-04-20 05:02:55 +02:00
|
|
|
// TaskLabel returns TaskLabelResolver implementation.
|
|
|
|
func (r *Resolver) TaskLabel() TaskLabelResolver { return &taskLabelResolver{r} }
|
|
|
|
|
|
|
|
// UserAccount returns UserAccountResolver implementation.
|
|
|
|
func (r *Resolver) UserAccount() UserAccountResolver { return &userAccountResolver{r} }
|
2020-04-10 04:40:22 +02:00
|
|
|
|
|
|
|
type mutationResolver struct{ *Resolver }
|
|
|
|
type projectResolver struct{ *Resolver }
|
|
|
|
type queryResolver struct{ *Resolver }
|
|
|
|
type taskResolver struct{ *Resolver }
|
|
|
|
type taskGroupResolver struct{ *Resolver }
|
2020-04-20 05:02:55 +02:00
|
|
|
type taskLabelResolver struct{ *Resolver }
|
|
|
|
type userAccountResolver struct{ *Resolver }
|
|
|
|
|
|
|
|
// !!! WARNING !!!
|
|
|
|
// The code below was going to be deleted when updating resolvers. It has been copied here so you have
|
|
|
|
// one last chance to move it out of harms way if you want. There are two reasons this happens:
|
|
|
|
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
|
|
|
|
// it when you're done.
|
|
|
|
// - You have helper methods in this file. Move them out to keep these resolver files clean.
|
|
|
|
func (r *userAccountResolver) DisplayName(ctx context.Context, obj *pg.UserAccount) (string, error) {
|
|
|
|
return obj.FirstName + " " + obj.LastName, nil
|
|
|
|
}
|