2020-10-09 18:35:44 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2020-10-12 19:51:44 +02:00
|
|
|
uuid "github.com/satori/go.uuid"
|
2020-10-09 18:35:44 +02:00
|
|
|
"github.com/tidwall/buntdb"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestStoreUserHandling(t *testing.T) {
|
|
|
|
store, err := NewDBStore(":memory:")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("cannot create store: %v", err)
|
|
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
|
|
|
|
t.Run("store should be empty initially", func(t *testing.T) {
|
|
|
|
users, err := store.GetUsers()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("no error should have been returned: %v", err)
|
|
|
|
}
|
|
|
|
if len(users) != 0 {
|
|
|
|
t.Errorf("there should be no users")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("user that doesn't exist should return error", func(t *testing.T) {
|
|
|
|
_, err := store.GetUser("someuser")
|
|
|
|
if err != ErrUserNotFound {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("adding users should work", func(t *testing.T) {
|
2020-10-10 19:06:49 +02:00
|
|
|
if err := store.AddUser(User{Username: "myuser", Password: "mypass", Role: GlobalRoleUser}); err != nil {
|
2020-10-09 18:35:44 +02:00
|
|
|
t.Errorf("cannot add user: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("retrieving that single user should work", func(t *testing.T) {
|
|
|
|
user, err := store.GetUser("myuser")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot retrieve user: %v", err)
|
|
|
|
}
|
|
|
|
if user.Username != "myuser" {
|
|
|
|
t.Errorf("retrieved user contains unexpected username")
|
|
|
|
}
|
|
|
|
if user.Role != GlobalRoleUser {
|
|
|
|
t.Errorf("retrieved user contains unexpected role")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("retrieving multiple users should work", func(t *testing.T) {
|
|
|
|
users, err := store.GetUsers()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot retrieve user list: %v", err)
|
|
|
|
}
|
|
|
|
if len(users) != 1 {
|
|
|
|
t.Errorf("there should be only one user")
|
|
|
|
}
|
|
|
|
if users[0].Username != "myuser" {
|
|
|
|
t.Errorf("retrieved user contains unexpected username")
|
|
|
|
}
|
|
|
|
if users[0].Role != GlobalRoleUser {
|
|
|
|
t.Errorf("retrieved user contains unexpected role")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("deleting that user should work", func(t *testing.T) {
|
|
|
|
err := store.RemoveUser("myuser")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("cannot delete user: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("user should no longer be found", func(t *testing.T) {
|
|
|
|
_, err := store.GetUser("myuser")
|
|
|
|
if err != ErrUserNotFound {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("user should no longer be listed", func(t *testing.T) {
|
|
|
|
users, err := store.GetUsers()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if len(users) != 0 {
|
|
|
|
t.Errorf("there should be no users")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("database should be empty now", func(t *testing.T) {
|
|
|
|
// checks that we properly deleted all keys
|
|
|
|
if err := store.db.View(func(tx *buntdb.Tx) error {
|
|
|
|
return tx.Ascend("", func(key, value string) bool {
|
|
|
|
t.Errorf("there should be no keys left")
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
}); err != nil {
|
|
|
|
t.Errorf("iterating keys failed: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2020-10-12 19:51:44 +02:00
|
|
|
|
|
|
|
func TestStoreShareHandling(t *testing.T) {
|
|
|
|
store, err := NewDBStore(":memory:")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("cannot create store: %v", err)
|
|
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
|
|
|
|
t.Run("store should be empty initially", func(t *testing.T) {
|
|
|
|
shares, err := store.GetShares()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("no error should have been returned: %v", err)
|
|
|
|
}
|
|
|
|
if len(shares) != 0 {
|
|
|
|
t.Errorf("there should be no shares")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("creating a share should work", func(t *testing.T) {
|
|
|
|
share, err := store.CreateShare()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error creating share: %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var emptyUUID uuid.UUID
|
|
|
|
if share.UUID == emptyUUID {
|
|
|
|
t.Errorf("UUID is empty")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if share.Name != "" || share.Description != "" {
|
|
|
|
t.Errorf("share should not have attributes set (yet)")
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("share attributes can be set", func(t *testing.T) {
|
|
|
|
share.Name = "a name"
|
|
|
|
share.Description = "some desc"
|
|
|
|
if err := store.UpdateShareAttributes(share); err != nil {
|
|
|
|
t.Errorf("cannot set attributes of share: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cannot set attributes of unknown share", func(t *testing.T) {
|
|
|
|
otherShare := Share{UUID: uuid.NewV4()}
|
|
|
|
otherShare.Name = "foo"
|
|
|
|
otherShare.Description = "bar"
|
|
|
|
|
|
|
|
err := store.UpdateShareAttributes(otherShare)
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("an error should have been returned")
|
|
|
|
} else if err != ErrShareNotFound {
|
|
|
|
t.Errorf("wrong error has been returned: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("share can be listed", func(t *testing.T) {
|
|
|
|
shares, err := store.GetShares()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error getting shares: %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(shares) != 1 {
|
|
|
|
t.Errorf("invalid number of shares: %d", len(shares))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if shares[0].UUID != share.UUID {
|
|
|
|
t.Errorf("unexpected uuid")
|
|
|
|
}
|
|
|
|
if shares[0].Name != "a name" {
|
|
|
|
t.Errorf("unexpected name")
|
|
|
|
}
|
|
|
|
if shares[0].Description != "some desc" {
|
|
|
|
t.Errorf("unexpected description")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("share can be removed", func(t *testing.T) {
|
|
|
|
if err := store.RemoveShare(share.UUID); err != nil {
|
|
|
|
t.Errorf("removing share failed: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Run("share access should work", func(t *testing.T) {
|
|
|
|
share1, _ := store.CreateShare()
|
|
|
|
share2, _ := store.CreateShare()
|
|
|
|
share3, _ := store.CreateShare()
|
|
|
|
|
|
|
|
user1 := User{Username: "user1"}
|
|
|
|
user2 := User{Username: "user2"}
|
|
|
|
_ = store.AddUser(user1)
|
|
|
|
_ = store.AddUser(user2)
|
|
|
|
|
2020-10-17 14:34:42 +02:00
|
|
|
defer func() {
|
|
|
|
_ = store.RemoveUser(user1.Username)
|
|
|
|
_ = store.RemoveUser(user2.Username)
|
|
|
|
}()
|
|
|
|
|
2020-10-24 16:57:00 +02:00
|
|
|
t.Run("can get single share", func(t *testing.T) {
|
|
|
|
share, err := store.GetShare(share1.UUID.String())
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if share != share1 {
|
|
|
|
t.Error("share should equal share1")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("unknown share cannot be retrieved", func(t *testing.T) {
|
|
|
|
_, err := store.GetShare(uuid.NewV4().String())
|
|
|
|
if err != ErrShareNotFound {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Run("multiple shares should exist", func(t *testing.T) {
|
|
|
|
shares, _ := store.GetShares()
|
|
|
|
if len(shares) != 3 {
|
|
|
|
t.Errorf("3 shares should exist")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("can add users to shares", func(t *testing.T) {
|
|
|
|
if err := store.AddUserToShare(share1, user1.Username, ShareRoleAdmin); err != nil {
|
|
|
|
t.Errorf("cannot add user1 to share1: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.AddUserToShare(share1, user2.Username, ShareRoleReader); err != nil {
|
|
|
|
t.Errorf("cannot add user2 to share1: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.AddUserToShare(share2, user2.Username, ShareRoleAdmin); err != nil {
|
|
|
|
t.Errorf("cannot add user2 to share2: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("cannot add login if user doesn't exist", func(t *testing.T) {
|
2020-10-18 10:33:29 +02:00
|
|
|
if err := store.AddLogin(share3, user1.Username, Login{"foo", "", false}); err == nil {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("an error should have been returned")
|
|
|
|
} else if err != ErrUserNotFound {
|
|
|
|
t.Errorf("wrong error has been returned: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-10-27 19:48:09 +01:00
|
|
|
t.Run("can get share access", func(t *testing.T) {
|
|
|
|
shareRole, err := store.GetShareAccess(share1, user1.Username)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if shareRole != ShareRoleAdmin {
|
|
|
|
t.Errorf("unexpected role: %s", shareRole)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cannot get share access if user has none", func(t *testing.T) {
|
|
|
|
_, err := store.GetShareAccess(share2, user1.Username)
|
|
|
|
if err != ErrUserNotFound {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-10-18 15:04:11 +02:00
|
|
|
t.Run("can list users", func(t *testing.T) {
|
|
|
|
users, err := store.GetShareUsers(share1)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if len(users) != 2 {
|
|
|
|
t.Errorf("unexpected amount of users: %d", len(users))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("can find shares by user", func(t *testing.T) {
|
|
|
|
userShares, err := store.FindSharesByUser(user2.Username)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if len(userShares) != 2 {
|
|
|
|
t.Errorf("unexpected amount of shared: %d", len(userShares))
|
|
|
|
}
|
|
|
|
share1Found := false
|
|
|
|
share2Found := false
|
|
|
|
for _, userShare := range userShares {
|
|
|
|
switch userShare.UUID {
|
|
|
|
case share1.UUID:
|
|
|
|
if userShare.Role != ShareRoleReader {
|
|
|
|
t.Errorf("invalid role for share1: %v", userShare.Role)
|
|
|
|
}
|
|
|
|
share1Found = true
|
|
|
|
case share2.UUID:
|
|
|
|
if userShare.Role != ShareRoleAdmin {
|
|
|
|
t.Errorf("invalid role for share2: %v", userShare.Role)
|
|
|
|
}
|
|
|
|
share2Found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !share1Found {
|
|
|
|
t.Errorf("share1 was not found")
|
|
|
|
}
|
|
|
|
if !share2Found {
|
|
|
|
t.Errorf("share2 was not found")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Run("logins can be added", func(t *testing.T) {
|
|
|
|
login1 := Login{LoginName: "login1"}
|
|
|
|
login2 := Login{LoginName: "login2"}
|
|
|
|
login3 := Login{LoginName: "login3"}
|
|
|
|
|
|
|
|
if err := store.AddLogin(share1, user1.Username, login1); err != nil {
|
|
|
|
t.Errorf("adding login returned error: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.AddLogin(share1, user2.Username, login2); err != nil {
|
|
|
|
t.Errorf("adding login returned error: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.AddLogin(share1, user2.Username, login3); err != nil {
|
|
|
|
t.Errorf("adding login returned error: %v", err)
|
|
|
|
}
|
|
|
|
|
2020-10-18 15:04:11 +02:00
|
|
|
t.Run("can list logins", func(t *testing.T) {
|
|
|
|
logins, err := store.GetShareLogins(share1, user2.Username)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if len(logins) != 2 {
|
|
|
|
t.Errorf("unexpected amount of users: %d", len(logins))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Run("duplicate login not allowed", func(t *testing.T) {
|
2020-10-17 14:34:42 +02:00
|
|
|
// Different share, but same user:login pair as above. Must be a share where
|
|
|
|
// that user is already assigned, though.
|
|
|
|
if err := store.AddLogin(share2, user2.Username, login2); err != ErrLoginDuplicate {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("share is found by login", func(t *testing.T) {
|
2020-10-17 14:34:42 +02:00
|
|
|
share, err := store.FindShareByLogin(user1.Username, login1.LoginName)
|
2020-10-13 19:59:35 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if share.UUID != share1.UUID {
|
2020-10-17 14:34:42 +02:00
|
|
|
t.Errorf("wrong share returned")
|
2020-10-13 19:59:35 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("unknown login/share combination returns error", func(t *testing.T) {
|
2020-10-17 14:34:42 +02:00
|
|
|
if _, err := store.FindShareByLogin(user1.Username, login3.LoginName); err != ErrShareNotFound {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("login can be removed", func(t *testing.T) {
|
|
|
|
if err := store.RemoveLogin(share1, user1.Username, login1.LoginName); err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2020-10-17 14:34:42 +02:00
|
|
|
if _, err := store.FindShareByLogin(user1.Username, login1.LoginName); err != ErrShareNotFound {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("share should not be found now, but returned: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("user can be removed", func(t *testing.T) {
|
2020-10-17 14:34:42 +02:00
|
|
|
if err := store.RemoveUserFromShare(share1, user2.Username); err != nil {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2020-10-17 14:34:42 +02:00
|
|
|
if _, err := store.FindShareByLogin(user2.Username, login2.LoginName); err != ErrShareNotFound {
|
2020-10-13 19:59:35 +02:00
|
|
|
t.Errorf("share should not be found now, but returned: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2020-10-17 14:34:42 +02:00
|
|
|
|
|
|
|
t.Run("can remove shares", func(t *testing.T) {
|
|
|
|
if err := store.RemoveShare(share1.UUID); err != nil {
|
|
|
|
t.Errorf("cannot remove share1: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.RemoveShare(share2.UUID); err != nil {
|
|
|
|
t.Errorf("cannot remove share2: %v", err)
|
|
|
|
}
|
|
|
|
if err := store.RemoveShare(share3.UUID); err != nil {
|
|
|
|
t.Errorf("cannot remove share3: %v", err)
|
|
|
|
}
|
|
|
|
})
|
2020-10-13 19:59:35 +02:00
|
|
|
})
|
|
|
|
|
2020-10-12 19:51:44 +02:00
|
|
|
t.Run("database should be empty now", func(t *testing.T) {
|
|
|
|
// checks that we properly deleted all keys
|
|
|
|
if err := store.db.View(func(tx *buntdb.Tx) error {
|
|
|
|
return tx.Ascend("", func(key, value string) bool {
|
2020-10-17 14:34:42 +02:00
|
|
|
t.Errorf("leftover key found: %v", key)
|
|
|
|
return true
|
2020-10-12 19:51:44 +02:00
|
|
|
})
|
|
|
|
}); err != nil {
|
|
|
|
t.Errorf("iterating keys failed: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|