diff --git a/pkg/models/label.go b/pkg/models/label.go index 4154335b7..4a26df899 100644 --- a/pkg/models/label.go +++ b/pkg/models/label.go @@ -222,7 +222,7 @@ func getUserTaskIDs(s *xorm.Session, u *user.User) (taskIDs []int64, err error) return nil, err } - tasks, _, _, err := getRawTasksForLists(lists, u, &taskOptions{ + tasks, _, _, err := getRawTasksForLists(s, lists, u, &taskOptions{ page: -1, perPage: 0, }) diff --git a/pkg/models/label_rights.go b/pkg/models/label_rights.go index f2222b5ac..c6919301c 100644 --- a/pkg/models/label_rights.go +++ b/pkg/models/label_rights.go @@ -88,7 +88,7 @@ func (l *Label) hasAccessToLabel(s *xorm.Session, a web.Auth) (has bool, maxRigh // Since the right depends on the task the label is associated with, we need to check that too. if ll.TaskID > 0 { t := &Task{ID: ll.TaskID} - _, maxRight, err = t.CanRead(a) + _, maxRight, err = t.CanRead(s, a) if err != nil { return } diff --git a/pkg/models/label_task.go b/pkg/models/label_task.go index 71ac27293..cc7e99797 100644 --- a/pkg/models/label_task.go +++ b/pkg/models/label_task.go @@ -119,7 +119,7 @@ func (lt *LabelTask) Create(s *xorm.Session, a web.Auth) (err error) { func (lt *LabelTask) ReadAll(s *xorm.Session, a web.Auth, search string, page int, perPage int) (result interface{}, resultCount int, numberOfTotalItems int64, err error) { // Check if the user has the right to see the task task := Task{ID: lt.TaskID} - canRead, _, err := task.CanRead(a) + canRead, _, err := task.CanRead(s, a) if err != nil { return nil, 0, 0, err } @@ -358,7 +358,7 @@ type LabelTaskBulk struct { // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/labels/bulk [post] func (ltb *LabelTaskBulk) Create(s *xorm.Session, a web.Auth) (err error) { - task, err := GetTaskByIDSimple(ltb.TaskID) + task, err := GetTaskByIDSimple(s, ltb.TaskID) if err != nil { return } diff --git a/pkg/models/label_task_rights.go b/pkg/models/label_task_rights.go index 4e3da7a34..300969e0d 100644 --- a/pkg/models/label_task_rights.go +++ b/pkg/models/label_task_rights.go @@ -70,9 +70,9 @@ func (ltb *LabelTaskBulk) CanCreate(s *xorm.Session, a web.Auth) (bool, error) { // always the same check for either deleting or adding a label to a task func canDoLabelTask(s *xorm.Session, taskID int64, a web.Auth) (bool, error) { // A user can add a label to a task if he can write to the task - task, err := GetTaskByIDSimple(taskID) + task, err := GetTaskByIDSimple(s, taskID) if err != nil { return false, err } - return task.CanUpdate(a) + return task.CanUpdate(s, a) } diff --git a/pkg/models/list.go b/pkg/models/list.go index a535f2bcb..a7af5fd4d 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -548,7 +548,7 @@ func updateListLastUpdated(s *xorm.Session, list *List) error { func updateListByTaskID(s *xorm.Session, taskID int64) (err error) { // need to get the task to update the list last updated timestamp - task, err := GetTaskByIDSimple(taskID) + task, err := GetTaskByIDSimple(s, taskID) if err != nil { return err } diff --git a/pkg/models/list_duplicate.go b/pkg/models/list_duplicate.go index d8df5d81d..640b1b51e 100644 --- a/pkg/models/list_duplicate.go +++ b/pkg/models/list_duplicate.go @@ -108,7 +108,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { log.Debugf("Duplicated all buckets from list %d into %d", ld.ListID, ld.List.ID) // Get all tasks + all task details - tasks, _, _, err := getTasksForLists([]*List{{ID: ld.ListID}}, a, &taskOptions{}) + tasks, _, _, err := getTasksForLists(s, []*List{{ID: ld.ListID}}, a, &taskOptions{}) if err != nil { return err } diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index 750aec87f..0671a2d7b 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -301,7 +301,7 @@ type BulkAssignees struct { // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/assignees/bulk [post] func (ba *BulkAssignees) Create(s *xorm.Session, a web.Auth) (err error) { - task, err := GetTaskByIDSimple(ba.TaskID) + task, err := GetTaskByIDSimple(s, ba.TaskID) if err != nil { return } diff --git a/pkg/models/task_attachment_rights.go b/pkg/models/task_attachment_rights.go index 6fb64b10d..0bc4248f4 100644 --- a/pkg/models/task_attachment_rights.go +++ b/pkg/models/task_attachment_rights.go @@ -24,20 +24,20 @@ import ( // CanRead checks if the user can see an attachment func (ta *TaskAttachment) CanRead(s *xorm.Session, a web.Auth) (bool, int, error) { t := &Task{ID: ta.TaskID} - return t.CanRead(a) + return t.CanRead(s, a) } // CanDelete checks if the user can delete an attachment func (ta *TaskAttachment) CanDelete(s *xorm.Session, a web.Auth) (bool, error) { t := &Task{ID: ta.TaskID} - return t.CanWrite(a) + return t.CanWrite(s, a) } // CanCreate checks if the user can create an attachment func (ta *TaskAttachment) CanCreate(s *xorm.Session, a web.Auth) (bool, error) { - t, err := GetTaskByIDSimple(ta.TaskID) + t, err := GetTaskByIDSimple(s, ta.TaskID) if err != nil { return false, err } - return t.CanCreate(a) + return t.CanCreate(s, a) } diff --git a/pkg/models/task_collection.go b/pkg/models/task_collection.go index 49446175f..fe7777245 100644 --- a/pkg/models/task_collection.go +++ b/pkg/models/task_collection.go @@ -161,7 +161,7 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa if err != nil { return nil, 0, 0, err } - return getTasksForLists([]*List{list}, a, taskopts) + return getTasksForLists(s, []*List{list}, a, taskopts) } // If the list ID is not set, we get all tasks for the user. @@ -190,5 +190,5 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa tf.Lists = []*List{{ID: tf.ListID}} } - return getTasksForLists(tf.Lists, a, taskopts) + return getTasksForLists(s, tf.Lists, a, taskopts) } diff --git a/pkg/models/task_comment_rights.go b/pkg/models/task_comment_rights.go index 3d45970ff..9ff808719 100644 --- a/pkg/models/task_comment_rights.go +++ b/pkg/models/task_comment_rights.go @@ -25,23 +25,23 @@ import ( // CanRead checks if a user can read a comment func (tc *TaskComment) CanRead(s *xorm.Session, a web.Auth) (bool, int, error) { t := Task{ID: tc.TaskID} - return t.CanRead(a) + return t.CanRead(s, a) } // CanDelete checks if a user can delete a comment func (tc *TaskComment) CanDelete(s *xorm.Session, a web.Auth) (bool, error) { t := Task{ID: tc.TaskID} - return t.CanWrite(a) + return t.CanWrite(s, a) } // CanUpdate checks if a user can update a comment func (tc *TaskComment) CanUpdate(s *xorm.Session, a web.Auth) (bool, error) { t := Task{ID: tc.TaskID} - return t.CanWrite(a) + return t.CanWrite(s, a) } // CanCreate checks if a user can create a new comment func (tc *TaskComment) CanCreate(s *xorm.Session, a web.Auth) (bool, error) { t := Task{ID: tc.TaskID} - return t.CanWrite(a) + return t.CanWrite(s, a) } diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index 97707bab1..72a4a94fa 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -60,7 +60,7 @@ func (tc *TaskComment) TableName() string { // @Router /tasks/{taskID}/comments [put] func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { // Check if the task exists - _, err = GetTaskSimple(&Task{ID: tc.TaskID}) + _, err = GetTaskSimple(s, &Task{ID: tc.TaskID}) if err != nil { return err } diff --git a/pkg/models/task_relation_rights.go b/pkg/models/task_relation_rights.go index 481a40a4f..e68fa1a05 100644 --- a/pkg/models/task_relation_rights.go +++ b/pkg/models/task_relation_rights.go @@ -26,7 +26,7 @@ import ( func (rel *TaskRelation) CanDelete(s *xorm.Session, a web.Auth) (bool, error) { // A user can delete a relation if it can update the base task baseTask := &Task{ID: rel.TaskID} - return baseTask.CanUpdate(a) + return baseTask.CanUpdate(s, a) } // CanCreate checks if a user can create a new relation between two relations @@ -38,14 +38,14 @@ func (rel *TaskRelation) CanCreate(s *xorm.Session, a web.Auth) (bool, error) { // Needs have write access to the base task and at least read access to the other task baseTask := &Task{ID: rel.TaskID} - has, err := baseTask.CanUpdate(a) + has, err := baseTask.CanUpdate(s, a) if err != nil || !has { return false, err } // We explicitly don't check if the two tasks are on the same list. otherTask := &Task{ID: rel.OtherTaskID} - has, _, err = otherTask.CanRead(a) + has, _, err = otherTask.CanRead(s, a) if err != nil { return false, err } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index ef49e8313..ee3e10cda 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -153,7 +153,7 @@ type taskOptions struct { // @Success 200 {array} models.Task "The tasks" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/all [get] -func (t *Task) ReadAll(a web.Auth, search string, page int, perPage int) (result interface{}, resultCount int, totalItems int64, err error) { +func (t *Task) ReadAll(s *xorm.Session, a web.Auth, search string, page int, perPage int) (result interface{}, resultCount int, totalItems int64, err error) { return nil, 0, 0, nil } @@ -209,7 +209,7 @@ func getFilterCondForSeparateTable(table string, concat taskFilterConcatinator, } //nolint:gocyclo -func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []*Task, resultCount int, totalItems int64, err error) { +func getRawTasksForLists(s *xorm.Session, lists []*List, a web.Auth, opts *taskOptions) (tasks []*Task, resultCount int, totalItems int64, err error) { // If the user does not have any lists, don't try to get any tasks if len(lists) == 0 { @@ -324,9 +324,7 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] } // Then return all tasks for that lists - query := x.NewSession(). - OrderBy(orderby) - queryCount := x.NewSession() + var where builder.Cond if len(opts.search) > 0 { // Postgres' is case sensitive by default. @@ -335,11 +333,9 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] // See https://stackoverflow.com/q/7005302/10924593 // Seems okay to use that now, we may need to find a better solution overall in the future. if config.DatabaseType.GetString() == "postgres" { - query = query.Where("title ILIKE ?", "%"+opts.search+"%") - queryCount = queryCount.Where("title ILIKE ?", "%"+opts.search+"%") + where = builder.Expr("title ILIKE ?", "%"+opts.search+"%") } else { - query = query.Where("title LIKE ?", "%"+opts.search+"%") - queryCount = queryCount.Where("title LIKE ?", "%"+opts.search+"%") + where = &builder.Like{"title LIKE ?", "%" + opts.search + "%"} } } @@ -352,10 +348,13 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] if hasFavoriteLists { // Make sure users can only see their favorites - userLists, _, _, err := getRawListsForUser(&listOptions{ - user: &user.User{ID: a.GetID()}, - page: -1, - }) + userLists, _, _, err := getRawListsForUser( + s, + &listOptions{ + user: &user.User{ID: a.GetID()}, + page: -1, + }, + ) if err != nil { return nil, 0, 0, err } @@ -399,8 +398,8 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] filters = append(filters, cond) } - query = query.Where(listCond) - queryCount = queryCount.Where(listCond) + query := s.Where(builder.And(listCond, where)) + queryCount := s.Where(builder.And(listCond, where)) if len(filters) > 0 { if opts.filterConcat == filterConcatOr { @@ -434,9 +433,9 @@ func getRawTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks [] return tasks, len(tasks), totalItems, nil } -func getTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []*Task, resultCount int, totalItems int64, err error) { +func getTasksForLists(s *xorm.Session, lists []*List, a web.Auth, opts *taskOptions) (tasks []*Task, resultCount int, totalItems int64, err error) { - tasks, resultCount, totalItems, err = getRawTasksForLists(lists, a, opts) + tasks, resultCount, totalItems, err = getRawTasksForLists(s, lists, a, opts) if err != nil { return nil, 0, 0, err } @@ -446,7 +445,7 @@ func getTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []*Ta taskMap[t.ID] = t } - err = addMoreInfoToTasks(taskMap) + err = addMoreInfoToTasks(s, taskMap) if err != nil { return nil, 0, 0, err } @@ -455,18 +454,18 @@ func getTasksForLists(lists []*List, a web.Auth, opts *taskOptions) (tasks []*Ta } // GetTaskByIDSimple returns a raw task without extra data by the task ID -func GetTaskByIDSimple(taskID int64) (task Task, err error) { +func GetTaskByIDSimple(s *xorm.Session, taskID int64) (task Task, err error) { if taskID < 1 { return Task{}, ErrTaskDoesNotExist{taskID} } - return GetTaskSimple(&Task{ID: taskID}) + return GetTaskSimple(s, &Task{ID: taskID}) } // GetTaskSimple returns a raw task without extra data -func GetTaskSimple(t *Task) (task Task, err error) { +func GetTaskSimple(s *xorm.Session, t *Task) (task Task, err error) { task = *t - exists, err := x.Get(&task) + exists, err := s.Get(&task) if err != nil { return Task{}, err } @@ -494,9 +493,9 @@ func (bt *BulkTask) GetTasksByIDs(s *xorm.Session) (err error) { } // GetTasksByUIDs gets all tasks from a bunch of uids -func GetTasksByUIDs(uids []string) (tasks []*Task, err error) { +func GetTasksByUIDs(s *xorm.Session, uids []string) (tasks []*Task, err error) { tasks = []*Task{} - err = x.In("uid", uids).Find(&tasks) + err = s.In("uid", uids).Find(&tasks) if err != nil { return } @@ -506,13 +505,13 @@ func GetTasksByUIDs(uids []string) (tasks []*Task, err error) { taskMap[t.ID] = t } - err = addMoreInfoToTasks(taskMap) + err = addMoreInfoToTasks(s, taskMap) return } -func getRemindersForTasks(taskIDs []int64) (reminders []*TaskReminder, err error) { +func getRemindersForTasks(s *xorm.Session, taskIDs []int64) (reminders []*TaskReminder, err error) { reminders = []*TaskReminder{} - err = x.In("task_id", taskIDs).Find(&reminders) + err = s.In("task_id", taskIDs).Find(&reminders) return } @@ -521,7 +520,7 @@ func (t *Task) setIdentifier(list *List) { } // Get all assignees -func addAssigneesToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { +func addAssigneesToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) { taskAssignees, err := getRawTaskAssigneesForTasks(s, taskIDs) if err != nil { return @@ -538,7 +537,7 @@ func addAssigneesToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { } // Get all labels for all the tasks -func addLabelsToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { +func addLabelsToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) { labels, _, _, err := getLabelsByTaskIDs(s, &LabelByTaskIDsOptions{ TaskIDs: taskIDs, Page: -1, @@ -556,7 +555,7 @@ func addLabelsToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { } // Get task attachments -func addAttachmentsToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { +func addAttachmentsToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) { attachments, err := getTaskAttachmentsByTaskIDs(s, taskIDs) if err != nil { return @@ -568,11 +567,11 @@ func addAttachmentsToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) return } -func getTaskReminderMap(taskIDs []int64) (taskReminders map[int64][]time.Time, err error) { +func getTaskReminderMap(s *xorm.Session, taskIDs []int64) (taskReminders map[int64][]time.Time, err error) { taskReminders = make(map[int64][]time.Time) // Get all reminders and put them in a map to have it easier later - reminders, err := getRemindersForTasks(taskIDs) + reminders, err := getRemindersForTasks(s, taskIDs) if err != nil { return } @@ -584,9 +583,9 @@ func getTaskReminderMap(taskIDs []int64) (taskReminders map[int64][]time.Time, e return } -func addRelatedTasksToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error) { +func addRelatedTasksToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) { relatedTasks := []*TaskRelation{} - err = x.In("task_id", taskIDs).Find(&relatedTasks) + err = s.In("task_id", taskIDs).Find(&relatedTasks) if err != nil { return } @@ -597,7 +596,7 @@ func addRelatedTasksToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error relatedTaskIDs = append(relatedTaskIDs, rt.OtherTaskID) } fullRelatedTasks := make(map[int64]*Task) - err = x.In("id", relatedTaskIDs).Find(&fullRelatedTasks) + err = s.In("id", relatedTaskIDs).Find(&fullRelatedTasks) if err != nil { return } @@ -614,7 +613,7 @@ func addRelatedTasksToTasks(taskIDs []int64, taskMap map[int64]*Task) (err error // This function takes a map with pointers and returns a slice with pointers to tasks // It adds more stuff like assignees/labels/etc to a bunch of tasks -func addMoreInfoToTasks(taskMap map[int64]*Task) (err error) { +func addMoreInfoToTasks(s *xorm.Session, taskMap map[int64]*Task) (err error) { // No need to iterate over users and stuff if the list doesn't have tasks if len(taskMap) == 0 { @@ -631,17 +630,17 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (err error) { listIDs = append(listIDs, i.ListID) } - err = addAssigneesToTasks(taskIDs, taskMap) + err = addAssigneesToTasks(s, taskIDs, taskMap) if err != nil { return } - err = addLabelsToTasks(taskIDs, taskMap) + err = addLabelsToTasks(s, taskIDs, taskMap) if err != nil { return } - err = addAttachmentsToTasks(taskIDs, taskMap) + err = addAttachmentsToTasks(s, taskIDs, taskMap) if err != nil { return } @@ -651,13 +650,13 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (err error) { return } - taskReminders, err := getTaskReminderMap(taskIDs) + taskReminders, err := getTaskReminderMap(s, taskIDs) if err != nil { return err } // Get all identifiers - lists, err := GetListsByIDs(listIDs) + lists, err := GetListsByIDs(s, listIDs) if err != nil { return err } @@ -679,7 +678,7 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (err error) { } // Get all related tasks - err = addRelatedTasksToTasks(taskIDs, taskMap) + err = addRelatedTasksToTasks(s, taskIDs, taskMap) return } @@ -739,14 +738,8 @@ func checkBucketLimit(s *xorm.Session, t *Task, bucket *Bucket) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{id} [put] -func (t *Task) Create(a web.Auth) (err error) { - s := x.NewSession() - err = createTask(s, t, a, true) - if err != nil { - _ = s.Rollback() - return err - } - return s.Commit() +func (t *Task) Create(s *xorm.Session, a web.Auth) (err error) { + return createTask(s, t, a, true) } func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err error) { @@ -853,21 +846,17 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{id} [post] //nolint:gocyclo -func (t *Task) Update() (err error) { - - s := x.NewSession() +func (t *Task) Update(s *xorm.Session) (err error) { // Check if the task exists and get the old values - ot, err := GetTaskByIDSimple(t.ID) + ot, err := GetTaskByIDSimple(s, t.ID) if err != nil { - _ = s.Rollback() return } // Get the reminders - reminders, err := getRemindersForTasks([]int64{t.ID}) + reminders, err := getRemindersForTasks(s, []int64{t.ID}) if err != nil { - _ = s.Rollback() return } @@ -881,20 +870,17 @@ func (t *Task) Update() (err error) { // Update the assignees if err := ot.updateTaskAssignees(s, t.Assignees); err != nil { - _ = s.Rollback() return err } // Update the reminders if err := ot.updateReminders(s, t.Reminders); err != nil { - _ = s.Rollback() return err } // If there is a bucket set, make sure they belong to the same list as the task err = checkBucketAndTaskBelongToSameList(s, &ot, t.BucketID) if err != nil { - _ = s.Rollback() return } @@ -923,7 +909,6 @@ func (t *Task) Update() (err error) { if t.BucketID == 0 || (t.ListID != 0 && ot.ListID != t.ListID) { bucket, err = getDefaultBucket(s, t.ListID) if err != nil { - _ = s.Rollback() return err } t.BucketID = bucket.ID @@ -934,7 +919,6 @@ func (t *Task) Update() (err error) { latestTask := &Task{} _, err = s.Where("list_id = ?", t.ListID).OrderBy("id desc").Get(latestTask) if err != nil { - _ = s.Rollback() return err } @@ -946,7 +930,6 @@ func (t *Task) Update() (err error) { // Only check the bucket limit if the task is being moved between buckets, allow reordering the task within a bucket if t.BucketID != ot.BucketID { if err := checkBucketLimit(s, t, bucket); err != nil { - _ = s.Rollback() return err } } @@ -972,7 +955,6 @@ func (t *Task) Update() (err error) { // Which is why we merge the actual task struct with the one we got from the db // The user struct overrides values in the actual one. if err := mergo.Merge(&ot, t, mergo.WithOverride); err != nil { - _ = s.Rollback() return err } @@ -1034,7 +1016,6 @@ func (t *Task) Update() (err error) { Update(ot) *t = ot if err != nil { - _ = s.Rollback() return err } // Get the task updated timestamp in a new struct - if we'd just try to put it into t which we already have, it @@ -1042,17 +1023,11 @@ func (t *Task) Update() (err error) { nt := &Task{} _, err = s.ID(t.ID).Get(nt) if err != nil { - _ = s.Rollback() return err } t.Updated = nt.Updated - err = updateListLastUpdated(s, &List{ID: t.ListID}) - if err != nil { - _ = s.Rollback() - return err - } - return s.Commit() + return updateListLastUpdated(s, &List{ID: t.ListID}) } // This helper function updates the reminders, doneAt, start and end dates of the *old* task @@ -1190,14 +1165,14 @@ func (t *Task) updateReminders(s *xorm.Session, reminders []time.Time) (err erro // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{id} [delete] -func (t *Task) Delete() (err error) { +func (t *Task) Delete(s *xorm.Session) (err error) { - if _, err = x.ID(t.ID).Delete(Task{}); err != nil { + if _, err = s.ID(t.ID).Delete(Task{}); err != nil { return err } // Delete assignees - if _, err = x.Where("task_id = ?", t.ID).Delete(TaskAssginee{}); err != nil { + if _, err = s.Where("task_id = ?", t.ID).Delete(TaskAssginee{}); err != nil { return err } @@ -1219,16 +1194,16 @@ func (t *Task) Delete() (err error) { // @Failure 404 {object} models.Message "Task not found" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{ID} [get] -func (t *Task) ReadOne() (err error) { +func (t *Task) ReadOne(s *xorm.Session) (err error) { taskMap := make(map[int64]*Task, 1) taskMap[t.ID] = &Task{} - *taskMap[t.ID], err = GetTaskByIDSimple(t.ID) + *taskMap[t.ID], err = GetTaskByIDSimple(s, t.ID) if err != nil { return } - err = addMoreInfoToTasks(taskMap) + err = addMoreInfoToTasks(s, taskMap) if err != nil { return } diff --git a/pkg/models/tasks_rights.go b/pkg/models/tasks_rights.go index cac9f32fa..da044ac73 100644 --- a/pkg/models/tasks_rights.go +++ b/pkg/models/tasks_rights.go @@ -18,29 +18,30 @@ package models import ( "code.vikunja.io/web" + "xorm.io/xorm" ) // CanDelete checks if the user can delete an task -func (t *Task) CanDelete(a web.Auth) (bool, error) { - return t.canDoTask(a) +func (t *Task) CanDelete(s *xorm.Session, a web.Auth) (bool, error) { + return t.canDoTask(s, a) } // CanUpdate determines if a user has the right to update a list task -func (t *Task) CanUpdate(a web.Auth) (bool, error) { - return t.canDoTask(a) +func (t *Task) CanUpdate(s *xorm.Session, a web.Auth) (bool, error) { + return t.canDoTask(s, a) } // CanCreate determines if a user has the right to create a list task -func (t *Task) CanCreate(a web.Auth) (bool, error) { +func (t *Task) CanCreate(s *xorm.Session, a web.Auth) (bool, error) { // A user can do a task if he has write acces to its list l := &List{ID: t.ListID} return l.CanWrite(s, a) } // CanRead determines if a user can read a task -func (t *Task) CanRead(a web.Auth) (canRead bool, maxRight int, err error) { +func (t *Task) CanRead(s *xorm.Session, a web.Auth) (canRead bool, maxRight int, err error) { // Get the task, error out if it doesn't exist - *t, err = GetTaskByIDSimple(t.ID) + *t, err = GetTaskByIDSimple(s, t.ID) if err != nil { return } @@ -51,14 +52,14 @@ func (t *Task) CanRead(a web.Auth) (canRead bool, maxRight int, err error) { } // CanWrite checks if a user has write access to a task -func (t *Task) CanWrite(a web.Auth) (canWrite bool, err error) { - return t.canDoTask(a) +func (t *Task) CanWrite(s *xorm.Session, a web.Auth) (canWrite bool, err error) { + return t.canDoTask(s, a) } // Helper function to check if a user can do stuff on a list task -func (t *Task) canDoTask(a web.Auth) (bool, error) { +func (t *Task) canDoTask(s *xorm.Session, a web.Auth) (bool, error) { // Get the task - ot, err := GetTaskByIDSimple(t.ID) + ot, err := GetTaskByIDSimple(s, t.ID) if err != nil { return false, err } diff --git a/pkg/models/tasks_test.go b/pkg/models/tasks_test.go index b350f73f8..bab26ba34 100644 --- a/pkg/models/tasks_test.go +++ b/pkg/models/tasks_test.go @@ -36,12 +36,15 @@ func TestTask_Create(t *testing.T) { t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ Title: "Lorem", Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Create(usr) + err := task.Create(s, usr) assert.NoError(t, err) // Assert getting a uid assert.NotEmpty(t, task.UID) @@ -50,6 +53,9 @@ func TestTask_Create(t *testing.T) { assert.Equal(t, int64(18), task.Index) // Assert moving it into the default bucket assert.Equal(t, int64(1), task.BucketID) + err = s.Commit() + assert.NoError(t, err) + db.AssertExists(t, "tasks", map[string]interface{}{ "id": task.ID, "title": "Lorem", @@ -62,47 +68,59 @@ func TestTask_Create(t *testing.T) { }) t.Run("empty title", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ Title: "", Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Create(usr) + err := task.Create(s, usr) assert.Error(t, err) assert.True(t, IsErrTaskCannotBeEmpty(err)) }) t.Run("nonexistant list", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ Title: "Test", Description: "Lorem Ipsum Dolor", ListID: 9999999, } - err := task.Create(usr) + err := task.Create(s, usr) assert.Error(t, err) assert.True(t, IsErrListDoesNotExist(err)) }) t.Run("noneixtant user", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + nUser := &user.User{ID: 99999999} task := &Task{ Title: "Test", Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Create(nUser) + err := task.Create(s, nUser) assert.Error(t, err) assert.True(t, user.IsErrUserDoesNotExist(err)) }) t.Run("full bucket", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ Title: "Lorem", Description: "Lorem Ipsum Dolor", ListID: 1, BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3 } - err := task.Create(usr) + err := task.Create(s, usr) assert.Error(t, err) assert.True(t, IsErrBucketLimitExceeded(err)) }) @@ -111,14 +129,20 @@ func TestTask_Create(t *testing.T) { func TestTask_Update(t *testing.T) { t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ ID: 1, Title: "test10000", Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Update() + err := task.Update(s) assert.NoError(t, err) + err = s.Commit() + assert.NoError(t, err) + db.AssertExists(t, "tasks", map[string]interface{}{ "id": 1, "title": "test10000", @@ -128,18 +152,24 @@ func TestTask_Update(t *testing.T) { }) t.Run("nonexistant task", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ ID: 9999999, Title: "test10000", Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Update() + err := task.Update(s) assert.Error(t, err) assert.True(t, IsErrTaskDoesNotExist(err)) }) t.Run("full bucket", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ ID: 1, Title: "test10000", @@ -147,12 +177,15 @@ func TestTask_Update(t *testing.T) { ListID: 1, BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3 } - err := task.Update() + err := task.Update(s) assert.Error(t, err) assert.True(t, IsErrBucketLimitExceeded(err)) }) t.Run("full bucket but not changing the bucket", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ ID: 4, Title: "test10000", @@ -161,7 +194,7 @@ func TestTask_Update(t *testing.T) { ListID: 1, BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3 } - err := task.Update() + err := task.Update(s) assert.NoError(t, err) }) } @@ -169,11 +202,17 @@ func TestTask_Update(t *testing.T) { func TestTask_Delete(t *testing.T) { t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ ID: 1, } - err := task.Delete() + err := task.Delete(s) assert.NoError(t, err) + err = s.Commit() + assert.NoError(t, err) + db.AssertMissing(t, "tasks", map[string]interface{}{ "id": 1, }) @@ -183,6 +222,9 @@ func TestTask_Delete(t *testing.T) { func TestUpdateDone(t *testing.T) { t.Run("marking a task as done", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + oldTask := &Task{Done: false} newTask := &Task{Done: true} updateDone(oldTask, newTask) @@ -190,6 +232,9 @@ func TestUpdateDone(t *testing.T) { }) t.Run("unmarking a task as done", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + oldTask := &Task{Done: true} newTask := &Task{Done: false} updateDone(oldTask, newTask) @@ -397,15 +442,21 @@ func TestUpdateDone(t *testing.T) { func TestTask_ReadOne(t *testing.T) { t.Run("default", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ID: 1} - err := task.ReadOne() + err := task.ReadOne(s) assert.NoError(t, err) assert.Equal(t, "task #1", task.Title) }) t.Run("nonexisting", func(t *testing.T) { db.LoadAndAssertFixtures(t) + s := x.NewSession() + defer s.Close() + task := &Task{ID: 99999} - err := task.ReadOne() + err := task.ReadOne(s) assert.Error(t, err) assert.True(t, IsErrTaskDoesNotExist(err)) }) diff --git a/pkg/modules/migration/create_from_structure.go b/pkg/modules/migration/create_from_structure.go index b3f011892..af8fb5a2a 100644 --- a/pkg/modules/migration/create_from_structure.go +++ b/pkg/modules/migration/create_from_structure.go @@ -111,7 +111,7 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err } t.ListID = l.ID - err = t.Create(user) + err = t.Create(s, user) if err != nil { return } @@ -132,7 +132,7 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err // First create the related tasks if they do not exist if rt.ID == 0 { rt.ListID = t.ListID - err = rt.Create(user) + err = rt.Create(s, user) if err != nil { return } diff --git a/pkg/routes/caldav/listStorageProvider.go b/pkg/routes/caldav/listStorageProvider.go index 763136806..718622a13 100644 --- a/pkg/routes/caldav/listStorageProvider.go +++ b/pkg/routes/caldav/listStorageProvider.go @@ -127,7 +127,7 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]dat // GetTasksByUIDs... // Parse these into ressources... - tasks, err := models.GetTasksByUIDs(uids) + tasks, err := models.GetTasksByUIDs(s, uids) if err != nil { return nil, err } @@ -189,7 +189,7 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource, if vcls.task != nil { // save and override the updated unix date to not break any later etag checks updated := vcls.task.Updated - task, err := models.GetTaskSimple(&models.Task{ID: vcls.task.ID, UID: vcls.task.UID}) + task, err := models.GetTaskSimple(s, &models.Task{ID: vcls.task.ID, UID: vcls.task.UID}) if err != nil { if models.IsErrTaskDoesNotExist(err) { return nil, false, errs.ResourceNotFoundError @@ -238,7 +238,7 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da vTask.ListID = vcls.list.ID // Check the rights - canCreate, err := vTask.CanCreate(vcls.user) + canCreate, err := vTask.CanCreate(s, vcls.user) if err != nil { return nil, err } @@ -247,7 +247,7 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da } // Create the task - err = vTask.Create(vcls.user) + err = vTask.Create(s, vcls.user) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da vTask.ID = vcls.task.ID // Check the rights - canUpdate, err := vTask.CanUpdate(vcls.user) + canUpdate, err := vTask.CanUpdate(s, vcls.user) if err != nil { return nil, err } @@ -282,7 +282,7 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da } // Update the task - err = vTask.Update() + err = vTask.Update(s) if err != nil { return nil, err } @@ -300,7 +300,7 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error { if vcls.task != nil { // Check the rights - canDelete, err := vcls.task.CanDelete(vcls.user) + canDelete, err := vcls.task.CanDelete(s, vcls.user) if err != nil { return err } @@ -309,7 +309,7 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error { } // Delete it - return vcls.task.Delete() + return vcls.task.Delete(s) } return nil