✨ Implement user-by-share, login-by-share and share-by-user retrieval
This commit is contained in:
parent
9c29280207
commit
8f49cccfeb
75
store.go
75
store.go
|
@ -53,6 +53,8 @@ type ShareStore interface {
|
||||||
RemoveLogin(share Share, username string, loginName string) error
|
RemoveLogin(share Share, username string, loginName string) error
|
||||||
|
|
||||||
GetShares() ([]Share, error)
|
GetShares() ([]Share, error)
|
||||||
|
GetShareUsers(share Share) ([]ShareUser, error)
|
||||||
|
GetShareLogins(share Share, username string) ([]Login, error)
|
||||||
|
|
||||||
FindShareByLogin(username, loginName string) (LoginShare, error)
|
FindShareByLogin(username, loginName string) (LoginShare, error)
|
||||||
FindSharesByUser(username string) ([]UserShare, error)
|
FindSharesByUser(username string) ([]UserShare, error)
|
||||||
|
@ -497,6 +499,44 @@ func (store *DBStore) GetShares() (shares []Share, err error) {
|
||||||
return shares, err
|
return shares, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (store *DBStore) GetShareUsers(share Share) (shareUsers []ShareUser, err error) {
|
||||||
|
err = store.db.View(func(tx *buntdb.Tx) error {
|
||||||
|
usersPrefix := share.userKey("")
|
||||||
|
if err := tx.AscendKeys(usersPrefix+"*", func(key, value string) bool {
|
||||||
|
var shareUser ShareUser
|
||||||
|
shareUser.Username = strings.TrimPrefix(key, usersPrefix)
|
||||||
|
shareUser.Role = ShareRole(value)
|
||||||
|
shareUsers = append(shareUsers, shareUser)
|
||||||
|
return true
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *DBStore) GetShareLogins(share Share, username string) (logins []Login, err error) {
|
||||||
|
err = store.db.View(func(tx *buntdb.Tx) error {
|
||||||
|
var processingErr error
|
||||||
|
|
||||||
|
loginsPrefix := share.loginKey(username, "")
|
||||||
|
if err := tx.AscendKeys(loginsPrefix+"*", func(key, value string) bool {
|
||||||
|
var login Login
|
||||||
|
if err := json.Unmarshal([]byte(value), &login); err != nil {
|
||||||
|
processingErr = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
logins = append(logins, login)
|
||||||
|
return true
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return processingErr
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (store *DBStore) FindShareByLogin(username, loginName string) (loginShare LoginShare, err error) {
|
func (store *DBStore) FindShareByLogin(username, loginName string) (loginShare LoginShare, err error) {
|
||||||
err = store.db.View(func(tx *buntdb.Tx) error {
|
err = store.db.View(func(tx *buntdb.Tx) error {
|
||||||
shareIdString, err := tx.Get(loginSharePrefix + username + ":" + loginName)
|
shareIdString, err := tx.Get(loginSharePrefix + username + ":" + loginName)
|
||||||
|
@ -549,8 +589,39 @@ func (store *DBStore) FindShareByLogin(username, loginName string) (loginShare L
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *DBStore) FindSharesByUser(username string) ([]UserShare, error) {
|
func (store *DBStore) FindSharesByUser(username string) (userShares []UserShare, err error) {
|
||||||
panic("implement me")
|
prefix := shareuserPrefix
|
||||||
|
suffix := ":" + username
|
||||||
|
|
||||||
|
err = store.db.View(func(tx *buntdb.Tx) error {
|
||||||
|
var processingError error
|
||||||
|
if err := tx.AscendKeys(prefix+"*"+suffix, func(key, value string) bool {
|
||||||
|
var userShare UserShare
|
||||||
|
shareIdString := strings.TrimSuffix(strings.TrimPrefix(key, prefix), suffix)
|
||||||
|
|
||||||
|
if sharePayload, err := tx.Get(sharePrefix + shareIdString); err == buntdb.ErrNotFound {
|
||||||
|
// TODO report inconsistency
|
||||||
|
processingError = ErrShareNotFound
|
||||||
|
return false
|
||||||
|
} else if err != nil {
|
||||||
|
processingError = err
|
||||||
|
return false
|
||||||
|
} else if err := json.Unmarshal([]byte(sharePayload), &userShare.Share); err != nil {
|
||||||
|
processingError = fmt.Errorf("cannot unmarshal share: %w", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
userShare.Role = ShareRole(value)
|
||||||
|
|
||||||
|
userShares = append(userShares, userShare)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return processingError
|
||||||
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalShare(idString, payload string) (Share, error) {
|
func unmarshalShare(idString, payload string) (Share, error) {
|
||||||
|
|
|
@ -227,6 +227,49 @@ func TestStoreShareHandling(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("logins can be added", func(t *testing.T) {
|
t.Run("logins can be added", func(t *testing.T) {
|
||||||
login1 := Login{LoginName: "login1"}
|
login1 := Login{LoginName: "login1"}
|
||||||
login2 := Login{LoginName: "login2"}
|
login2 := Login{LoginName: "login2"}
|
||||||
|
@ -242,6 +285,16 @@ func TestStoreShareHandling(t *testing.T) {
|
||||||
t.Errorf("adding login returned error: %v", err)
|
t.Errorf("adding login returned error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("duplicate login not allowed", func(t *testing.T) {
|
t.Run("duplicate login not allowed", func(t *testing.T) {
|
||||||
// Different share, but same user:login pair as above. Must be a share where
|
// Different share, but same user:login pair as above. Must be a share where
|
||||||
// that user is already assigned, though.
|
// that user is already assigned, though.
|
||||||
|
|
Loading…
Reference in New Issue