🚧 Implement basic share handling

This commit is contained in:
2020-10-12 19:51:44 +02:00
parent e6a62bfeb1
commit 66c525aa7b
2 changed files with 251 additions and 8 deletions
+154 -8
View File
@@ -45,9 +45,22 @@ type UserStore interface {
}
type ShareStore interface {
CreateShare() (Share, error)
UpdateShareAttributes(share Share) error
RemoveShare(id uuid.UUID) error
AddUserToShare(share Share, username string, role ShareRole) error
RemoveUserFromShare(share Share, username string) error
AddLogin(share Share, username string, login Login) error
RemoveLogin(share Share, username string, loginName string) error
GetShares() ([]Share, error)
FindByLogin(username, loginName string) (LoginShare, error)
FindByUser(username string) ([]UserShare, error)
}
var _ UserStore = &DBStore{}
var _ UserStore = (*DBStore)(nil)
var _ ShareStore = (*DBStore)(nil)
type GlobalRole string
@@ -72,30 +85,47 @@ type User struct {
}
type Share struct {
UUID uuid.UUID
Directory string
Users []ShareUser
UUID uuid.UUID
Name string
Description string
}
type ShareUser struct {
Username string
Role ShareRole
Logins []Login
}
type Login struct {
Loginname string
LoginName string
Password string
}
const usersPrefix = "users:"
// View on a share from the perspective of a user of that share.
type UserShare struct {
Share
Role ShareRole
}
// View on a share from the perspective of a specific login (with associated user).
type LoginShare struct {
Share
ShareUser
Login
}
const userPrefix = "user:"
const sharePrefix = "share:"
type DBStore struct {
db *buntdb.DB
}
func (u User) key() string {
return usersPrefix + u.Username
return userPrefix + u.Username
}
func (s Share) key() string {
return sharePrefix + s.UUID.String()
}
func NewDBStore(filename string) (*DBStore, error) {
@@ -135,6 +165,8 @@ func (u User) merge(updates User) (User, error) {
return merged, nil
}
var ErrShareNotFound = errors.New("share not found")
func (store *DBStore) AddUser(user User) (err error) {
if strings.Contains(user.Username, ":") {
return ErrInvalidUsername
@@ -260,3 +292,117 @@ func hashPassword(password string) (string, error) {
}
return string(hash), nil
}
func (store *DBStore) CreateShare() (Share, error) {
share := Share{
UUID: uuid.NewV4(),
}
if err := store.db.Update(func(tx *buntdb.Tx) error {
b, err := json.Marshal(share)
if err != nil {
return fmt.Errorf("cannot marshal share: %w", err)
}
if _, _, err := tx.Set(share.key(), string(b), nil); err != nil {
return err
}
return nil
}); err != nil {
return Share{}, err
}
return share, nil
}
func (store *DBStore) UpdateShareAttributes(share Share) error {
return store.db.Update(func(tx *buntdb.Tx) error {
var existingShare Share
if val, err := tx.Get(share.key()); err == buntdb.ErrNotFound {
return ErrShareNotFound
} else if err != nil {
return err
} else if err := json.Unmarshal([]byte(val), &existingShare); err != nil {
return fmt.Errorf("cannot unmarshal share %s: %w", share.UUID, err)
}
existingShare.UUID = share.UUID
existingShare.Name = share.Name
existingShare.Description = share.Description
if b, err := json.Marshal(existingShare); err != nil {
return fmt.Errorf("cannot marshal share %s: %w", share.UUID, err)
} else if _, _, err := tx.Set(existingShare.key(), string(b), nil); err != nil {
return err
}
return nil
})
}
func (store *DBStore) RemoveShare(id uuid.UUID) error {
return store.db.Update(func(tx *buntdb.Tx) error {
share := Share{UUID: id}
if _, err := tx.Delete(share.key()); err == buntdb.ErrNotFound {
return ErrShareNotFound
} else {
return err
}
})
}
func (store *DBStore) AddUserToShare(share Share, username string, role ShareRole) error {
panic("implement me")
}
func (store *DBStore) RemoveUserFromShare(share Share, username string) error {
panic("implement me")
}
func (store *DBStore) AddLogin(share Share, username string, login Login) error {
panic("implement me")
}
func (store *DBStore) RemoveLogin(share Share, username string, loginName string) error {
panic("implement me")
}
func (store *DBStore) GetShares() (shares []Share, err error) {
err = store.db.View(func(tx *buntdb.Tx) error {
var processingError error
if err := tx.AscendKeys(sharePrefix+"*", func(key, value string) bool {
var share Share
if err := json.Unmarshal([]byte(value), &share); err != nil {
processingError = err
return false
}
// Just in case ...
idString := strings.TrimPrefix(key, sharePrefix)
if id, err := uuid.FromString(idString); err != nil {
processingError = fmt.Errorf("invalid uuid in db: %q: %w", idString, err)
return false
} else {
share.UUID = id
}
shares = append(shares, share)
return true
}); err != nil {
return err
}
return processingError
})
return shares, err
}
func (store *DBStore) FindByLogin(username, loginName string) (LoginShare, error) {
panic("implement me")
}
func (store *DBStore) FindByUser(username string) ([]UserShare, error) {
panic("implement me")
}