diff --git a/docs/content/doc/usage/errors.md b/docs/content/doc/usage/errors.md index fafe8a371..faf4ef548 100644 --- a/docs/content/doc/usage/errors.md +++ b/docs/content/doc/usage/errors.md @@ -87,6 +87,7 @@ This document describes the different errors Vikunja can return. | 4018 | 400 | Invalid task filter concatinator. | | 4019 | 400 | Invalid task filter value. | | 4020 | 400 | The provided attachment does not belong to that task. | +| 4021 | 400 | This user is already assigned to that task. | ## Namespace diff --git a/pkg/models/error.go b/pkg/models/error.go index 2f9da63e4..580ba0551 100644 --- a/pkg/models/error.go +++ b/pkg/models/error.go @@ -847,6 +847,34 @@ func (err ErrAttachmentDoesNotBelongToTask) HTTPError() web.HTTPError { } } +// ErrUserAlreadyAssigned represents an error where the user is already assigned to this task +type ErrUserAlreadyAssigned struct { + TaskID int64 + UserID int64 +} + +// IsErrUserAlreadyAssigned checks if an error is ErrUserAlreadyAssigned. +func IsErrUserAlreadyAssigned(err error) bool { + _, ok := err.(ErrUserAlreadyAssigned) + return ok +} + +func (err ErrUserAlreadyAssigned) Error() string { + return fmt.Sprintf("User is already assigned to task [TaskID: %d, UserID: %d]", err.TaskID, err.UserID) +} + +// ErrCodeUserAlreadyAssigned holds the unique world-error code of this error +const ErrCodeUserAlreadyAssigned = 4021 + +// HTTPError holds the http error description +func (err ErrUserAlreadyAssigned) HTTPError() web.HTTPError { + return web.HTTPError{ + HTTPCode: http.StatusBadRequest, + Code: ErrCodeUserAlreadyAssigned, + Message: "This user is already assigned to that task.", + } +} + // ================= // Namespace errors // ================= diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index e2b4a5159..d2dc996c7 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -221,6 +221,19 @@ func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *Li return ErrUserDoesNotHaveAccessToList{list.ID, newAssigneeID} } + exist, err := s. + Where("task_id = ? AND user_id = ?", t.ID, newAssigneeID). + Exist(&TaskAssginee{}) + if err != nil { + return err + } + if exist { + return &ErrUserAlreadyAssigned{ + UserID: newAssigneeID, + TaskID: t.ID, + } + } + _, err = s.Insert(TaskAssginee{ TaskID: t.ID, UserID: newAssigneeID,