graph: add appRoleAssignments and minimal application resource (#5318)
* bump libregraph-go lib Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * add appRoleAssignment stubs Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * add get application stub Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * fetch appRoles for application from settings service Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * initial list appRoleAssignments implementation Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * initial create appRoleAssignment implementation, extract assignmentToAppRoleAssignment, configurable app id and displayname Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * initial delete appRoleAssignment implementation, changed error handling and logging Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * initial expand appRoleAssignment on users Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * test user expand appRoleAssignment Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * test appRoleAssignment Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * fix education test by actually using the mocked roleManager Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * test getapplication Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * list assignments Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * use common not exists error handling Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * default to just 'ownCloud Infinite Scale' as application name Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * fix store_test Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * roll application uuid on init Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * fix tests Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * extract method Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * Apply suggestions from code review Co-authored-by: Michael Barz <mbarz@owncloud.com> Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> Co-authored-by: Michael Barz <mbarz@owncloud.com>
This commit is contained in:
co-authored by
Michael Barz
parent
1b6c269de5
commit
078698fdf4
@@ -79,7 +79,7 @@ func (g Service) CheckPermission(ctx context.Context, req *permissions.CheckPerm
|
||||
|
||||
permission, err := g.manager.ReadPermissionByName(req.Permission, roleIDs)
|
||||
if err != nil {
|
||||
if !errors.Is(err, settings.ErrPermissionNotFound) {
|
||||
if !errors.Is(err, settings.ErrNotFound) {
|
||||
return &permissions.CheckPermissionResponse{
|
||||
Status: status.NewInternal(ctx, err.Error()),
|
||||
}, nil
|
||||
|
||||
@@ -12,7 +12,12 @@ var (
|
||||
Registry = map[string]RegisterFunc{}
|
||||
|
||||
// ErrPermissionNotFound defines a new error for when a permission was not found
|
||||
//
|
||||
// Deprecated use the more generic ErrNotFound
|
||||
ErrPermissionNotFound = errors.New("permission not found")
|
||||
|
||||
// ErrNotFound is the error to use when a resource was not found.
|
||||
ErrNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
// RegisterFunc stores store constructors
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package errortypes
|
||||
|
||||
// BundleNotFound is the error to use when a bundle is not found.
|
||||
//
|
||||
// Deprecated: use the genreric services/settings/pkg/settings.NotFound error
|
||||
type BundleNotFound string
|
||||
|
||||
func (e BundleNotFound) Error() string { return "error: bundle not found: " + string(e) }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/store/errortypes"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
var m = &sync.RWMutex{}
|
||||
@@ -111,7 +112,7 @@ func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, err
|
||||
func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) {
|
||||
bundle, err := s.ReadBundle(bundleID)
|
||||
if err != nil {
|
||||
if _, notFound := err.(errortypes.BundleNotFound); !notFound {
|
||||
if !errors.Is(err, settings.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
bundle = new(settingsmsg.Bundle)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/store/errortypes"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
@@ -13,7 +14,7 @@ import (
|
||||
func (s Store) parseRecordFromFile(record proto.Message, filePath string) error {
|
||||
_, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
return errortypes.BundleNotFound(err.Error())
|
||||
return fmt.Errorf("%q: %w", filePath, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
@@ -28,7 +29,7 @@ func (s Store) parseRecordFromFile(record proto.Message, filePath string) error
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return errortypes.BundleNotFound(filePath)
|
||||
return fmt.Errorf("%q: %w", filePath, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
if err := protojson.Unmarshal(b, record); err != nil {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s Store) ReadPermissionByName(name string, roleIDs []string) (*settingsmsg
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, settings.ErrPermissionNotFound
|
||||
return nil, settings.ErrNotFound
|
||||
}
|
||||
|
||||
// extractPermissionsByResource collects all permissions from the provided role that match the requested resource
|
||||
|
||||
@@ -6,8 +6,10 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
// ListRoleAssignments loads and returns all role assignments matching the given assignment identifier.
|
||||
@@ -15,14 +17,24 @@ func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRole
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
assIDs, err := s.mdc.ReadDir(ctx, accountPath(accountUUID))
|
||||
if err != nil {
|
||||
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))
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -42,10 +54,17 @@ func (s *Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.Us
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
// as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role"
|
||||
_ = s.mdc.Delete(ctx, accountPath(accountUUID))
|
||||
// TODO: How to differentiate between 'not found' and other errors?
|
||||
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))
|
||||
err = s.mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -67,7 +86,12 @@ func (s *Store) RemoveRoleAssignment(assignmentID string) error {
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
accounts, err := s.mdc.ReadDir(ctx, accountsFolderLocation)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return fmt.Errorf("assignmentID '%s' %w", assignmentID, settings.ErrNotFound)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -81,11 +105,13 @@ func (s *Store) RemoveRoleAssignment(assignmentID string) error {
|
||||
|
||||
for _, assID := range assIDs {
|
||||
if assID == assignmentID {
|
||||
return s.mdc.Delete(ctx, assignmentPath(accID, assID))
|
||||
// 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' not found", assignmentID)
|
||||
return fmt.Errorf("assignmentID '%s' %w", assignmentID, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
func accountPath(accountUUID string) string {
|
||||
|
||||
@@ -7,8 +7,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
// ListBundles returns all bundles in the dataPath folder that match the given type.
|
||||
@@ -18,7 +20,12 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri
|
||||
|
||||
if len(bundleIDs) == 0 {
|
||||
bIDs, err := s.mdc.ReadDir(ctx, bundleFolderLocation)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return make([]*settingsmsg.Bundle, 0), nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -27,7 +34,12 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri
|
||||
var bundles []*settingsmsg.Bundle
|
||||
for _, id := range bundleIDs {
|
||||
b, err := s.mdc.SimpleDownload(ctx, bundlePath(id))
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -50,7 +62,12 @@ func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) {
|
||||
s.Init()
|
||||
ctx := context.TODO()
|
||||
b, err := s.mdc.SimpleDownload(ctx, bundlePath(bundleID))
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return nil, fmt.Errorf("bundleID '%s' %w", bundleID, settings.ErrNotFound)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -64,7 +81,12 @@ func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
ids, err := s.mdc.ReadDir(ctx, bundleFolderLocation)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return nil, fmt.Errorf("settingID '%s' %w", settingID, settings.ErrNotFound)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -72,6 +94,9 @@ func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) {
|
||||
for _, id := range ids {
|
||||
b, err := s.ReadBundle(id)
|
||||
if err != nil {
|
||||
if errors.Is(err, settings.ErrNotFound) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -82,7 +107,7 @@ func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) {
|
||||
}
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("setting '%s' not found", settingID)
|
||||
return nil, fmt.Errorf("settingID '%s' %w", settingID, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
// WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons
|
||||
@@ -102,7 +127,9 @@ func (s *Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting
|
||||
s.Init()
|
||||
b, err := s.ReadBundle(bundleID)
|
||||
if err != nil {
|
||||
// TODO: How to differentiate 'not found'?
|
||||
if !errors.Is(err, settings.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
b = new(settingsmsg.Bundle)
|
||||
b.Id = bundleID
|
||||
b.Type = settingsmsg.Bundle_TYPE_DEFAULT
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *Store) ReadPermissionByName(name string, roleIDs []string) (*settingsms
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, settings.ErrPermissionNotFound
|
||||
return nil, settings.ErrNotFound
|
||||
}
|
||||
|
||||
// extractPermissionsByResource collects all permissions from the provided role that match the requested resource
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/config/defaults"
|
||||
)
|
||||
|
||||
@@ -53,9 +54,12 @@ func NewMDC(s *Store) error {
|
||||
return s.initMetadataClient(mdc)
|
||||
}
|
||||
|
||||
// SimpleDownload returns nil if not found
|
||||
// SimpleDownload returns errtypes.NotFound if not found
|
||||
func (m *MockedMetadataClient) SimpleDownload(_ context.Context, id string) ([]byte, error) {
|
||||
return m.data[id], nil
|
||||
if data, ok := m.data[id]; ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, errtypes.NotFound("not found")
|
||||
}
|
||||
|
||||
// SimpleUpload can't error
|
||||
|
||||
@@ -7,8 +7,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
// ListValues reads all values that match the given bundleId and accountUUID.
|
||||
@@ -20,7 +22,12 @@ func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value,
|
||||
ctx := context.TODO()
|
||||
|
||||
vIDs, err := s.mdc.ReadDir(ctx, valuesFolderLocation)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return make([]*settingsmsg.Value, 0), nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,7 +35,12 @@ func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value,
|
||||
var values []*settingsmsg.Value
|
||||
for _, vid := range vIDs {
|
||||
b, err := s.mdc.SimpleDownload(ctx, valuePath(vid))
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
continue
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -61,7 +73,12 @@ func (s *Store) ReadValue(valueID string) (*settingsmsg.Value, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
b, err := s.mdc.SimpleDownload(ctx, valuePath(valueID))
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// continue
|
||||
case errtypes.NotFound:
|
||||
return nil, fmt.Errorf("valueID '%s' %w", valueID, settings.ErrNotFound)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
val := &settingsmsg.Value{}
|
||||
|
||||
Reference in New Issue
Block a user