✨ Add initial share commandline handling
This commit is contained in:
@@ -77,9 +77,9 @@ const (
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string
|
||||
Password string
|
||||
Role GlobalRole
|
||||
Username string
|
||||
Password string
|
||||
Role GlobalRole
|
||||
}
|
||||
|
||||
type Share struct {
|
||||
@@ -96,6 +96,7 @@ type ShareUser struct {
|
||||
type Login struct {
|
||||
LoginName string
|
||||
Password string
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
// View on a share from the perspective of a user of that share.
|
||||
@@ -114,6 +115,8 @@ type LoginShare struct {
|
||||
const userPrefix = "user:"
|
||||
const sharePrefix = "share:"
|
||||
const loginSharePrefix = "loginshare:"
|
||||
const shareuserPrefix = "shareuser:"
|
||||
const shareloginPrefix = "sharelogin:"
|
||||
|
||||
type DBStore struct {
|
||||
db *buntdb.DB
|
||||
@@ -127,6 +130,14 @@ func (s Share) key() string {
|
||||
return sharePrefix + s.UUID.String()
|
||||
}
|
||||
|
||||
func (s Share) userKey(username string) string {
|
||||
return fmt.Sprintf("%s%s:%s", shareuserPrefix, s.UUID.String(), username)
|
||||
}
|
||||
|
||||
func (s Share) loginKey(username, loginName string) string {
|
||||
return fmt.Sprintf("%s%s:%s:%s", shareloginPrefix, s.UUID.String(), username, loginName)
|
||||
}
|
||||
|
||||
func NewDBStore(filename string) (*DBStore, error) {
|
||||
db, err := buntdb.Open(filename)
|
||||
if err != nil {
|
||||
@@ -333,7 +344,7 @@ func (store *DBStore) RemoveShare(id uuid.UUID) error {
|
||||
share := Share{UUID: id}
|
||||
|
||||
var userNames []string
|
||||
usersPrefix := share.key() + ":user:"
|
||||
usersPrefix := share.userKey("")
|
||||
if err := tx.AscendKeys(usersPrefix+"*", func(key, value string) bool {
|
||||
userNames = append(userNames, strings.TrimPrefix(key, usersPrefix))
|
||||
return true
|
||||
@@ -343,7 +354,7 @@ func (store *DBStore) RemoveShare(id uuid.UUID) error {
|
||||
|
||||
for _, username := range userNames {
|
||||
if err := store.removeUserFromShare(tx, share, username); err != nil {
|
||||
return fmt.Errorf("cannot remove user %q from share: %v", username, err)
|
||||
return fmt.Errorf("cannot remove user %q from share: %w", username, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,8 +374,8 @@ func (store *DBStore) AddUserToShare(share Share, username string, role ShareRol
|
||||
if _, err := tx.Get(share.key()); err != nil {
|
||||
return ErrShareNotFound
|
||||
}
|
||||
if _, _, err := tx.Set(share.key()+":user:"+username, string(role), nil); err != nil {
|
||||
return fmt.Errorf("cannot set user: %v", err)
|
||||
if _, _, err := tx.Set(share.userKey(username), string(role), nil); err != nil {
|
||||
return fmt.Errorf("cannot set user: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -372,7 +383,7 @@ func (store *DBStore) AddUserToShare(share Share, username string, role ShareRol
|
||||
|
||||
func (store *DBStore) removeUserFromShare(tx *buntdb.Tx, share Share, username string) error {
|
||||
var logins []string
|
||||
loginsPrefix := share.key() + ":login:" + username + ":"
|
||||
loginsPrefix := share.loginKey(username, "")
|
||||
if err := tx.AscendKeys(loginsPrefix+"*", func(key, value string) bool {
|
||||
logins = append(logins, strings.TrimPrefix(key, loginsPrefix))
|
||||
return true
|
||||
@@ -383,18 +394,18 @@ func (store *DBStore) removeUserFromShare(tx *buntdb.Tx, share Share, username s
|
||||
for _, loginName := range logins {
|
||||
shareIdString, err := tx.Delete(loginSharePrefix + username + ":" + loginName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot remove login ref: %v", err)
|
||||
return fmt.Errorf("cannot remove login ref: %w", err)
|
||||
} else if shareIdString != share.UUID.String() {
|
||||
return fmt.Errorf("inconsistent login ref %q", username+":"+loginName)
|
||||
}
|
||||
|
||||
if _, err := tx.Delete(share.key() + ":login:" + username + ":" + loginName); err != nil {
|
||||
return fmt.Errorf("cannot remove login %q: %v", loginName, err)
|
||||
if _, err := tx.Delete(share.loginKey(username, loginName)); err != nil {
|
||||
return fmt.Errorf("cannot remove login %q: %w", loginName, err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := tx.Delete(share.key() + ":user:" + username); err != nil {
|
||||
return fmt.Errorf("cannot remove user: %v", err)
|
||||
if _, err := tx.Delete(share.userKey(username)); err != nil {
|
||||
return fmt.Errorf("cannot remove user: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -415,7 +426,7 @@ func (store *DBStore) AddLogin(share Share, username string, login Login) error
|
||||
if _, err := tx.Get(share.key()); err != nil {
|
||||
return ErrShareNotFound
|
||||
}
|
||||
if _, err := tx.Get(share.key() + ":user:" + username); err != nil {
|
||||
if _, err := tx.Get(share.userKey(username)); err != nil {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
|
||||
@@ -426,14 +437,18 @@ func (store *DBStore) AddLogin(share Share, username string, login Login) error
|
||||
// If the existing value happens to be our shareId already, we assume we are just
|
||||
// updating the existing model. No harm there.
|
||||
if existingValue, exists, err := tx.Set(loginSharePrefix+username+":"+login.LoginName, share.UUID.String(), nil); err != nil {
|
||||
return fmt.Errorf("cannot set login reference: %v", err)
|
||||
return fmt.Errorf("cannot set login reference: %w", err)
|
||||
} else if exists && existingValue != share.UUID.String() {
|
||||
return ErrLoginDuplicate
|
||||
}
|
||||
|
||||
// Now simply update the current login information.
|
||||
if _, _, err := tx.Set(share.key()+":login:"+username+":"+login.LoginName, login.Password, nil); err != nil {
|
||||
return fmt.Errorf("cannot set login: %v", err)
|
||||
b, err := json.Marshal(login)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot marshal login: %w", err)
|
||||
}
|
||||
if _, _, err := tx.Set(share.loginKey(username, login.LoginName), string(b), nil); err != nil {
|
||||
return fmt.Errorf("cannot set login: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -451,7 +466,7 @@ func (store *DBStore) RemoveLogin(share Share, username string, loginName string
|
||||
return ErrLoginNotFound
|
||||
}
|
||||
|
||||
if _, err := tx.Delete(share.key() + ":login:" + username + ":" + loginName); err != nil {
|
||||
if _, err := tx.Delete(share.loginKey(username, loginName)); err != nil {
|
||||
return ErrLoginNotFound
|
||||
}
|
||||
|
||||
@@ -499,37 +514,35 @@ func (store *DBStore) FindShareByLogin(username, loginName string) (loginShare L
|
||||
return err
|
||||
}
|
||||
|
||||
userRole, err := tx.Get(sharePrefix + shareIdString + ":user:" + username)
|
||||
if err == buntdb.ErrNotFound {
|
||||
// TODO warn about inconsistency
|
||||
return ErrShareNotFound
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginPassword, err := tx.Get(sharePrefix + shareIdString + ":login:" + username + ":" + loginName)
|
||||
if err == buntdb.ErrNotFound {
|
||||
// TODO warn about inconsistency
|
||||
return ErrShareNotFound
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
share, err := unmarshalShare(shareIdString, sharePayload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userRole, err := tx.Get(share.userKey(username))
|
||||
if err == buntdb.ErrNotFound {
|
||||
// TODO warn about inconsistency
|
||||
return ErrShareNotFound
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginPayload, err := tx.Get(share.loginKey(username, loginName))
|
||||
if err == buntdb.ErrNotFound {
|
||||
// TODO warn about inconsistency
|
||||
return ErrShareNotFound
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginShare.Share = share
|
||||
loginShare.ShareUser = ShareUser{
|
||||
Username: username,
|
||||
Role: ShareRole(userRole),
|
||||
}
|
||||
loginShare.Login = Login{
|
||||
LoginName: loginName,
|
||||
Password: loginPassword,
|
||||
if err := json.Unmarshal([]byte(loginPayload), &loginShare.Login); err != nil {
|
||||
return fmt.Errorf("cannot unmarshal login: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -543,7 +556,7 @@ func (store *DBStore) FindSharesByUser(username string) ([]UserShare, error) {
|
||||
func unmarshalShare(idString, payload string) (Share, error) {
|
||||
var share Share
|
||||
if err := json.Unmarshal([]byte(payload), &share); err != nil {
|
||||
return Share{}, err
|
||||
return Share{}, fmt.Errorf("cannot unmarshal share: %w", err)
|
||||
}
|
||||
|
||||
// Just in case ...
|
||||
|
||||
Reference in New Issue
Block a user