Refactor ListTask to Task (#92)

This commit is contained in:
konrad 2019-08-14 20:19:04 +00:00 committed by Gitea
parent be14634e1e
commit 66cdd79666
26 changed files with 206 additions and 189 deletions

View file

@ -184,7 +184,7 @@ Sorry for some of them being in German, I'll tranlate them at some point.
* [x] Less files, but with some kind of logic * [x] Less files, but with some kind of logic
* [x] Have extra functions for logging to call so it is possible to call `log.Info` instead of `log.Log.Info` * [x] Have extra functions for logging to call so it is possible to call `log.Info` instead of `log.Log.Info`
* [x] `GetUserByID` and the likes should return pointers * [x] `GetUserByID` and the likes should return pointers
* [ ] `ListTask` should be just `Task` * [x] `ListTask` should be just `Task`
### Linters ### Linters

View file

@ -70,8 +70,8 @@ func TestList(t *testing.T) {
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
// Owned by user3 // Owned by user13
_, err := testHandler.testReadOne(nil, map[string]string{"list": "2"}) _, err := testHandler.testReadOne(nil, map[string]string{"list": "20"})
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.(*echo.HTTPError).Message, `You don't have the right to see this`) assert.Contains(t, err.(*echo.HTTPError).Message, `You don't have the right to see this`)
}) })
@ -177,8 +177,8 @@ func TestList(t *testing.T) {
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
// Owned by user3 // Owned by user13
_, err := testHandler.testUpdate(nil, map[string]string{"list": "2"}, `{"title":"TestLoremIpsum"}`) _, err := testHandler.testUpdate(nil, map[string]string{"list": "20"}, `{"title":"TestLoremIpsum"}`)
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`) assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
}) })
@ -260,8 +260,8 @@ func TestList(t *testing.T) {
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
// Owned by user3 // Owned by user13
_, err := testHandler.testDelete(nil, map[string]string{"list": "2"}) _, err := testHandler.testDelete(nil, map[string]string{"list": "20"})
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`) assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
}) })
@ -371,8 +371,8 @@ func TestList(t *testing.T) {
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
// Owned by user3 // Owned by user13
_, err := testHandler.testCreate(nil, map[string]string{"namespace": "3"}, `{"title":"Lorem"}`) _, err := testHandler.testCreate(nil, map[string]string{"namespace": "15"}, `{"title":"Lorem"}`)
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`) assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
}) })

View file

@ -25,16 +25,16 @@ import (
"testing" "testing"
) )
func TestListTask(t *testing.T) { func TestTask(t *testing.T) {
testHandler := webHandlerTest{ testHandler := webHandlerTest{
user: &testuser1, user: &testuser1,
strFunc: func() handler.CObject { strFunc: func() handler.CObject {
return &models.ListTask{} return &models.Task{}
}, },
t: t, t: t,
} }
// Only run specific nested tests: // Only run specific nested tests:
// ^TestListTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$ // ^TestTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$
t.Run("ReadAll", func(t *testing.T) { t.Run("ReadAll", func(t *testing.T) {
t.Run("Normal", func(t *testing.T) { t.Run("Normal", func(t *testing.T) {
rec, err := testHandler.testReadAll(nil, nil) rec, err := testHandler.testReadAll(nil, nil)
@ -333,7 +333,7 @@ func TestListTask(t *testing.T) {
t.Run("Nonexisting", func(t *testing.T) { t.Run("Nonexisting", func(t *testing.T) {
_, err := testHandler.testUpdate(nil, map[string]string{"listtask": "99999"}, `{"text":"Lorem Ipsum"}`) _, err := testHandler.testUpdate(nil, map[string]string{"listtask": "99999"}, `{"text":"Lorem Ipsum"}`)
assert.Error(t, err) assert.Error(t, err)
assertHandlerErrorCode(t, err, models.ErrCodeListTaskDoesNotExist) assertHandlerErrorCode(t, err, models.ErrCodeTaskDoesNotExist)
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
@ -415,7 +415,7 @@ func TestListTask(t *testing.T) {
t.Run("Nonexisting", func(t *testing.T) { t.Run("Nonexisting", func(t *testing.T) {
_, err := testHandler.testDelete(nil, map[string]string{"listtask": "99999"}) _, err := testHandler.testDelete(nil, map[string]string{"listtask": "99999"})
assert.Error(t, err) assert.Error(t, err)
assertHandlerErrorCode(t, err, models.ErrCodeListTaskDoesNotExist) assertHandlerErrorCode(t, err, models.ErrCodeTaskDoesNotExist)
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
@ -501,8 +501,8 @@ func TestListTask(t *testing.T) {
}) })
t.Run("Rights check", func(t *testing.T) { t.Run("Rights check", func(t *testing.T) {
t.Run("Forbidden", func(t *testing.T) { t.Run("Forbidden", func(t *testing.T) {
// Owned by user3 // Owned by user13
_, err := testHandler.testCreate(nil, map[string]string{"list": "2"}, `{"text":"Lorem Ipsum"}`) _, err := testHandler.testCreate(nil, map[string]string{"list": "20"}, `{"text":"Lorem Ipsum"}`)
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`) assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
}) })

View file

