Enable a list to be moved across namespaces (#1096)
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
Co-authored-by: Simon Hilchenbach <simon@hilchenba.ch> Reviewed-on: vikunja/api#1096 Reviewed-by: konrad <k@knt.li> Co-authored-by: shilch <simon@hilchenba.ch> Co-committed-by: shilch <simon@hilchenba.ch>
This commit is contained in:
parent
da318e3db1
commit
f7a06e4644
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"go.testEnvVars": {
|
||||
"VIKUNJA_SERVICE_ROOTPATH": "${workspaceRoot}"
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@ menu:
|
||||
# Mage
|
||||
|
||||
Vikunja uses [Mage](https://magefile.org/) to script common development tasks and even releasing.
|
||||
Mage is a pure go solution which allows for greater flexibility and things like better paralelization.
|
||||
Mage is a pure go solution which allows for greater flexibility and things like better parallelization.
|
||||
|
||||
This document explains what taks are available and what they do.
|
||||
This document explains what tasks are available and what they do.
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build mage
|
||||
// +build mage
|
||||
|
||||
package main
|
||||
@ -349,7 +350,7 @@ func (Test) Unit() {
|
||||
mg.Deps(initVars)
|
||||
setApiPackages()
|
||||
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
||||
args := append([]string{"test", Goflags[0], "-p", "1", "-timeout", "20m"}, ApiPackages...)
|
||||
args := append([]string{"test", Goflags[0], "-p", "1", "-coverprofile", "cover.out", "-timeout", "20m"}, ApiPackages...)
|
||||
runAndStreamOutput("go", args...)
|
||||
}
|
||||
|
||||
|
@ -630,6 +630,7 @@ func UpdateList(s *xorm.Session, list *List, auth web.Auth, updateListBackground
|
||||
"is_archived",
|
||||
"identifier",
|
||||
"hex_color",
|
||||
"namespace_id",
|
||||
"position",
|
||||
}
|
||||
if list.Description != "" {
|
||||
|
@ -116,6 +116,25 @@ func (l *List) CanUpdate(s *xorm.Session, a web.Auth) (canUpdate bool, err error
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Get the list
|
||||
ol, err := GetListSimpleByID(s, l.ID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if we're moving the list into a different namespace.
|
||||
// If that is the case, we need to verify permissions to do so.
|
||||
if l.NamespaceID != 0 && l.NamespaceID != ol.NamespaceID {
|
||||
newNamespace := &Namespace{ID: l.NamespaceID}
|
||||
can, err := newNamespace.CanWrite(s, a)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !can {
|
||||
return false, ErrGenericForbidden{}
|
||||
}
|
||||
}
|
||||
|
||||
fid := getSavedFilterIDFromListID(l.ID)
|
||||
if fid > 0 {
|
||||
sf, err := getSavedFilterSimpleByID(s, fid)
|
||||
|
@ -163,6 +163,65 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
||||
assert.True(t, IsErrListIdentifierIsNotUnique(err))
|
||||
_ = s.Close()
|
||||
})
|
||||
t.Run("change namespace", func(t *testing.T) {
|
||||
t.Run("own", 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: 7, // from 6
|
||||
}
|
||||
can, err := list.CanUpdate(s, usr)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, can)
|
||||
err = list.Update(s, usr)
|
||||
assert.NoError(t, err)
|
||||
err = s.Commit()
|
||||
assert.NoError(t, err)
|
||||
db.AssertExists(t, "lists", map[string]interface{}{
|
||||
"id": list.ID,
|
||||
"title": list.Title,
|
||||
"description": list.Description,
|
||||
"namespace_id": list.NamespaceID,
|
||||
}, false)
|
||||
})
|
||||
// FIXME: The check for whether the namespace is archived is missing in namespace.CanWrite
|
||||
// t.Run("archived own", func(t *testing.T) {
|
||||
// db.LoadAndAssertFixtures(t)
|
||||
// s := db.NewSession()
|
||||
// list := List{
|
||||
// ID: 1,
|
||||
// Title: "Test1",
|
||||
// Description: "Lorem Ipsum",
|
||||
// NamespaceID: 16, // from 1
|
||||
// }
|
||||
// can, err := list.CanUpdate(s, usr)
|
||||
// assert.NoError(t, err)
|
||||
// assert.False(t, can) // namespace is archived and thus not writeable
|
||||
// _ = s.Close()
|
||||
// })
|
||||
t.Run("others", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
s := db.NewSession()
|
||||
list := List{
|
||||
ID: 1,
|
||||
Title: "Test1",
|
||||
Description: "Lorem Ipsum",
|
||||
NamespaceID: 2, // from 1
|
||||
}
|
||||
can, _ := list.CanUpdate(s, usr)
|
||||
assert.False(t, can) // namespace is not writeable by us
|
||||
_ = s.Close()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -9215,5 +9215,5 @@ func (s *s) ReadDoc() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(swag.Name, &s{})
|
||||
swag.Register("swagger", &s{})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user