fix: prevent moving a list into a pseudo namespace
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kolaente 2022-08-15 23:25:35 +02:00
parent 8d10130d4c
commit 3ccc6365a6
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
4 changed files with 62 additions and 10 deletions

View File

@ -4,8 +4,8 @@ title: "Errors"
draft: false draft: false
type: "doc" type: "doc"
menu: menu:
sidebar: sidebar:
parent: "usage" parent: "usage"
--- ---
# Errors # Errors
@ -52,14 +52,15 @@ This document describes the different errors Vikunja can return.
## List ## List
| ErrorCode | HTTP Status Code | Description | | ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------| |-----------|------------------|-------------------------------------------------------------------------------------------------------------------------------|
| 3001 | 404 | The list does not exist. | | 3001 | 404 | The list does not exist. |
| 3004 | 403 | The user needs to have read permissions on that list to perform that action. | | 3004 | 403 | The user needs to have read permissions on that list to perform that action. |
| 3005 | 400 | The list title cannot be empty. | | 3005 | 400 | The list title cannot be empty. |
| 3006 | 404 | The list share does not exist. | | 3006 | 404 | The list share does not exist. |
| 3007 | 400 | A list with this identifier already exists. | | 3007 | 400 | A list with this identifier already exists. |
| 3008 | 412 | The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list. | | 3008 | 412 | The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list. |
| 3009 | 412 | The list cannot belong to a dynamically generated namespace like "Favorites". |
## Task ## Task

View File

@ -237,7 +237,7 @@ type ErrListIsArchived struct {
ListID int64 ListID int64
} }
// IsErrListIsArchived checks if an error is a . // IsErrListIsArchived checks if an error is a list is archived error.
func IsErrListIsArchived(err error) bool { func IsErrListIsArchived(err error) bool {
_, ok := err.(ErrListIsArchived) _, ok := err.(ErrListIsArchived)
return ok return ok
@ -255,6 +255,34 @@ func (err ErrListIsArchived) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeListIsArchived, Message: "This list is archived. Editing or creating new tasks is not possible."} return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeListIsArchived, Message: "This list is archived. Editing or creating new tasks is not possible."}
} }
// ErrListCannotBelongToAPseudoNamespace represents an error where a list cannot belong to a pseudo namespace
type ErrListCannotBelongToAPseudoNamespace struct {
ListID int64
NamespaceID int64
}
// IsErrListCannotBelongToAPseudoNamespace checks if an error is a list is archived error.
func IsErrListCannotBelongToAPseudoNamespace(err error) bool {
_, ok := err.(*ErrListCannotBelongToAPseudoNamespace)
return ok
}
func (err *ErrListCannotBelongToAPseudoNamespace) Error() string {
return fmt.Sprintf("List cannot belong to a pseudo namespace [ListID: %d, NamespaceID: %d]", err.ListID, err.NamespaceID)
}
// ErrCodeListCannotBelongToAPseudoNamespace holds the unique world-error code of this error
const ErrCodeListCannotBelongToAPseudoNamespace = 3009
// HTTPError holds the http error description
func (err *ErrListCannotBelongToAPseudoNamespace) HTTPError() web.HTTPError {
return web.HTTPError{
HTTPCode: http.StatusPreconditionFailed,
Code: ErrCodeListCannotBelongToAPseudoNamespace,
Message: "This list cannot belong a dynamically generated namespace.",
}
}
// ================ // ================
// List task errors // List task errors
// ================ // ================

View File

@ -543,6 +543,10 @@ func (l *List) CheckIsArchived(s *xorm.Session) (err error) {
} }
func checkListBeforeUpdateOrDelete(s *xorm.Session, list *List) error { func checkListBeforeUpdateOrDelete(s *xorm.Session, list *List) error {
if list.NamespaceID < 0 {
return &ErrListCannotBelongToAPseudoNamespace{ListID: list.ID, NamespaceID: list.NamespaceID}
}
// Check if the namespace exists // Check if the namespace exists
if list.NamespaceID > 0 { if list.NamespaceID > 0 {
_, err := GetNamespaceByID(s, list.NamespaceID) _, err := GetNamespaceByID(s, list.NamespaceID)

View File

@ -221,6 +221,25 @@ func TestList_CreateOrUpdate(t *testing.T) {
assert.False(t, can) // namespace is not writeable by us assert.False(t, can) // namespace is not writeable by us
_ = s.Close() _ = s.Close()
}) })
t.Run("pseudo namespace", func(t *testing.T) {
usr := &user.User{
ID: 6,
Username: "user6",
Email: "user6@example.com",
}
db.LoadAndAssertFixtures(t)
s := db.NewSession()
list := List{
ID: 6,
Title: "Test6",
Description: "Lorem Ipsum",
NamespaceID: -1,
}
err := list.Update(s, usr)
assert.Error(t, err)
assert.True(t, IsErrListCannotBelongToAPseudoNamespace(err))
})
}) })
}) })
} }