Add session handling for tasks and related entities

This commit is contained in:
kolaente 2020-12-23 00:51:28 +01:00
parent 1528e7d861
commit 7b1d838997
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
17 changed files with 161 additions and 134 deletions

View File

@ -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,
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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