diff --git a/pkg/integrations/task_test.go b/pkg/integrations/task_test.go index f4d7820c74c..c5cc1078abd 100644 --- a/pkg/integrations/task_test.go +++ b/pkg/integrations/task_test.go @@ -269,6 +269,24 @@ func TestTask(t *testing.T) { assert.Contains(t, rec.Body.String(), `"text":"Lorem Ipsum"`) }) }) + t.Run("Move to other list", func(t *testing.T) { + t.Run("normal", func(t *testing.T) { + rec, err := testHandler.testUpdateWithUser(nil, map[string]string{"listtask": "1"}, `{"list_id":7}`) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `"list_id":7`) + assert.NotContains(t, rec.Body.String(), `"list_id":1`) + }) + t.Run("Forbidden", func(t *testing.T) { + _, err := testHandler.testUpdateWithUser(nil, map[string]string{"listtask": "1"}, `{"list_id":20}`) + assert.Error(t, err) + assertHandlerErrorCode(t, err, models.ErrorCodeGenericForbidden) + }) + t.Run("Read Only", func(t *testing.T) { + _, err := testHandler.testUpdateWithUser(nil, map[string]string{"listtask": "1"}, `{"list_id":6}`) + assert.Error(t, err) + assertHandlerErrorCode(t, err, models.ErrorCodeGenericForbidden) + }) + }) }) t.Run("Delete", func(t *testing.T) { t.Run("Normal", func(t *testing.T) { diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 99a4989bf97..af76bd1f847 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -649,7 +649,9 @@ func (t *Task) Update() (err error) { "end_date_unix", "hex_color", "done_at_unix", - "percent_done"). + "percent_done", + "list_id", + ). Update(ot) *t = ot if err != nil { diff --git a/pkg/models/tasks_rights.go b/pkg/models/tasks_rights.go index 4771a995e21..8eb13834777 100644 --- a/pkg/models/tasks_rights.go +++ b/pkg/models/tasks_rights.go @@ -59,12 +59,24 @@ func (t *Task) CanWrite(a web.Auth) (canWrite bool, err error) { // Helper function to check if a user can do stuff on a list task func (t *Task) canDoTask(a web.Auth) (bool, error) { // Get the task - lI, err := GetTaskByIDSimple(t.ID) + ot, err := GetTaskByIDSimple(t.ID) if err != nil { return false, err } + // Check if we're moving the task into a different list to check if the user has sufficient rights for that on the new list + if t.ListID != 0 && t.ListID != ot.ListID { + newList := &List{ID: t.ListID} + can, err := newList.CanWrite(a) + if err != nil { + return false, err + } + if !can { + return false, ErrGenericForbidden{} + } + } + // A user can do a task if it has write acces to its list - l := &List{ID: lI.ListID} + l := &List{ID: ot.ListID} return l.CanWrite(a) }