diff --git a/docs/content/doc/usage/errors.md b/docs/content/doc/usage/errors.md index a704e1e092..fafe8a3715 100644 --- a/docs/content/doc/usage/errors.md +++ b/docs/content/doc/usage/errors.md @@ -82,10 +82,11 @@ This document describes the different errors Vikunja can return. | 4013 | 400 | The task sort param is invalid. | | 4014 | 400 | The task sort order is invalid. | | 4015 | 404 | The task comment does not exist. | -| 4016 | 403 | Invalid task field. | -| 4017 | 403 | Invalid task filter comparator. | -| 4018 | 403 | Invalid task filter concatinator. | -| 4019 | 403 | Invalid task filter value. | +| 4016 | 400 | Invalid task field. | +| 4017 | 400 | Invalid task filter comparator. | +| 4018 | 400 | Invalid task filter concatinator. | +| 4019 | 400 | Invalid task filter value. | +| 4020 | 400 | The provided attachment does not belong to that task. | ## Namespace diff --git a/pkg/models/error.go b/pkg/models/error.go index 2317f7ecd5..2f9da63e43 100644 --- a/pkg/models/error.go +++ b/pkg/models/error.go @@ -819,6 +819,34 @@ func (err ErrInvalidTaskFilterValue) HTTPError() web.HTTPError { } } +// ErrAttachmentDoesNotBelongToTask represents an error where the provided task cover attachment does not belong to the same task +type ErrAttachmentDoesNotBelongToTask struct { + TaskID int64 + AttachmentID int64 +} + +// IsErrAttachmentAndCoverMustBelongToTheSameTask checks if an error is ErrAttachmentDoesNotBelongToTask. +func IsErrAttachmentAndCoverMustBelongToTheSameTask(err error) bool { + _, ok := err.(ErrAttachmentDoesNotBelongToTask) + return ok +} + +func (err ErrAttachmentDoesNotBelongToTask) Error() string { + return fmt.Sprintf("Task attachment and cover image do not belong to the same task [TaskID: %d, AttachmentID: %d]", err.TaskID, err.AttachmentID) +} + +// ErrCodeAttachmentDoesNotBelongToTask holds the unique world-error code of this error +const ErrCodeAttachmentDoesNotBelongToTask = 4020 + +// HTTPError holds the http error description +func (err ErrAttachmentDoesNotBelongToTask) HTTPError() web.HTTPError { + return web.HTTPError{ + HTTPCode: http.StatusBadRequest, + Code: ErrCodeAttachmentDoesNotBelongToTask, + Message: "This attachment does not belong to that task.", + } +} + // ================= // Namespace errors // ================= diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 21e8d3c1a6..a8e41dddd5 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -1042,7 +1042,7 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { "position", "repeat_mode", "kanban_position", - "cover_image_attachment_id", // TODO: check if the attachment belongs to the task + "cover_image_attachment_id", } // If the task is being moved between lists, make sure to move the bucket + index as well @@ -1057,6 +1057,23 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { colsToUpdate = append(colsToUpdate, "index") } + // If a task attachment is being set as cover image, check if the attachment actually belongs to the task + if t.CoverImageAttachmentID != 0 { + is, err := s.Exist(&TaskAttachment{ + TaskID: t.ID, + ID: t.CoverImageAttachmentID, + }) + if err != nil { + return err + } + if !is { + return &ErrAttachmentDoesNotBelongToTask{ + AttachmentID: t.CoverImageAttachmentID, + TaskID: t.ID, + } + } + } + wasFavorite, err := isFavorite(s, t.ID, a, FavoriteKindTask) if err != nil { return