Initial QSfera import
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
// Package store implements the go-micro store interface
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
settingsmsg "github.com/qsfera/server/protogen/gen/qsfera/messages/settings/v0"
|
||||
"github.com/qsfera/server/services/settings/pkg/settings"
|
||||
"github.com/qsfera/server/services/settings/pkg/store/defaults"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
|
||||
)
|
||||
|
||||
// ListRoleAssignments loads and returns all role assignments matching the given assignment identifier.
|
||||
func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) {
|
||||
// shortcut for service accounts
|
||||
for _, serviceAccountID := range s.cfg.ServiceAccountIDs {
|
||||
if accountUUID == serviceAccountID {
|
||||
return []*settingsmsg.UserRoleAssignment{
|
||||
{
|
||||
Id: uuid.NewString(), // should we hardcode this id too?
|
||||
AccountUuid: accountUUID,
|
||||
RoleId: defaults.BundleUUIDServiceAccount,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
assIDs, err := s.mdc.ReadDir(ctx, accountPath(accountUUID))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return make([]*settingsmsg.UserRoleAssignment, 0), nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ass := make([]*settingsmsg.UserRoleAssignment, 0, len(assIDs))
|
||||
for _, assID := range assIDs {
|
||||
b, err := s.mdc.SimpleDownload(ctx, assignmentPath(accountUUID, assID))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a := &settingsmsg.UserRoleAssignment{}
|
||||
err = json.Unmarshal(b, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ass = append(ass, a)
|
||||
}
|
||||
return ass, nil
|
||||
}
|
||||
|
||||
// ListRoleAssignmentsByRole returns all role assignmentes matching the give roleID
|
||||
func (s *Store) ListRoleAssignmentsByRole(roleID string) ([]*settingsmsg.UserRoleAssignment, error) {
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
accountIDs, err := s.mdc.ReadDir(ctx, accountsFolderLocation)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return make([]*settingsmsg.UserRoleAssignment, 0), nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
assignments := make([]*settingsmsg.UserRoleAssignment, 0, len(accountIDs))
|
||||
|
||||
// This is very inefficient, with the current layout we need to iterated through all
|
||||
// account folders and read each assignment file in there to check if that contains
|
||||
// the give role ID.
|
||||
for _, account := range accountIDs {
|
||||
assignmentIDs, err := s.mdc.ReadDir(ctx, accountPath(account))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return make([]*settingsmsg.UserRoleAssignment, 0), nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, assignmentID := range assignmentIDs {
|
||||
b, err := s.mdc.SimpleDownload(ctx, assignmentPath(account, assignmentID))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a := &settingsmsg.UserRoleAssignment{}
|
||||
err = json.Unmarshal(b, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if a.GetRoleId() == roleID {
|
||||
assignments = append(assignments, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
return assignments, nil
|
||||
}
|
||||
|
||||
// WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account.
|
||||
func (s *Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) {
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
// as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role"
|
||||
err := s.mdc.Delete(ctx, accountPath(accountUUID))
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
// already gone, continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = s.mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ass := &settingsmsg.UserRoleAssignment{
|
||||
Id: uuid.NewString(),
|
||||
AccountUuid: accountUUID,
|
||||
RoleId: roleID,
|
||||
}
|
||||
b, err := json.Marshal(ass)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ass, s.mdc.SimpleUpload(ctx, assignmentPath(accountUUID, ass.Id), b)
|
||||
}
|
||||
|
||||
// RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account.
|
||||
func (s *Store) RemoveRoleAssignment(assignmentID string) error {
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
accounts, err := s.mdc.ReadDir(ctx, accountsFolderLocation)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return fmt.Errorf("assignmentID '%s' %w", assignmentID, settings.ErrNotFound)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: use indexer to avoid spamming Metadata service
|
||||
for _, accID := range accounts {
|
||||
assIDs, err := s.mdc.ReadDir(ctx, accountPath(accID))
|
||||
if err != nil {
|
||||
// TODO: error?
|
||||
continue
|
||||
}
|
||||
|
||||
for _, assID := range assIDs {
|
||||
if assID == assignmentID {
|
||||
// as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role"
|
||||
// we also have to delete the cached dir listing
|
||||
return s.mdc.Delete(ctx, accountPath(accID))
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("assignmentID '%s' %w", assignmentID, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
func accountPath(accountUUID string) string {
|
||||
return fmt.Sprintf("%s/%s", accountsFolderLocation, accountUUID)
|
||||
}
|
||||
|
||||
func assignmentPath(accountUUID string, assignmentID string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", accountsFolderLocation, accountUUID, assignmentID)
|
||||
}
|
||||
Reference in New Issue
Block a user