@ -25,8 +25,8 @@ import (
type BulkTask struct { type BulkTask struct {
// A list of task ids to update // A list of task ids to update
IDs []int64 `json:"task_ids"` IDs []int64 `json:"task_ids"`
Tasks []*ListTask `json:"-"` Tasks []*Task `json:"-"`
ListTask Task
} }
func (bt *BulkTask) checkIfTasksAreOnTheSameList() (err error) { func (bt *BulkTask) checkIfTasksAreOnTheSameList() (err error) {
@ -72,7 +72,7 @@ func (bt *BulkTask) CanUpdate(a web.Auth) (bool, error) {
// @Produce json // @Produce json
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param task body models.BulkTask true "The task object. Looks like a normal task, the only difference is it uses an array of list_ids to update." // @Param task body models.BulkTask true "The task object. Looks like a normal task, the only difference is it uses an array of list_ids to update."
// @Success 200 {object} models.ListTask "The updated task object." // @Success 200 {object} models.Task "The updated task object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided." // @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)" // @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
@ -90,7 +90,7 @@ func (bt *BulkTask) Update() (err error) {
for _, oldtask := range bt.Tasks { for _, oldtask := range bt.Tasks {
// When a repeating task is marked as done, we update all deadlines and reminders and set it as undone // When a repeating task is marked as done, we update all deadlines and reminders and set it as undone
updateDone(oldtask, &bt.ListTask) updateDone(oldtask, &bt.Task)
// Update the assignees // Update the assignees
if err := oldtask.updateTaskAssignees(bt.Assignees); err != nil { if err := oldtask.updateTaskAssignees(bt.Assignees); err != nil {
@ -100,12 +100,12 @@ func (bt *BulkTask) Update() (err error) {
// For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand // For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand
// Which is why we merge the actual task struct with the one we got from the // Which is why we merge the actual task struct with the one we got from the
// The user struct overrides values in the actual one. // The user struct overrides values in the actual one.
if err := mergo.Merge(oldtask, &bt.ListTask, mergo.WithOverride); err != nil { if err := mergo.Merge(oldtask, &bt.Task, mergo.WithOverride); err != nil {
return err return err
} }
// And because a false is considered to be a null value, we need to explicitly check that case here. // And because a false is considered to be a null value, we need to explicitly check that case here.
if !bt.ListTask.Done { if !bt.Task.Done {
oldtask.Done = false oldtask.Done = false
} }

View file

@ -7,8 +7,8 @@ import (
func TestBulkTask_Update(t *testing.T) { func TestBulkTask_Update(t *testing.T) {
type fields struct { type fields struct {
IDs []int64 IDs []int64
Tasks []*ListTask Tasks []*Task
ListTask ListTask Task Task
User *User User *User
} }
tests := []struct { tests := []struct {
@ -21,7 +21,7 @@ func TestBulkTask_Update(t *testing.T) {
name: "Test normal update", name: "Test normal update",
fields: fields{ fields: fields{
IDs: []int64{10, 11, 12}, IDs: []int64{10, 11, 12},
ListTask: ListTask{ Task: Task{
Text: "bulkupdated", Text: "bulkupdated",
}, },
User: &User{ID: 1}, User: &User{ID: 1},
@ -31,7 +31,7 @@ func TestBulkTask_Update(t *testing.T) {
name: "Test with one task on different list", name: "Test with one task on different list",
fields: fields{ fields: fields{
IDs: []int64{10, 11, 12, 13}, IDs: []int64{10, 11, 12, 13},
ListTask: ListTask{ Task: Task{
Text: "bulkupdated", Text: "bulkupdated",
}, },
User: &User{ID: 1}, User: &User{ID: 1},
@ -42,7 +42,7 @@ func TestBulkTask_Update(t *testing.T) {
name: "Test without any tasks", name: "Test without any tasks",
fields: fields{ fields: fields{
IDs: []int64{}, IDs: []int64{},
ListTask: ListTask{ Task: Task{
Text: "bulkupdated", Text: "bulkupdated",
}, },
User: &User{ID: 1}, User: &User{ID: 1},
@ -55,7 +55,7 @@ func TestBulkTask_Update(t *testing.T) {
bt := &BulkTask{ bt := &BulkTask{
IDs: tt.fields.IDs, IDs: tt.fields.IDs,
Tasks: tt.fields.Tasks, Tasks: tt.fields.Tasks,
ListTask: tt.fields.ListTask, Task: tt.fields.Task,
} }
allowed, _ := bt.CanUpdate(tt.fields.User) allowed, _ := bt.CanUpdate(tt.fields.User)
if !allowed != tt.wantForbidden { if !allowed != tt.wantForbidden {

View file

@ -427,48 +427,48 @@ func (err ErrListTitleCannotBeEmpty) HTTPError() web.HTTPError {
// List task errors // List task errors
// ================ // ================
// ErrListTaskCannotBeEmpty represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist. // ErrTaskCannotBeEmpty represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
type ErrListTaskCannotBeEmpty struct{} type ErrTaskCannotBeEmpty struct{}
// IsErrListTaskCannotBeEmpty checks if an error is a ErrListDoesNotExist. // IsErrTaskCannotBeEmpty checks if an error is a ErrListDoesNotExist.
func IsErrListTaskCannotBeEmpty(err error) bool { func IsErrTaskCannotBeEmpty(err error) bool {
_, ok := err.(ErrListTaskCannotBeEmpty) _, ok := err.(ErrTaskCannotBeEmpty)
return ok return ok
} }
func (err ErrListTaskCannotBeEmpty) Error() string { func (err ErrTaskCannotBeEmpty) Error() string {
return fmt.Sprintf("List task text cannot be empty.") return fmt.Sprintf("List task text cannot be empty.")
} }
// ErrCodeListTaskCannotBeEmpty holds the unique world-error code of this error // ErrCodeTaskCannotBeEmpty holds the unique world-error code of this error
const ErrCodeListTaskCannotBeEmpty = 4001 const ErrCodeTaskCannotBeEmpty = 4001
// HTTPError holds the http error description // HTTPError holds the http error description
func (err ErrListTaskCannotBeEmpty) HTTPError() web.HTTPError { func (err ErrTaskCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTaskCannotBeEmpty, Message: "You must provide at least a list task text."} return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTaskCannotBeEmpty, Message: "You must provide at least a list task text."}
} }
// ErrListTaskDoesNotExist represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist. // ErrTaskDoesNotExist represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
type ErrListTaskDoesNotExist struct { type ErrTaskDoesNotExist struct {
ID int64 ID int64
} }
// IsErrListTaskDoesNotExist checks if an error is a ErrListDoesNotExist. // IsErrTaskDoesNotExist checks if an error is a ErrListDoesNotExist.
func IsErrListTaskDoesNotExist(err error) bool { func IsErrTaskDoesNotExist(err error) bool {
_, ok := err.(ErrListTaskDoesNotExist) _, ok := err.(ErrTaskDoesNotExist)
return ok return ok
} }
func (err ErrListTaskDoesNotExist) Error() string { func (err ErrTaskDoesNotExist) Error() string {
return fmt.Sprintf("List task does not exist. [ID: %d]", err.ID) return fmt.Sprintf("List task does not exist. [ID: %d]", err.ID)
} }
// ErrCodeListTaskDoesNotExist holds the unique world-error code of this error // ErrCodeTaskDoesNotExist holds the unique world-error code of this error
const ErrCodeListTaskDoesNotExist = 4002 const ErrCodeTaskDoesNotExist = 4002
// HTTPError holds the http error description // HTTPError holds the http error description
func (err ErrListTaskDoesNotExist) HTTPError() web.HTTPError { func (err ErrTaskDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListTaskDoesNotExist, Message: "This list task does not exist"} return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTaskDoesNotExist, Message: "This list task does not exist"}
} }
// ErrBulkTasksMustBeInSameList represents a "ErrBulkTasksMustBeInSameList" kind of error. // ErrBulkTasksMustBeInSameList represents a "ErrBulkTasksMustBeInSameList" kind of error.

View file

@ -152,3 +152,11 @@
namespace_id: 14 namespace_id: 14
updated: 0 updated: 0
created: 0 created: 0
-
id: 20
title: Test20
description: Lorem Ipsum
owner_id: 13
namespace_id: 15
updated: 0
created: 0

View file

@ -70,3 +70,9 @@
owner_id: 7 owner_id: 7
updated: 0 updated: 0
created: 0 created: 0
- id: 15
name: testnamespace15
description: Lorem Ipsum
owner_id: 13
updated: 0
created: 0

View file

@ -109,7 +109,7 @@ func (lt *LabelTask) Create(a web.Auth) (err error) {
// @Router /tasks/{task}/labels [get] // @Router /tasks/{task}/labels [get]
func (lt *LabelTask) ReadAll(search string, a web.Auth, page int) (labels interface{}, err error) { func (lt *LabelTask) ReadAll(search string, a web.Auth, page int) (labels interface{}, err error) {
// Check if the user has the right to see the task // Check if the user has the right to see the task
task := ListTask{ID: lt.TaskID} task := Task{ID: lt.TaskID}
canRead, err := task.CanRead(a) canRead, err := task.CanRead(a)
if err != nil { if err != nil {
return nil, err return nil, err
@ -193,7 +193,7 @@ func getLabelsByTaskIDs(opts *LabelByTaskIDsOptions) (ls []*labelWithTaskID, err
} }
// Create or update a bunch of task labels // Create or update a bunch of task labels
func (t *ListTask) updateTaskLabels(creator web.Auth, labels []*Label) (err error) { func (t *Task) updateTaskLabels(creator web.Auth, labels []*Label) (err error) {
// If we don't have any new labels, delete everything right away. Saves us some hassle. // If we don't have any new labels, delete everything right away. Saves us some hassle.
if len(labels) == 0 && len(t.Labels) > 0 { if len(labels) == 0 && len(t.Labels) > 0 {

View file

@ -76,7 +76,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
a: &User{ID: 1}, a: &User{ID: 1},
}, },
wantErr: true, wantErr: true,
errType: IsErrListTaskDoesNotExist, errType: IsErrTaskDoesNotExist,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -168,7 +168,7 @@ func TestLabelTask_Create(t *testing.T) {
}, },
wantForbidden: true, wantForbidden: true,
wantErr: true, wantErr: true,
errType: IsErrListTaskDoesNotExist, errType: IsErrTaskDoesNotExist,
}, },
} }
for _, tt := range tests { for _, tt := range tests {

View file

@ -35,7 +35,7 @@ type List struct {
// The user who created this list. // The user who created this list.
Owner *User `xorm:"-" json:"owner" valid:"-"` Owner *User `xorm:"-" json:"owner" valid:"-"`
// An array of tasks which belong to the list. // An array of tasks which belong to the list.
Tasks []*ListTask `xorm:"-" json:"tasks"` Tasks []*Task `xorm:"-" json:"tasks"`
// A unix timestamp when this list was created. You cannot change this value. // A unix timestamp when this list was created. You cannot change this value.
Created int64 `xorm:"created not null" json:"created"` Created int64 `xorm:"created not null" json:"created"`
@ -206,7 +206,7 @@ func AddListDetails(lists []*List) (err error) {
} }
// Get all tasks // Get all tasks
ts := []*ListTask{} ts := []*Task{}
err = x.In("list_id", listIDs).Find(&ts) err = x.In("list_id", listIDs).Find(&ts)
if err != nil { if err != nil {
return return
@ -354,6 +354,6 @@ func (l *List) Delete() (err error) {
metrics.UpdateCount(-1, metrics.ListCountKey) metrics.UpdateCount(-1, metrics.ListCountKey)
// Delete all todotasks on that list // Delete all todotasks on that list
_, err = x.Where("list_id = ?", l.ID).Delete(&ListTask{}) _, err = x.Where("list_id = ?", l.ID).Delete(&Task{})
return return
} }

View file

@ -130,6 +130,9 @@ func (l *List) checkRight(a web.Auth, rights ...Right) (bool, error) {
)) ))
} }
// If the user is the owner of a namespace, it has any right, all the time
conds = append(conds, builder.Eq{"n.owner_id": a.GetID()})
exists, err := x.Select("l.*"). exists, err := x.Select("l.*").
Table("list"). Table("list").
Alias("l"). Alias("l").

View file

@ -36,7 +36,7 @@ func GetTables() []interface{} {
return []interface{}{ return []interface{}{
&User{}, &User{},
&List{}, &List{},
&ListTask{}, &Task{},
&Team{}, &Team{},
&TeamMember{}, &TeamMember{},
&TeamList{}, &TeamList{},
@ -44,7 +44,7 @@ func GetTables() []interface{} {
&Namespace{}, &Namespace{},
&ListUser{}, &ListUser{},
&NamespaceUser{}, &NamespaceUser{},
&ListTaskAssginee{}, &TaskAssginee{},
&Label{}, &Label{},
&LabelTask{}, &LabelTask{},
&TaskReminder{}, &TaskReminder{},

View file

@ -330,7 +330,7 @@ func (n *Namespace) Delete() (err error) {
} }
// Delete tasks // Delete tasks
_, err = x.In("list_id", listIDs).Delete(&ListTask{}) _, err = x.In("list_id", listIDs).Delete(&Task{})
if err != nil { if err != nil {
return return
} }

View file

@ -20,8 +20,8 @@ import (
"code.vikunja.io/web" "code.vikunja.io/web"
) )
// ListTaskAssginee represents an assignment of a user to a task // TaskAssginee represents an assignment of a user to a task
type ListTaskAssginee struct { type TaskAssginee struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"-"` ID int64 `xorm:"int(11) autoincr not null unique pk" json:"-"`
TaskID int64 `xorm:"int(11) INDEX not null" json:"-" param:"listtask"` TaskID int64 `xorm:"int(11) INDEX not null" json:"-" param:"listtask"`
UserID int64 `xorm:"int(11) INDEX not null" json:"user_id" param:"user"` UserID int64 `xorm:"int(11) INDEX not null" json:"user_id" param:"user"`
@ -32,18 +32,18 @@ type ListTaskAssginee struct {
} }
// TableName makes a pretty table name // TableName makes a pretty table name
func (ListTaskAssginee) TableName() string { func (TaskAssginee) TableName() string {
return "task_assignees" return "task_assignees"
} }
// ListTaskAssigneeWithUser is a helper type to deal with user joins // TaskAssigneeWithUser is a helper type to deal with user joins
type ListTaskAssigneeWithUser struct { type TaskAssigneeWithUser struct {
TaskID int64 TaskID int64
User `xorm:"extends"` User `xorm:"extends"`
} }
func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*ListTaskAssigneeWithUser, err error) { func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*TaskAssigneeWithUser, err error) {
taskAssignees = []*ListTaskAssigneeWithUser{nil} taskAssignees = []*TaskAssigneeWithUser{nil}
err = x.Table("task_assignees"). err = x.Table("task_assignees").
Select("task_id, users.*"). Select("task_id, users.*").
In("task_id", taskIDs). In("task_id", taskIDs).
@ -53,12 +53,12 @@ func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*ListTaskAssi
} }
// Create or update a bunch of task assignees // Create or update a bunch of task assignees
func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) { func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
// If we don't have any new assignees, delete everything right away. Saves us some hassle. // If we don't have any new assignees, delete everything right away. Saves us some hassle.
if len(assignees) == 0 && len(t.Assignees) > 0 { if len(assignees) == 0 && len(t.Assignees) > 0 {
_, err = x.Where("task_id = ?", t.ID). _, err = x.Where("task_id = ?", t.ID).
Delete(ListTaskAssginee{}) Delete(TaskAssginee{})
t.setTaskAssignees(assignees) t.setTaskAssignees(assignees)
return err return err
} }
@ -96,7 +96,7 @@ func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
if len(assigneesToDelete) > 0 { if len(assigneesToDelete) > 0 {
_, err = x.In("user_id", assigneesToDelete). _, err = x.In("user_id", assigneesToDelete).
And("task_id = ?", t.ID). And("task_id = ?", t.ID).
Delete(ListTaskAssginee{}) Delete(TaskAssginee{})
if err != nil { if err != nil {
return err return err
} }
@ -131,7 +131,7 @@ func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
} }
// Small helper functions to set the new assignees in various places // Small helper functions to set the new assignees in various places
func (t *ListTask) setTaskAssignees(assignees []*User) { func (t *Task) setTaskAssignees(assignees []*User) {
if len(assignees) == 0 { if len(assignees) == 0 {
t.Assignees = nil t.Assignees = nil
return return
@ -152,8 +152,8 @@ func (t *ListTask) setTaskAssignees(assignees []*User) {
// @Failure 403 {object} code.vikunja.io/web.HTTPError "Not allowed to delete the assignee." // @Failure 403 {object} code.vikunja.io/web.HTTPError "Not allowed to delete the assignee."
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{taskID}/assignees/{userID} [delete] // @Router /tasks/{taskID}/assignees/{userID} [delete]
func (la *ListTaskAssginee) Delete() (err error) { func (la *TaskAssginee) Delete() (err error) {
_, err = x.Delete(&ListTaskAssginee{TaskID: la.TaskID, UserID: la.UserID}) _, err = x.Delete(&TaskAssginee{TaskID: la.TaskID, UserID: la.UserID})
if err != nil { if err != nil {
return err return err
} }
@ -169,13 +169,13 @@ func (la *ListTaskAssginee) Delete() (err error) {
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param assignee body models.ListTaskAssginee true "The assingee object" // @Param assignee body models.TaskAssginee true "The assingee object"
// @Param taskID path int true "Task ID" // @Param taskID path int true "Task ID"
// @Success 200 {object} models.ListTaskAssginee "The created assingee object." // @Success 200 {object} models.TaskAssginee "The created assingee object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided." // @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{taskID}/assignees [put] // @Router /tasks/{taskID}/assignees [put]
func (la *ListTaskAssginee) Create(a web.Auth) (err error) { func (la *TaskAssginee) Create(a web.Auth) (err error) {
// Get the list to perform later checks // Get the list to perform later checks
list, err := GetListSimplByTaskID(la.TaskID) list, err := GetListSimplByTaskID(la.TaskID)
@ -183,11 +183,11 @@ func (la *ListTaskAssginee) Create(a web.Auth) (err error) {
return return
} }
task := &ListTask{ID: la.TaskID} task := &Task{ID: la.TaskID}
return task.addNewAssigneeByID(la.UserID, list) return task.addNewAssigneeByID(la.UserID, list)
} }
func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) { func (t *Task) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) {
// Check if the user exists and has access to the list // Check if the user exists and has access to the list
newAssignee, err := GetUserByID(newAssigneeID) newAssignee, err := GetUserByID(newAssigneeID)
if err != nil { if err != nil {
@ -201,7 +201,7 @@ func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err erro
return ErrUserDoesNotHaveAccessToList{list.ID, newAssigneeID} return ErrUserDoesNotHaveAccessToList{list.ID, newAssigneeID}
} }
_, err = x.Insert(ListTaskAssginee{ _, err = x.Insert(TaskAssginee{
TaskID: t.ID, TaskID: t.ID,
UserID: newAssigneeID, UserID: newAssigneeID,
}) })
@ -225,7 +225,7 @@ func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err erro
// @Success 200 {array} models.User "The assignees" // @Success 200 {array} models.User "The assignees"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /labels [get] // @Router /labels [get]
func (la *ListTaskAssginee) ReadAll(search string, a web.Auth, page int) (interface{}, error) { func (la *TaskAssginee) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
var taskAssignees []*User var taskAssignees []*User
err := x.Table("task_assignees"). err := x.Table("task_assignees").
Select("users.*"). Select("users.*").
@ -255,7 +255,7 @@ type BulkAssignees struct {
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param assignee body models.BulkAssignees true "The array of assignees" // @Param assignee body models.BulkAssignees true "The array of assignees"
// @Param taskID path int true "Task ID" // @Param taskID path int true "Task ID"
// @Success 200 {object} models.ListTaskAssginee "The created assingees object." // @Success 200 {object} models.TaskAssginee "The created assingees object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided." // @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{taskID}/assignees/bulk [post] // @Router /tasks/{taskID}/assignees/bulk [post]

View file

@ -21,21 +21,21 @@ import (
) )
// CanCreate checks if a user can add a new assignee // CanCreate checks if a user can add a new assignee
func (la *ListTaskAssginee) CanCreate(a web.Auth) (bool, error) { func (la *TaskAssginee) CanCreate(a web.Auth) (bool, error) {
return canDoListTaskAssingee(la.TaskID, a) return canDoTaskAssingee(la.TaskID, a)
} }
// CanCreate checks if a user can add a new assignee // CanCreate checks if a user can add a new assignee
func (ba *BulkAssignees) CanCreate(a web.Auth) (bool, error) { func (ba *BulkAssignees) CanCreate(a web.Auth) (bool, error) {
return canDoListTaskAssingee(ba.TaskID, a) return canDoTaskAssingee(ba.TaskID, a)
} }
// CanDelete checks if a user can delete an assignee // CanDelete checks if a user can delete an assignee
func (la *ListTaskAssginee) CanDelete(a web.Auth) (bool, error) { func (la *TaskAssginee) CanDelete(a web.Auth) (bool, error) {
return canDoListTaskAssingee(la.TaskID, a) return canDoTaskAssingee(la.TaskID, a)
} }
func canDoListTaskAssingee(taskID int64, a web.Auth) (bool, error) { func canDoTaskAssingee(taskID int64, a web.Auth) (bool, error) {
// Check if the current user can edit the list // Check if the current user can edit the list
list, err := GetListSimplByTaskID(taskID) list, err := GetListSimplByTaskID(taskID)
if err != nil { if err != nil {

View file

@ -15,7 +15,7 @@ import (
"code.vikunja.io/web" "code.vikunja.io/web"
) )
func sortTasksForTesting(by SortBy) (tasks []*ListTask) { func sortTasksForTesting(by SortBy) (tasks []*Task) {
user1 := &User{ user1 := &User{
ID: 1, ID: 1,
Username: "user1", Username: "user1",
@ -37,7 +37,7 @@ func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed", // hash for "" AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed", // hash for ""
} }
tasks = []*ListTask{ tasks = []*Task{
{ {
ID: 1, ID: 1,
Text: "task #1", Text: "task #1",
@ -341,7 +341,7 @@ func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
return return
} }
func TestListTask_ReadAll(t *testing.T) { func TestTask_ReadAll(t *testing.T) {
assert.NoError(t, LoadFixtures()) assert.NoError(t, LoadFixtures())
// Dummy users // Dummy users
@ -368,7 +368,7 @@ func TestListTask_ReadAll(t *testing.T) {
Sorting string Sorting string
StartDateSortUnix int64 StartDateSortUnix int64
EndDateSortUnix int64 EndDateSortUnix int64
Subtasks []*ListTask Subtasks []*Task
Created int64 Created int64
Updated int64 Updated int64
CreatedBy *User CreatedBy *User
@ -388,7 +388,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr bool wantErr bool
}{ }{
{ {
name: "ReadAll ListTasks normally", name: "ReadAll Tasks normally",
fields: fields{}, fields: fields{},
args: args{ args: args{
search: "", search: "",
@ -399,7 +399,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by priority (desc)", name: "ReadAll Tasks sorted by priority (desc)",
fields: fields{ fields: fields{
Sorting: "priority", Sorting: "priority",
}, },
@ -412,7 +412,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by priority asc", name: "ReadAll Tasks sorted by priority asc",
fields: fields{ fields: fields{
Sorting: "priorityasc", Sorting: "priorityasc",
}, },
@ -425,7 +425,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by priority desc", name: "ReadAll Tasks sorted by priority desc",
fields: fields{ fields: fields{
Sorting: "prioritydesc", Sorting: "prioritydesc",
}, },
@ -438,7 +438,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by due date default desc", name: "ReadAll Tasks sorted by due date default desc",
fields: fields{ fields: fields{
Sorting: "duedate", Sorting: "duedate",
}, },
@ -451,7 +451,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by due date asc", name: "ReadAll Tasks sorted by due date asc",
fields: fields{ fields: fields{
Sorting: "duedateasc", Sorting: "duedateasc",
}, },
@ -464,7 +464,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks sorted by due date desc", name: "ReadAll Tasks sorted by due date desc",
fields: fields{ fields: fields{
Sorting: "duedatedesc", Sorting: "duedatedesc",
}, },
@ -478,7 +478,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks with range", name: "ReadAll Tasks with range",
fields: fields{ fields: fields{
StartDateSortUnix: 1544500000, StartDateSortUnix: 1544500000,
EndDateSortUnix: 1544600000, EndDateSortUnix: 1544600000,
@ -488,7 +488,7 @@ func TestListTask_ReadAll(t *testing.T) {
a: &User{ID: 1}, a: &User{ID: 1},
page: 0, page: 0,
}, },
want: []*ListTask{ want: []*Task{
{ {
ID: 7, ID: 7,
Text: "task #7 with start date", Text: "task #7 with start date",
@ -514,7 +514,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks with range", name: "ReadAll Tasks with range",
fields: fields{ fields: fields{
StartDateSortUnix: 1544700000, StartDateSortUnix: 1544700000,
EndDateSortUnix: 1545000000, EndDateSortUnix: 1545000000,
@ -524,7 +524,7 @@ func TestListTask_ReadAll(t *testing.T) {
a: &User{ID: 1}, a: &User{ID: 1},
page: 0, page: 0,
}, },
want: []*ListTask{ want: []*Task{
{ {
ID: 8, ID: 8,
Text: "task #8 with end date", Text: "task #8 with end date",
@ -550,7 +550,7 @@ func TestListTask_ReadAll(t *testing.T) {
wantErr: false, wantErr: false,
}, },
{ {
name: "ReadAll ListTasks with range without end date", name: "ReadAll Tasks with range without end date",
fields: fields{ fields: fields{
StartDateSortUnix: 1544700000, StartDateSortUnix: 1544700000,
}, },
@ -559,7 +559,7 @@ func TestListTask_ReadAll(t *testing.T) {
a: &User{ID: 1}, a: &User{ID: 1},
page: 0, page: 0,
}, },
want: []*ListTask{ want: []*Task{
{ {
ID: 8, ID: 8,
Text: "task #8 with end date", Text: "task #8 with end date",
@ -587,7 +587,7 @@ func TestListTask_ReadAll(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
lt := &ListTask{ lt := &Task{
ID: tt.fields.ID, ID: tt.fields.ID,
Text: tt.fields.Text, Text: tt.fields.Text,
Description: tt.fields.Description, Description: tt.fields.Description,
@ -611,7 +611,7 @@ func TestListTask_ReadAll(t *testing.T) {
} }
got, err := lt.ReadAll(tt.args.search, tt.args.a, tt.args.page) got, err := lt.ReadAll(tt.args.search, tt.args.a, tt.args.page)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("Test %s, ListTask.ReadAll() error = %v, wantErr %v", tt.name, err, tt.wantErr) t.Errorf("Test %s, Task.ReadAll() error = %v, wantErr %v", tt.name, err, tt.wantErr)
return return
} }
if diff, equal := messagediff.PrettyDiff(got, tt.want); !equal { if diff, equal := messagediff.PrettyDiff(got, tt.want); !equal {

View file

@ -25,8 +25,8 @@ import (
"time" "time"
) )
// ListTask represents an task in a todolist // Task represents an task in a todolist
type ListTask struct { type Task struct {
// The unique, numeric id of this task. // The unique, numeric id of this task.
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"` ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"`
// The task text. This is what you'll see in the list. // The task text. This is what you'll see in the list.
@ -69,7 +69,7 @@ type ListTask struct {
EndDateSortUnix int64 `xorm:"-" json:"-" query:"enddate"` EndDateSortUnix int64 `xorm:"-" json:"-" query:"enddate"`
// An array of subtasks. // An array of subtasks.
Subtasks []*ListTask `xorm:"-" json:"subtasks"` Subtasks []*Task `xorm:"-" json:"subtasks"`
// A unix timestamp when this task was created. You cannot change this value. // A unix timestamp when this task was created. You cannot change this value.
Created int64 `xorm:"created not null" json:"created"` Created int64 `xorm:"created not null" json:"created"`
@ -84,7 +84,7 @@ type ListTask struct {
} }
// TableName returns the table name for listtasks // TableName returns the table name for listtasks
func (ListTask) TableName() string { func (Task) TableName() string {
return "tasks" return "tasks"
} }
@ -125,10 +125,10 @@ const (
// @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time." // @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time."
// @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time." // @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time."
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Success 200 {array} models.ListTask "The tasks" // @Success 200 {array} models.Task "The tasks"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/all [get] // @Router /tasks/all [get]
func (t *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, error) { func (t *Task) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
var sortby SortBy var sortby SortBy
switch t.Sorting { switch t.Sorting {
case "priority": case "priority":
@ -151,7 +151,7 @@ func (t *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, er
} }
//GetTasksByUser returns all tasks for a user //GetTasksByUser returns all tasks for a user
func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) ([]*ListTask, error) { func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) ([]*Task, error) {
// Get all lists // Get all lists
lists, err := getRawListsForUser("", u, page) lists, err := getRawListsForUser("", u, page)
if err != nil { if err != nil {
@ -176,7 +176,7 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
orderby = "due_date_unix asc" orderby = "due_date_unix asc"
} }
taskMap := make(map[int64]*ListTask) taskMap := make(map[int64]*Task)
// Then return all tasks for that lists // Then return all tasks for that lists
if startDate.Unix() != 0 || endDate.Unix() != 0 { if startDate.Unix() != 0 || endDate.Unix() != 0 {
@ -222,7 +222,7 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
return tasks, err return tasks, err
} }
func sortTasks(tasks []*ListTask, by SortBy) { func sortTasks(tasks []*Task, by SortBy) {
switch by { switch by {
case SortTasksByPriorityDesc: case SortTasksByPriorityDesc:
sort.Slice(tasks, func(i, j int) bool { sort.Slice(tasks, func(i, j int) bool {
@ -244,9 +244,9 @@ func sortTasks(tasks []*ListTask, by SortBy) {
} }
// GetTasksByListID gets all todotasks for a list // GetTasksByListID gets all todotasks for a list
func GetTasksByListID(listID int64) (tasks []*ListTask, err error) { func GetTasksByListID(listID int64) (tasks []*Task, err error) {
// make a map so we can put in a lot of other stuff more easily // make a map so we can put in a lot of other stuff more easily
taskMap := make(map[int64]*ListTask, len(tasks)) taskMap := make(map[int64]*Task, len(tasks))
err = x.Where("list_id = ?", listID).Find(&taskMap) err = x.Where("list_id = ?", listID).Find(&taskMap)
if err != nil { if err != nil {
return return
@ -257,30 +257,30 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
} }
// GetTaskByIDSimple returns a raw task without extra data by the task ID // GetTaskByIDSimple returns a raw task without extra data by the task ID
func GetTaskByIDSimple(taskID int64) (task ListTask, err error) { func GetTaskByIDSimple(taskID int64) (task Task, err error) {
if taskID < 1 { if taskID < 1 {
return ListTask{}, ErrListTaskDoesNotExist{taskID} return Task{}, ErrTaskDoesNotExist{taskID}
} }
return GetTaskSimple(&ListTask{ID: taskID}) return GetTaskSimple(&Task{ID: taskID})
} }
// GetTaskSimple returns a raw task without extra data // GetTaskSimple returns a raw task without extra data
func GetTaskSimple(t *ListTask) (task ListTask, err error) { func GetTaskSimple(t *Task) (task Task, err error) {
task = *t task = *t
exists, err := x.Get(&task) exists, err := x.Get(&task)
if err != nil { if err != nil {
return ListTask{}, err return Task{}, err
} }
if !exists { if !exists {
return ListTask{}, ErrListTaskDoesNotExist{t.ID} return Task{}, ErrTaskDoesNotExist{t.ID}
} }
return return
} }
// GetTaskByID returns all tasks a list has // GetTaskByID returns all tasks a list has
func GetTaskByID(listTaskID int64) (listTask ListTask, err error) { func GetTaskByID(listTaskID int64) (listTask Task, err error) {
listTask, err = GetTaskByIDSimple(listTaskID) listTask, err = GetTaskByIDSimple(listTaskID)
if err != nil { if err != nil {
return return
@ -321,11 +321,11 @@ func GetTaskByID(listTaskID int64) (listTask ListTask, err error) {
func (bt *BulkTask) GetTasksByIDs() (err error) { func (bt *BulkTask) GetTasksByIDs() (err error) {
for _, id := range bt.IDs { for _, id := range bt.IDs {
if id < 1 { if id < 1 {
return ErrListTaskDoesNotExist{id} return ErrTaskDoesNotExist{id}
} }
} }
taskMap := make(map[int64]*ListTask, len(bt.Tasks)) taskMap := make(map[int64]*Task, len(bt.Tasks))
err = x.In("id", bt.IDs).Find(&taskMap) err = x.In("id", bt.IDs).Find(&taskMap)
if err != nil { if err != nil {
return return
@ -336,8 +336,8 @@ func (bt *BulkTask) GetTasksByIDs() (err error) {
} }
// GetTasksByUIDs gets all tasks from a bunch of uids // GetTasksByUIDs gets all tasks from a bunch of uids
func GetTasksByUIDs(uids []string) (tasks []*ListTask, err error) { func GetTasksByUIDs(uids []string) (tasks []*Task, err error) {
taskMap := make(map[int64]*ListTask) taskMap := make(map[int64]*Task)
err = x.In("uid", uids).Find(&taskMap) err = x.In("uid", uids).Find(&taskMap)
if err != nil { if err != nil {
return return
@ -349,7 +349,7 @@ func GetTasksByUIDs(uids []string) (tasks []*ListTask, err error) {
// This function takes a map with pointers and returns a slice with pointers to tasks // 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 // It adds more stuff like assignees/labels/etc to a bunch of tasks
func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err error) { func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
// No need to iterate over users and stuff if the list doesn't has tasks // No need to iterate over users and stuff if the list doesn't has tasks
if len(taskMap) == 0 { if len(taskMap) == 0 {
@ -430,7 +430,7 @@ func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err err
} }
// make a complete slice from the map // make a complete slice from the map
tasks = []*ListTask{} tasks = []*Task{}
for _, t := range taskMap { for _, t := range taskMap {
tasks = append(tasks, t) tasks = append(tasks, t)
} }
@ -453,19 +453,19 @@ func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err err
// @Produce json // @Produce json
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param id path int true "List ID" // @Param id path int true "List ID"
// @Param task body models.ListTask true "The task object" // @Param task body models.Task true "The task object"
// @Success 200 {object} models.ListTask "The created task object." // @Success 200 {object} models.Task "The created task object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided." // @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list" // @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /lists/{id} [put] // @Router /lists/{id} [put]
func (t *ListTask) Create(a web.Auth) (err error) { func (t *Task) Create(a web.Auth) (err error) {
t.ID = 0 t.ID = 0
// Check if we have at least a text // Check if we have at least a text
if t.Text == "" { if t.Text == "" {
return ErrListTaskCannotBeEmpty{} return ErrTaskCannotBeEmpty{}
} }
// Check if the list exists // Check if the list exists
@ -514,13 +514,13 @@ func (t *ListTask) Create(a web.Auth) (err error) {
// @Produce json // @Produce json
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param id path int true "Task ID" // @Param id path int true "Task ID"
// @Param task body models.ListTask true "The task object" // @Param task body models.Task true "The task object"
// @Success 200 {object} models.ListTask "The updated task object." // @Success 200 {object} models.Task "The updated task object."
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided." // @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)" // @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{id} [post] // @Router /tasks/{id} [post]
func (t *ListTask) Update() (err error) { func (t *Task) Update() (err error) {
// Check if the task exists // Check if the task exists
ot, err := GetTaskByID(t.ID) ot, err := GetTaskByID(t.ID)
if err != nil { if err != nil {
@ -634,7 +634,7 @@ func (t *ListTask) Update() (err error) {
// This helper function updates the reminders and doneAtUnix of the *old* task (since that's the one we're inserting // This helper function updates the reminders and doneAtUnix of the *old* task (since that's the one we're inserting
// with updated values into the db) // with updated values into the db)
func updateDone(oldTask *ListTask, newTask *ListTask) { func updateDone(oldTask *Task, newTask *Task) {
if !oldTask.Done && newTask.Done && oldTask.RepeatAfter > 0 { if !oldTask.Done && newTask.Done && oldTask.RepeatAfter > 0 {
oldTask.DueDateUnix = oldTask.DueDateUnix + oldTask.RepeatAfter // assuming we'll save the old task (merged) oldTask.DueDateUnix = oldTask.DueDateUnix + oldTask.RepeatAfter // assuming we'll save the old task (merged)
@ -657,7 +657,7 @@ func updateDone(oldTask *ListTask, newTask *ListTask) {
// Creates or deletes all necessary remindes without unneded db operations. // Creates or deletes all necessary remindes without unneded db operations.
// The parameter is a slice with unix dates which holds the new reminders. // The parameter is a slice with unix dates which holds the new reminders.
func (t *ListTask) updateReminders(reminders []int64) (err error) { func (t *Task) updateReminders(reminders []int64) (err error) {
// If we're removing everything, delete all reminders right away // If we're removing everything, delete all reminders right away
if len(reminders) == 0 && len(t.RemindersUnix) > 0 { if len(reminders) == 0 && len(t.RemindersUnix) > 0 {
@ -701,7 +701,7 @@ func (t *ListTask) updateReminders(reminders []int64) (err error) {
if len(remindersToDelete) > 0 { if len(remindersToDelete) > 0 {
_, err = x.In("reminder_unix", remindersToDelete). _, err = x.In("reminder_unix", remindersToDelete).
And("task_id = ?", t.ID). And("task_id = ?", t.ID).
Delete(ListTaskAssginee{}) Delete(TaskAssginee{})
if err != nil { if err != nil {
return err return err
} }
@ -743,7 +743,7 @@ func (t *ListTask) updateReminders(reminders []int64) (err error) {
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list" // @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{id} [delete] // @Router /tasks/{id} [delete]
func (t *ListTask) Delete() (err error) { func (t *Task) Delete() (err error) {
// Check if it exists // Check if it exists
_, err = GetTaskByID(t.ID) _, err = GetTaskByID(t.ID)
@ -751,12 +751,12 @@ func (t *ListTask) Delete() (err error) {
return return
} }
if _, err = x.ID(t.ID).Delete(ListTask{}); err != nil { if _, err = x.ID(t.ID).Delete(Task{}); err != nil {
return err return err
} }
// Delete assignees // Delete assignees
if _, err = x.Where("task_id = ?", t.ID).Delete(ListTaskAssginee{}); err != nil { if _, err = x.Where("task_id = ?", t.ID).Delete(TaskAssginee{}); err != nil {
return err return err
} }

View file

@ -21,25 +21,25 @@ import (
) )
// CanDelete checks if the user can delete an task // CanDelete checks if the user can delete an task
func (t *ListTask) CanDelete(a web.Auth) (bool, error) { func (t *Task) CanDelete(a web.Auth) (bool, error) {
return t.canDoListTask(a) return t.canDoTask(a)
} }
// CanUpdate determines if a user has the right to update a list task // CanUpdate determines if a user has the right to update a list task
func (t *ListTask) CanUpdate(a web.Auth) (bool, error) { func (t *Task) CanUpdate(a web.Auth) (bool, error) {
return t.canDoListTask(a) return t.canDoTask(a)
} }
// CanCreate determines if a user has the right to create a list task // CanCreate determines if a user has the right to create a list task
func (t *ListTask) CanCreate(a web.Auth) (bool, error) { func (t *Task) CanCreate(a web.Auth) (bool, error) {
// A user can do a task if he has write acces to its list // A user can do a task if he has write acces to its list
l := &List{ID: t.ListID} l := &List{ID: t.ListID}
return l.CanWrite(a) return l.CanWrite(a)
} }
// CanRead determines if a user can read a task // CanRead determines if a user can read a task
func (t *ListTask) CanRead(a web.Auth) (canRead bool, err error) { func (t *Task) CanRead(a web.Auth) (canRead bool, err error) {
//return t.canDoListTask(a) //return t.canDoTask(a)
// Get the task, error out if it doesn't exist // Get the task, error out if it doesn't exist
*t, err = GetTaskByIDSimple(t.ID) *t, err = GetTaskByIDSimple(t.ID)
if err != nil { if err != nil {
@ -52,7 +52,7 @@ func (t *ListTask) CanRead(a web.Auth) (canRead bool, err error) {
} }
// Helper function to check if a user can do stuff on a list task // Helper function to check if a user can do stuff on a list task
func (t *ListTask) canDoListTask(a web.Auth) (bool, error) { func (t *Task) canDoTask(a web.Auth) (bool, error) {
// Get the task // Get the task
lI, err := GetTaskByIDSimple(t.ID) lI, err := GetTaskByIDSimple(t.ID)
if err != nil { if err != nil {

View file

@ -21,11 +21,11 @@ import (
"testing" "testing"
) )
func TestListTask_Create(t *testing.T) { func TestTask_Create(t *testing.T) {
//assert.NoError(t, LoadFixtures()) //assert.NoError(t, LoadFixtures())
// Fake list task // Fake list task
listtask := ListTask{ listtask := Task{
Text: "Lorem", Text: "Lorem",
Description: "Lorem Ipsum BACKERY", Description: "Lorem Ipsum BACKERY",
ListID: 1, ListID: 1,
@ -63,13 +63,13 @@ func TestListTask_Create(t *testing.T) {
listtask.ID = 0 listtask.ID = 0
err = listtask.Delete() err = listtask.Delete()
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrListTaskDoesNotExist(err)) assert.True(t, IsErrTaskDoesNotExist(err))
// Try adding a list task with an empty text // Try adding a list task with an empty text
listtask.Text = "" listtask.Text = ""
err = listtask.Create(doer) err = listtask.Create(doer)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrListTaskCannotBeEmpty(err)) assert.True(t, IsErrTaskCannotBeEmpty(err))
// Try adding one to a nonexistant list // Try adding one to a nonexistant list
listtask.ListID = 99993939 listtask.ListID = 99993939
@ -82,7 +82,7 @@ func TestListTask_Create(t *testing.T) {
listtask.ID = 94829352 listtask.ID = 94829352
err = listtask.Update() err = listtask.Update()
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrListTaskDoesNotExist(err)) assert.True(t, IsErrTaskDoesNotExist(err))
// Try inserting an task with a nonexistant user // Try inserting an task with a nonexistant user
nUser := &User{ID: 9482385} nUser := &User{ID: 9482385}
@ -94,14 +94,14 @@ func TestListTask_Create(t *testing.T) {
func TestUpdateDone(t *testing.T) { func TestUpdateDone(t *testing.T) {
t.Run("marking a task as done", func(t *testing.T) { t.Run("marking a task as done", func(t *testing.T) {
oldTask := &ListTask{Done: false} oldTask := &Task{Done: false}
newTask := &ListTask{Done: true} newTask := &Task{Done: true}
updateDone(oldTask, newTask) updateDone(oldTask, newTask)
assert.NotEqual(t, int64(0), oldTask.DoneAtUnix) assert.NotEqual(t, int64(0), oldTask.DoneAtUnix)
}) })
t.Run("unmarking a task as done", func(t *testing.T) { t.Run("unmarking a task as done", func(t *testing.T) {
oldTask := &ListTask{Done: true} oldTask := &Task{Done: true}
newTask := &ListTask{Done: false} newTask := &Task{Done: false}
updateDone(oldTask, newTask) updateDone(oldTask, newTask)
assert.Equal(t, int64(0), oldTask.DoneAtUnix) assert.Equal(t, int64(0), oldTask.DoneAtUnix)
}) })

View file

@ -100,7 +100,7 @@ func TaskHandler(c echo.Context) error {
storage := &VikunjaCaldavListStorage{ storage := &VikunjaCaldavListStorage{
list: &models.List{ID: listID}, list: &models.List{ID: listID},
task: &models.ListTask{UID: taskUID}, task: &models.Task{UID: taskUID},
user: &u, user: &u,
} }

View file

@ -37,7 +37,7 @@ type VikunjaCaldavListStorage struct {
// Used when handling a list // Used when handling a list
list *models.List list *models.List
// Used when handling a single task, like updating // Used when handling a single task, like updating
task *models.ListTask task *models.Task
// The current user // The current user
user *models.User user *models.User
isPrincipal bool isPrincipal bool
@ -176,7 +176,7 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filter
//return vcls.GetResources(rpath, false) //return vcls.GetResources(rpath, false)
} }
func getTaskURL(task *models.ListTask) string { func getTaskURL(task *models.Task) string {
return ListBasePath + "/" + strconv.FormatInt(task.ListID, 10) + `/` + task.UID + `.ics` return ListBasePath + "/" + strconv.FormatInt(task.ListID, 10) + `/` + task.UID + `.ics`
} }
@ -187,9 +187,9 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
if vcls.task != nil { if vcls.task != nil {
// save and override the updated unix date to not break any later etag checks // save and override the updated unix date to not break any later etag checks
updated := vcls.task.Updated updated := vcls.task.Updated
task, err := models.GetTaskSimple(&models.ListTask{ID: vcls.task.ID, UID: vcls.task.UID}) task, err := models.GetTaskSimple(&models.Task{ID: vcls.task.ID, UID: vcls.task.UID})
if err != nil { if err != nil {
if models.IsErrListTaskDoesNotExist(err) { if models.IsErrTaskDoesNotExist(err) {
return nil, false, errs.ResourceNotFoundError return nil, false, errs.ResourceNotFoundError
} }
return nil, false, err return nil, false, err
@ -316,7 +316,7 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
// VikunjaListResourceAdapter holds the actual resource // VikunjaListResourceAdapter holds the actual resource
type VikunjaListResourceAdapter struct { type VikunjaListResourceAdapter struct {
list *models.List list *models.List
task *models.ListTask task *models.Task
isPrincipal bool isPrincipal bool
isCollection bool isCollection bool
@ -356,7 +356,7 @@ func (vlra *VikunjaListResourceAdapter) GetContent() string {
} }
if vlra.task != nil { if vlra.task != nil {
list := models.List{Tasks: []*models.ListTask{vlra.task}} list := models.List{Tasks: []*models.Task{vlra.task}}
return getCaldavTodosForTasks(&list) return getCaldavTodosForTasks(&list)
} }

View file

@ -59,7 +59,7 @@ func getCaldavTodosForTasks(list *models.List) string {
return caldav.ParseTodos(caldavConfig, caldavtodos) return caldav.ParseTodos(caldavConfig, caldavtodos)
} }
func parseTaskFromVTODO(content string) (vTask *models.ListTask, err error) { func parseTaskFromVTODO(content string) (vTask *models.Task, err error) {
parsed, err := ical.ParseCalendar(content) parsed, err := ical.ParseCalendar(content)
if err != nil { if err != nil {
return nil, err return nil, err
@ -89,7 +89,7 @@ func parseTaskFromVTODO(content string) (vTask *models.ListTask, err error) {
// Parse the enddate // Parse the enddate
duration, _ := time.ParseDuration(task["DURATION"]) duration, _ := time.ParseDuration(task["DURATION"])
vTask = &models.ListTask{ vTask = &models.Task{
UID: task["UID"], UID: task["UID"],
Text: task["SUMMARY"], Text: task["SUMMARY"],
Description: task["DESCRIPTION"], Description: task["DESCRIPTION"],

View file

@ -55,7 +55,7 @@ func setupMetrics(a *echo.Group) {
}, },
{ {
metrics.TaskCountKey, metrics.TaskCountKey,
models.ListTask{}, models.Task{},
}, },
{ {
metrics.TeamCountKey, metrics.TeamCountKey,

View file

@ -196,7 +196,7 @@ func registerAPIRoutes(a *echo.Group) {
taskHandler := &handler.WebHandler{ taskHandler := &handler.WebHandler{
EmptyStruct: func() handler.CObject { EmptyStruct: func() handler.CObject {
return &models.ListTask{} return &models.Task{}
}, },
} }
a.PUT("/lists/:list", taskHandler.CreateWeb) a.PUT("/lists/:list", taskHandler.CreateWeb)
@ -213,7 +213,7 @@ func registerAPIRoutes(a *echo.Group) {
assigneeTaskHandler := &handler.WebHandler{ assigneeTaskHandler := &handler.WebHandler{
EmptyStruct: func() handler.CObject { EmptyStruct: func() handler.CObject {
return &models.ListTaskAssginee{} return &models.TaskAssginee{}
}, },
} }
a.PUT("/tasks/:listtask/assignees", assigneeTaskHandler.CreateWeb) a.PUT("/tasks/:listtask/assignees", assigneeTaskHandler.CreateWeb)

View file

@ -488,7 +488,7 @@ var doc = `{
"required": true, "required": true,
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
} }
], ],
@ -497,7 +497,7 @@ var doc = `{
"description": "The created task object.", "description": "The created task object.",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"400": { "400": {
@ -2393,7 +2393,7 @@ var doc = `{
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
} }
}, },
@ -2442,7 +2442,7 @@ var doc = `{
"description": "The updated task object.", "description": "The updated task object.",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"400": { "400": {
@ -2502,7 +2502,7 @@ var doc = `{
"required": true, "required": true,
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
} }
], ],
@ -2511,7 +2511,7 @@ var doc = `{
"description": "The updated task object.", "description": "The updated task object.",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"400": { "400": {
@ -2618,7 +2618,7 @@ var doc = `{
"required": true, "required": true,
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTaskAssginee" "$ref": "#/definitions/models.TaskAssginee"
} }
}, },
{ {
@ -2634,7 +2634,7 @@ var doc = `{
"description": "The created assingee object.", "description": "The created assingee object.",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTaskAssginee" "$ref": "#/definitions/models.TaskAssginee"
} }
}, },
"400": { "400": {
@ -2696,7 +2696,7 @@ var doc = `{
"description": "The created assingees object.", "description": "The created assingees object.",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.ListTaskAssginee" "$ref": "#/definitions/models.TaskAssginee"
} }
}, },
"400": { "400": {
@ -3803,7 +3803,7 @@ var doc = `{
"description": "An array of subtasks.", "description": "An array of subtasks.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"task_ids": { "task_ids": {
@ -3920,7 +3920,7 @@ var doc = `{
"description": "An array of tasks which belong to the list.", "description": "An array of tasks which belong to the list.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"title": { "title": {
@ -3935,7 +3935,7 @@ var doc = `{
} }
} }
}, },
"models.ListTask": { "models.Task": {
"type": "object", "type": "object",
"properties": { "properties": {
"assignees": { "assignees": {
@ -4021,7 +4021,7 @@ var doc = `{
"description": "An array of subtasks.", "description": "An array of subtasks.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/models.ListTask" "$ref": "#/definitions/models.Task"
} }
}, },
"text": { "text": {
@ -4036,7 +4036,7 @@ var doc = `{
} }
} }
}, },
"models.ListTaskAssginee": { "models.TaskAssginee": {
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {