From 59527e118d35e2947fbe28241cd2f7530af9abbb Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 24 Feb 2022 15:09:25 +0100 Subject: [PATCH 01/42] Settings: add metadata store Signed-off-by: jkoberg --- settings/pkg/store/metadata/assignments.go | 23 +++ .../pkg/store/metadata/assignments_test.go | 177 ++++++++++++++++++ settings/pkg/store/metadata/bundles.go | 41 ++++ settings/pkg/store/metadata/bundles_test.go | 147 +++++++++++++++ settings/pkg/store/metadata/permissions.go | 22 +++ settings/pkg/store/metadata/store.go | 58 ++++++ settings/pkg/store/metadata/store_test.go | 62 ++++++ settings/pkg/store/metadata/values.go | 31 +++ settings/pkg/store/metadata/values_test.go | 72 +++++++ settings/pkg/store/registry.go | 1 + 10 files changed, 634 insertions(+) create mode 100644 settings/pkg/store/metadata/assignments.go create mode 100644 settings/pkg/store/metadata/assignments_test.go create mode 100644 settings/pkg/store/metadata/bundles.go create mode 100644 settings/pkg/store/metadata/bundles_test.go create mode 100644 settings/pkg/store/metadata/permissions.go create mode 100644 settings/pkg/store/metadata/store.go create mode 100644 settings/pkg/store/metadata/store_test.go create mode 100644 settings/pkg/store/metadata/values.go create mode 100644 settings/pkg/store/metadata/values_test.go diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go new file mode 100644 index 00000000000..fc9d4431f54 --- /dev/null +++ b/settings/pkg/store/metadata/assignments.go @@ -0,0 +1,23 @@ +// Package store implements the go-micro store interface +package store + +import ( + "errors" + + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" +) + +// ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. +func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { + return nil, errors.New("not implemented") +} + +// WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account. +func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) { + return nil, errors.New("not implemented") +} + +// RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account. +func (s Store) RemoveRoleAssignment(assignmentID string) error { + return errors.New("not implemented") +} diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go new file mode 100644 index 00000000000..654b8af25f0 --- /dev/null +++ b/settings/pkg/store/metadata/assignments_test.go @@ -0,0 +1,177 @@ +package store + +import ( + "log" + "testing" + + olog "github.com/owncloud/ocis/ocis-pkg/log" + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/stretchr/testify/assert" +) + +var ( + einstein = "a4d07560-a670-4be9-8d60-9b547751a208" + //marie = "3c054db3-eec1-4ca4-b985-bc56dcf560cb" + + s = Store{ + Logger: logger, + mdc: mdc, + } + + logger = olog.NewLogger( + olog.Color(true), + olog.Pretty(true), + olog.Level("info"), + ) + + mdc = &MockedMetadataClient{data: make(map[string][]byte)} + + bundles = []*settingsmsg.Bundle{ + { + Id: "f36db5e6-a03c-40df-8413-711c67e40b47", + Type: settingsmsg.Bundle_TYPE_ROLE, + DisplayName: "test role - reads | update", + Name: "TEST_ROLE", + Extension: "ocis-settings", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_BUNDLE, + }, + Settings: []*settingsmsg.Setting{ + { + Name: "update", + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_UPDATE, + }, + }, + }, + { + Name: "read", + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + }, + }, + }, + }, + }, + { + Id: "44f1a664-0a7f-461a-b0be-5b59e46bbc7a", + Type: settingsmsg.Bundle_TYPE_ROLE, + DisplayName: "another", + Name: "ANOTHER_TEST_ROLE", + Extension: "ocis-settings", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_BUNDLE, + }, + Settings: []*settingsmsg.Setting{ + { + Name: "read", + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + }, + }, + }, + }, + }, + } +) + +func init() { + setupRoles() +} + +func setupRoles() { + for i := range bundles { + if _, err := s.WriteBundle(bundles[i]); err != nil { + log.Fatal(err) + } + } +} + +func TestAssignmentUniqueness(t *testing.T) { + var scenarios = []struct { + name string + userID string + firstRole string + secondRole string + }{ + { + "roles assignments", + einstein, + "f36db5e6-a03c-40df-8413-711c67e40b47", + "44f1a664-0a7f-461a-b0be-5b59e46bbc7a", + }, + } + + for _, scenario := range scenarios { + scenario := scenario + t.Run(scenario.name, func(t *testing.T) { + firstAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole) + assert.NoError(t, err) + assert.Equal(t, firstAssignment.RoleId, scenario.firstRole) + // TODO: check entry exists + + list, err := s.ListRoleAssignments(scenario.userID) + assert.NoError(t, err) + assert.Equal(t, 1, len(list)) + assert.Equal(t, list[0].RoleId, scenario.firstRole) + + // creating another assignment shouldn't add another entry, as we support max one role per user. + // assigning the second role should remove the old + secondAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.secondRole) + assert.NoError(t, err) + assert.Equal(t, secondAssignment.RoleId, scenario.secondRole) + + list, err = s.ListRoleAssignments(scenario.userID) + assert.NoError(t, err) + assert.Equal(t, 1, len(list)) + assert.Equal(t, list[0].RoleId, scenario.secondRole) + }) + } +} + +func TestDeleteAssignment(t *testing.T) { + var scenarios = []struct { + name string + userID string + firstRole string + secondRole string + }{ + { + "roles assignments", + einstein, + "f36db5e6-a03c-40df-8413-711c67e40b47", + "44f1a664-0a7f-461a-b0be-5b59e46bbc7a", + }, + } + + for _, scenario := range scenarios { + scenario := scenario + t.Run(scenario.name, func(t *testing.T) { + assignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole) + assert.NoError(t, err) + assert.Equal(t, assignment.RoleId, scenario.firstRole) + // TODO: uncomment + // assert.True(t, mdc.IDExists(assignment.RoleId)) + + list, err := s.ListRoleAssignments(scenario.userID) + assert.NoError(t, err) + assert.Equal(t, 1, len(list)) + + err = s.RemoveRoleAssignment(assignment.Id) + assert.NoError(t, err) + // TODO: uncomment + // assert.False(t, mdc.IDExists(assignment.RoleId)) + + list, err = s.ListRoleAssignments(scenario.userID) + assert.NoError(t, err) + assert.Equal(t, 0, len(list)) + + err = s.RemoveRoleAssignment(assignment.Id) + assert.Error(t, err) + // TODO: do we want a custom error message? + }) + } +} diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go new file mode 100644 index 00000000000..29af5e91306 --- /dev/null +++ b/settings/pkg/store/metadata/bundles.go @@ -0,0 +1,41 @@ +// Package store implements the go-micro store interface +package store + +import ( + "errors" + "sync" + + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" +) + +var m = &sync.RWMutex{} + +// ListBundles returns all bundles in the dataPath folder that match the given type. +func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { + return nil, errors.New("not implemented") +} + +// ReadBundle tries to find a bundle by the given id within the dataPath. +func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { + return nil, errors.New("not implemented") +} + +// ReadSetting tries to find a setting by the given id within the dataPath. +func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { + return nil, errors.New("not implemented") +} + +// WriteBundle writes the given record into a file within the dataPath. +func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { + return nil, errors.New("not implemented") +} + +// AddSettingToBundle adds the given setting to the bundle with the given bundleID. +func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) { + return nil, errors.New("not implemented") +} + +// RemoveSettingFromBundle removes the setting from the bundle with the given ids. +func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error { + return errors.New("not implemented") +} diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go new file mode 100644 index 00000000000..13c889bc1b5 --- /dev/null +++ b/settings/pkg/store/metadata/bundles_test.go @@ -0,0 +1,147 @@ +package store + +import ( + "testing" + + olog "github.com/owncloud/ocis/ocis-pkg/log" + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/stretchr/testify/assert" +) + +var bundleScenarios = []struct { + name string + bundle *settingsmsg.Bundle +}{ + { + name: "generic-test-file-resource", + bundle: &settingsmsg.Bundle{ + Id: bundle1, + Type: settingsmsg.Bundle_TYPE_DEFAULT, + Extension: extension1, + DisplayName: "test1", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_FILE, + Id: "beep", + }, + Settings: []*settingsmsg.Setting{ + { + Id: setting1, + Description: "test-desc-1", + DisplayName: "test-displayname-1", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_FILE, + Id: "bleep", + }, + Value: &settingsmsg.Setting_IntValue{ + IntValue: &settingsmsg.Int{ + Min: 0, + Max: 42, + }, + }, + }, + }, + }, + }, + { + name: "generic-test-system-resource", + bundle: &settingsmsg.Bundle{ + Id: bundle2, + Type: settingsmsg.Bundle_TYPE_DEFAULT, + Extension: extension2, + DisplayName: "test1", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: setting2, + Description: "test-desc-2", + DisplayName: "test-displayname-2", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_IntValue{ + IntValue: &settingsmsg.Int{ + Min: 0, + Max: 42, + }, + }, + }, + }, + }, + }, + { + name: "generic-test-role-bundle", + bundle: &settingsmsg.Bundle{ + Id: bundle3, + Type: settingsmsg.Bundle_TYPE_ROLE, + Extension: extension1, + DisplayName: "Role1", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: setting3, + Description: "test-desc-3", + DisplayName: "test-displayname-3", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: setting1, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + }, + }, +} + +func TestBundles(t *testing.T) { + mdc := &MockedMetadataClient{data: make(map[string][]byte)} + s := Store{ + Logger: olog.NewLogger( + olog.Color(true), + olog.Pretty(true), + olog.Level("info"), + ), + + mdc: mdc, + } + + // write bundles + for i := range bundleScenarios { + index := i + t.Run(bundleScenarios[index].name, func(t *testing.T) { + _, err := s.WriteBundle(bundleScenarios[index].bundle) + assert.NoError(t, err) + // TODO: check entry exists + }) + } + + // check that ListBundles only returns bundles with type DEFAULT + bundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{}) + assert.NoError(t, err) + for i := range bundles { + assert.Equal(t, settingsmsg.Bundle_TYPE_DEFAULT, bundles[i].Type) + } + + // check that ListBundles filtered by an id only returns that bundle + filteredBundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{bundle2}) + assert.NoError(t, err) + assert.Equal(t, 1, len(filteredBundles)) + if len(filteredBundles) == 1 { + assert.Equal(t, bundle2, filteredBundles[0].Id) + } + + // check that ListRoles only returns bundles with type ROLE + roles, err := s.ListBundles(settingsmsg.Bundle_TYPE_ROLE, []string{}) + assert.NoError(t, err) + for i := range roles { + assert.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type) + } +} diff --git a/settings/pkg/store/metadata/permissions.go b/settings/pkg/store/metadata/permissions.go new file mode 100644 index 00000000000..7819aea38b2 --- /dev/null +++ b/settings/pkg/store/metadata/permissions.go @@ -0,0 +1,22 @@ +package store + +import ( + "errors" + + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" +) + +// ListPermissionsByResource collects all permissions from the provided roleIDs that match the requested resource +func (s Store) ListPermissionsByResource(resource *settingsmsg.Resource, roleIDs []string) ([]*settingsmsg.Permission, error) { + return nil, errors.New("not implemented") +} + +// ReadPermissionByID finds the permission in the roles, specified by the provided roleIDs +func (s Store) ReadPermissionByID(permissionID string, roleIDs []string) (*settingsmsg.Permission, error) { + return nil, errors.New("not implemented") +} + +// ReadPermissionByName finds the permission in the roles, specified by the provided roleIDs +func (s Store) ReadPermissionByName(name string, roleIDs []string) (*settingsmsg.Permission, error) { + return nil, errors.New("not implemented") +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go new file mode 100644 index 00000000000..054c5fcde5d --- /dev/null +++ b/settings/pkg/store/metadata/store.go @@ -0,0 +1,58 @@ +// Package store implements the go-micro store interface +package store + +import ( + "context" + "os" + + olog "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/owncloud/ocis/settings/pkg/config" + "github.com/owncloud/ocis/settings/pkg/settings" +) + +var ( + // Name is the default name for the settings store + Name = "ocis-settings" + managerName = "metadata" +) + +// MetadataClient is the interface to talk to metadata service +type MetadataClient interface { + SimpleDownload(ctx context.Context, id string) ([]byte, error) + SimpleUpload(ctx context.Context, id string, content []byte) error + Delete(ctx context.Context, id string) error +} + +// Store interacts with the filesystem to manage settings information +type Store struct { + Logger olog.Logger + + mdc MetadataClient +} + +// New creates a new store +func New(cfg *config.Config) settings.Manager { + s := Store{ + //Logger: olog.NewLogger( + // olog.Color(cfg.Log.Color), + // olog.Pretty(cfg.Log.Pretty), + // olog.Level(cfg.Log.Level), + // olog.File(cfg.Log.File), + //), + } + + if _, err := os.Stat(cfg.DataPath); err != nil { + s.Logger.Info().Msgf("creating container on %v", cfg.DataPath) + err = os.MkdirAll(cfg.DataPath, 0700) + + if err != nil { + s.Logger.Err(err).Msgf("providing container on %v", cfg.DataPath) + } + } + + return &s +} + +func init() { + settings.Registry[managerName] = New +} diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go new file mode 100644 index 00000000000..3fe5be0bb0f --- /dev/null +++ b/settings/pkg/store/metadata/store_test.go @@ -0,0 +1,62 @@ +package store + +import "context" + +const ( + // account UUIDs + accountUUID1 = "c4572da7-6142-4383-8fc6-efde3d463036" + //accountUUID2 = "e11f9769-416a-427d-9441-41a0e51391d7" + //accountUUID3 = "633ecd77-1980-412a-8721-bf598a330bb4" + + // extension names + extension1 = "test-extension-1" + extension2 = "test-extension-2" + + // bundle ids + bundle1 = "2f06addf-4fd2-49d5-8f71-00fbd3a3ec47" + bundle2 = "2d745744-749c-4286-8e92-74a24d8331c5" + bundle3 = "d8fd27d1-c00b-4794-a658-416b756a72ff" + + // setting ids + setting1 = "c7ebbc8b-d15a-4f2e-9d7d-d6a4cf858d1a" + setting2 = "3fd9a3d9-20b7-40d4-9294-b22bb5868c10" + setting3 = "24bb9535-3df4-42f1-a622-7c0562bec99f" + + // value ids + value1 = "fd3b6221-dc13-4a22-824d-2480495f1cdb" + value2 = "2a0bd9b0-ca1d-491a-8c56-d2ddfd68ded8" + //value3 = "b42702d2-5e4d-4d73-b133-e1f9e285355e" +) + +// MockedMetadataClient mocks the metadataservice inmemory +type MockedMetadataClient struct { + data map[string][]byte +} + +// SimpleDownload returns nil if not found +func (m *MockedMetadataClient) SimpleDownload(_ context.Context, id string) ([]byte, error) { + return m.data[id], nil +} + +// SimpleUpload can't error +func (m *MockedMetadataClient) SimpleUpload(_ context.Context, id string, content []byte) error { + m.data[id] = content + return nil +} + +// Delete can't error either +func (m *MockedMetadataClient) Delete(_ context.Context, id string) error { + delete(m.data, id) + return nil +} + +// IDExists is a helper to check if an id exists +func (m *MockedMetadataClient) IDExists(id string) bool { + _, ok := m.data[id] + return ok +} + +// IDHasContent returns true if the value stored under id has the given content (converted to string) +func (m *MockedMetadataClient) IDHasContent(id string, content []byte) bool { + return string(m.data[id]) == string(content) +} diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go new file mode 100644 index 00000000000..d7a78421ee6 --- /dev/null +++ b/settings/pkg/store/metadata/values.go @@ -0,0 +1,31 @@ +// Package store implements the go-micro store interface +package store + +import ( + "errors" + + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" +) + +// ListValues reads all values that match the given bundleId and accountUUID. +// If the bundleId is empty, it's ignored for filtering. +// If the accountUUID is empty, only values with empty accountUUID are returned. +// If the accountUUID is not empty, values with an empty or with a matching accountUUID are returned. +func (s Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, error) { + return nil, errors.New("not implemented") +} + +// ReadValue tries to find a value by the given valueId within the dataPath +func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { + return nil, errors.New("not implemented") +} + +// ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers +func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) { + return nil, errors.New("not implemented") +} + +// WriteValue writes the given value into a file within the dataPath +func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { + return nil, errors.New("not implemented") +} diff --git a/settings/pkg/store/metadata/values_test.go b/settings/pkg/store/metadata/values_test.go new file mode 100644 index 00000000000..4881f958196 --- /dev/null +++ b/settings/pkg/store/metadata/values_test.go @@ -0,0 +1,72 @@ +package store + +import ( + "testing" + + olog "github.com/owncloud/ocis/ocis-pkg/log" + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/stretchr/testify/assert" +) + +var valueScenarios = []struct { + name string + value *settingsmsg.Value +}{ + { + name: "generic-test-with-system-resource", + value: &settingsmsg.Value{ + Id: value1, + BundleId: bundle1, + SettingId: setting1, + AccountUuid: accountUUID1, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Value_StringValue{ + StringValue: "lalala", + }, + }, + }, + { + name: "generic-test-with-file-resource", + value: &settingsmsg.Value{ + Id: value2, + BundleId: bundle1, + SettingId: setting2, + AccountUuid: accountUUID1, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_FILE, + Id: "adfba82d-919a-41c3-9cd1-5a3f83b2bf76", + }, + Value: &settingsmsg.Value_StringValue{ + StringValue: "tralala", + }, + }, + }, +} + +func TestValues(t *testing.T) { + mdc := &MockedMetadataClient{data: make(map[string][]byte)} + s := Store{ + Logger: olog.NewLogger( + olog.Color(true), + olog.Pretty(true), + olog.Level("info"), + ), + mdc: mdc, + } + for i := range valueScenarios { + index := i + t.Run(valueScenarios[index].name, func(t *testing.T) { + value := valueScenarios[index].value + v, err := s.WriteValue(value) + assert.NoError(t, err) + assert.Equal(t, value, v) + + v, err = s.ReadValue(value.Id) + assert.NoError(t, err) + assert.Equal(t, value, v) + + }) + } +} diff --git a/settings/pkg/store/registry.go b/settings/pkg/store/registry.go index 29186466e34..2359e0d392d 100644 --- a/settings/pkg/store/registry.go +++ b/settings/pkg/store/registry.go @@ -3,4 +3,5 @@ package store import ( // init filesystem store _ "github.com/owncloud/ocis/settings/pkg/store/filesystem" + _ "github.com/owncloud/ocis/settings/pkg/store/metadata" ) From 0d4f8df2f6aeb7a6a242f707aa61d694eed98b2e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 24 Feb 2022 15:13:06 +0100 Subject: [PATCH 02/42] Settings: activate metadata store to see tests failing Signed-off-by: jkoberg --- settings/pkg/service/v0/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index b7d500acfad..5c372954bcf 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -15,7 +15,7 @@ import ( settingssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/settings/v0" "github.com/owncloud/ocis/settings/pkg/config" "github.com/owncloud/ocis/settings/pkg/settings" - store "github.com/owncloud/ocis/settings/pkg/store/filesystem" + store "github.com/owncloud/ocis/settings/pkg/store/metadata" merrors "go-micro.dev/v4/errors" "go-micro.dev/v4/metadata" "google.golang.org/protobuf/types/known/emptypb" From 297a0063abb3a8c0c116e0e9565d830c983c74c2 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 24 Feb 2022 15:17:13 +0100 Subject: [PATCH 03/42] add changelog Signed-off-by: jkoberg --- changelog/unreleased/store-settings-in-metadata-service.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/store-settings-in-metadata-service.md diff --git a/changelog/unreleased/store-settings-in-metadata-service.md b/changelog/unreleased/store-settings-in-metadata-service.md new file mode 100644 index 00000000000..16fd2340821 --- /dev/null +++ b/changelog/unreleased/store-settings-in-metadata-service.md @@ -0,0 +1,5 @@ +Change: settings service now stores its data via metadata service + +Instead of writing files to disk it will use metadata service to do so + +https://github.com/owncloud/ocis/pull/3232 From a762e3cf6900390ba2a11b3dbd88e5c22660cf1f Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 24 Feb 2022 18:16:58 +0100 Subject: [PATCH 04/42] make assignment unittests green Signed-off-by: jkoberg --- settings/pkg/store/metadata/assignments.go | 80 ++++++++++++++++++- .../pkg/store/metadata/assignments_test.go | 43 +++++----- settings/pkg/store/metadata/bundles.go | 17 ++-- settings/pkg/store/metadata/store.go | 1 + settings/pkg/store/metadata/store_test.go | 27 ++++++- 5 files changed, 137 insertions(+), 31 deletions(-) diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index fc9d4431f54..f2db6c57388 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -2,22 +2,94 @@ package store import ( - "errors" + "encoding/json" + "fmt" + "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) +var accountsFolderLocation = "settings/accounts" + // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { - return nil, errors.New("not implemented") + assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) + if err != nil { + return nil, err + } + + var ass []*settingsmsg.UserRoleAssignment + for _, assID := range assIDs { + b, err := s.mdc.SimpleDownload(nil, assignmentPath(accountUUID, assID)) + if err != nil { + return nil, err + } + + a := &settingsmsg.UserRoleAssignment{} + err = json.Unmarshal(b, a) + if err != nil { + return nil, err + } + + ass = append(ass, a) + } + return ass, 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) { - return nil, errors.New("not implemented") + // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" + assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) + if err != nil { + return nil, err + } + + for _, assID := range assIDs { + err := s.mdc.Delete(nil, assignmentPath(accountUUID, assID)) + if err != nil { + return nil, err + } + } + ass := &settingsmsg.UserRoleAssignment{ + Id: uuid.Must(uuid.NewV4()).String(), + AccountUuid: accountUUID, + RoleId: roleID, + } + b, err := json.Marshal(ass) + if err != nil { + return nil, err + } + return ass, s.mdc.SimpleUpload(nil, 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 { - return errors.New("not implemented") + accounts, err := s.mdc.ReadDir(nil, accountsFolderLocation) + if err != nil { + return err + } + + // TODO: use indexer to avoid spamming Metadata service + for _, accID := range accounts { + assIDs, err := s.mdc.ReadDir(nil, accountPath(accID)) + if err != nil { + // TODO: error? + continue + } + + for _, assID := range assIDs { + if assID == assignmentID { + return s.mdc.Delete(nil, assignmentPath(accID, assID)) + } + } + } + return fmt.Errorf("assignmentID '%s' not found", assignmentID) +} + +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) } diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index 654b8af25f0..33052a6487c 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -6,7 +6,7 @@ import ( olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -109,25 +109,25 @@ func TestAssignmentUniqueness(t *testing.T) { scenario := scenario t.Run(scenario.name, func(t *testing.T) { firstAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole) - assert.NoError(t, err) - assert.Equal(t, firstAssignment.RoleId, scenario.firstRole) + require.NoError(t, err) + require.Equal(t, firstAssignment.RoleId, scenario.firstRole) // TODO: check entry exists list, err := s.ListRoleAssignments(scenario.userID) - assert.NoError(t, err) - assert.Equal(t, 1, len(list)) - assert.Equal(t, list[0].RoleId, scenario.firstRole) + require.NoError(t, err) + require.Equal(t, 1, len(list)) + require.Equal(t, list[0].RoleId, scenario.firstRole) // creating another assignment shouldn't add another entry, as we support max one role per user. // assigning the second role should remove the old secondAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.secondRole) - assert.NoError(t, err) - assert.Equal(t, secondAssignment.RoleId, scenario.secondRole) + require.NoError(t, err) + require.Equal(t, secondAssignment.RoleId, scenario.secondRole) list, err = s.ListRoleAssignments(scenario.userID) - assert.NoError(t, err) - assert.Equal(t, 1, len(list)) - assert.Equal(t, list[0].RoleId, scenario.secondRole) + require.NoError(t, err) + require.Equal(t, 1, len(list)) + require.Equal(t, list[0].RoleId, scenario.secondRole) }) } } @@ -151,26 +151,27 @@ func TestDeleteAssignment(t *testing.T) { scenario := scenario t.Run(scenario.name, func(t *testing.T) { assignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole) - assert.NoError(t, err) - assert.Equal(t, assignment.RoleId, scenario.firstRole) + require.NoError(t, err) + require.Equal(t, assignment.RoleId, scenario.firstRole) // TODO: uncomment - // assert.True(t, mdc.IDExists(assignment.RoleId)) + // require.True(t, mdc.IDExists(assignment.RoleId)) list, err := s.ListRoleAssignments(scenario.userID) - assert.NoError(t, err) - assert.Equal(t, 1, len(list)) + require.NoError(t, err) + require.Equal(t, 1, len(list)) + require.Equal(t, assignment.Id, list[0].Id) err = s.RemoveRoleAssignment(assignment.Id) - assert.NoError(t, err) + require.NoError(t, err) // TODO: uncomment - // assert.False(t, mdc.IDExists(assignment.RoleId)) + // require.False(t, mdc.IDExists(assignment.RoleId)) list, err = s.ListRoleAssignments(scenario.userID) - assert.NoError(t, err) - assert.Equal(t, 0, len(list)) + require.NoError(t, err) + require.Equal(t, 0, len(list)) err = s.RemoveRoleAssignment(assignment.Id) - assert.Error(t, err) + require.Error(t, err) // TODO: do we want a custom error message? }) } diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 29af5e91306..8a59d907453 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -2,14 +2,13 @@ package store import ( + "encoding/json" "errors" - "sync" + "fmt" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) -var m = &sync.RWMutex{} - // ListBundles returns all bundles in the dataPath folder that match the given type. func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { return nil, errors.New("not implemented") @@ -25,9 +24,13 @@ func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { return nil, errors.New("not implemented") } -// WriteBundle writes the given record into a file within the dataPath. +// WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { - return nil, errors.New("not implemented") + b, err := json.Marshal(record) + if err != nil { + return nil, err + } + return record, s.mdc.SimpleUpload(nil, bundlePath(record.Id), b) } // AddSettingToBundle adds the given setting to the bundle with the given bundleID. @@ -39,3 +42,7 @@ func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error { return errors.New("not implemented") } + +func bundlePath(id string) string { + return fmt.Sprintf("bundle/%s", id) +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 054c5fcde5d..4f33c2a72f2 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -21,6 +21,7 @@ type MetadataClient interface { SimpleDownload(ctx context.Context, id string) ([]byte, error) SimpleUpload(ctx context.Context, id string, content []byte) error Delete(ctx context.Context, id string) error + ReadDir(ctx context.Context, id string) ([]string, error) } // Store interacts with the filesystem to manage settings information diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index 3fe5be0bb0f..8fdf200a877 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -1,6 +1,9 @@ package store -import "context" +import ( + "context" + "strings" +) const ( // account UUIDs @@ -33,6 +36,13 @@ type MockedMetadataClient struct { data map[string][]byte } +func keys(m map[string][]byte) (s []string) { + for k := range m { + s = append(s, k) + } + return +} + // SimpleDownload returns nil if not found func (m *MockedMetadataClient) SimpleDownload(_ context.Context, id string) ([]byte, error) { return m.data[id], nil @@ -50,6 +60,21 @@ func (m *MockedMetadataClient) Delete(_ context.Context, id string) error { return nil } +// ReadDir returns nil, nil if not found +// Known flaw: lists also subdirs +func (m *MockedMetadataClient) ReadDir(_ context.Context, id string) ([]string, error) { + var out []string + for k := range m.data { + if strings.HasPrefix(k, id) { + dir := strings.TrimPrefix(k, id+"/") + // filter subfolders the lame way + s := strings.Trim(strings.SplitAfter(dir, "/")[0], "/") + out = append(out, s) + } + } + return out, nil +} + // IDExists is a helper to check if an id exists func (m *MockedMetadataClient) IDExists(id string) bool { _, ok := m.data[id] From 45c85f423710c73be9763d03d271dea5a3cafe92 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 24 Feb 2022 18:41:55 +0100 Subject: [PATCH 05/42] make bundle unit tests green Signed-off-by: jkoberg --- settings/pkg/store/metadata/bundles.go | 28 +++++++++++++++++++-- settings/pkg/store/metadata/bundles_test.go | 28 +++++++++++---------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 8a59d907453..ee09e583e31 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -11,12 +11,36 @@ import ( // ListBundles returns all bundles in the dataPath folder that match the given type. func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { - return nil, errors.New("not implemented") + var bundles []*settingsmsg.Bundle + for _, id := range bundleIDs { + b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) + if err != nil { + return nil, err + } + + bundle := &settingsmsg.Bundle{} + err = json.Unmarshal(b, bundle) + if err != nil { + return nil, err + } + + if bundle.Type == bundleType { + bundles = append(bundles, bundle) + } + + } + return bundles, nil } // ReadBundle tries to find a bundle by the given id within the dataPath. func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { - return nil, errors.New("not implemented") + b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) + if err != nil { + return nil, err + } + + bundle := &settingsmsg.Bundle{} + return bundle, json.Unmarshal(b, bundle) } // ReadSetting tries to find a setting by the given id within the dataPath. diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go index 13c889bc1b5..541945e7d7c 100644 --- a/settings/pkg/store/metadata/bundles_test.go +++ b/settings/pkg/store/metadata/bundles_test.go @@ -5,7 +5,7 @@ import ( olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var bundleScenarios = []struct { @@ -115,33 +115,35 @@ func TestBundles(t *testing.T) { // write bundles for i := range bundleScenarios { - index := i - t.Run(bundleScenarios[index].name, func(t *testing.T) { - _, err := s.WriteBundle(bundleScenarios[index].bundle) - assert.NoError(t, err) - // TODO: check entry exists + b := bundleScenarios[i] + t.Run(b.name, func(t *testing.T) { + _, err := s.WriteBundle(b.bundle) + require.NoError(t, err) + bundle, err := s.ReadBundle(b.bundle.Id) + require.NoError(t, err) + require.Equal(t, b.bundle, bundle) }) } // check that ListBundles only returns bundles with type DEFAULT bundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{}) - assert.NoError(t, err) + require.NoError(t, err) for i := range bundles { - assert.Equal(t, settingsmsg.Bundle_TYPE_DEFAULT, bundles[i].Type) + require.Equal(t, settingsmsg.Bundle_TYPE_DEFAULT, bundles[i].Type) } // check that ListBundles filtered by an id only returns that bundle filteredBundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{bundle2}) - assert.NoError(t, err) - assert.Equal(t, 1, len(filteredBundles)) + require.NoError(t, err) + require.Equal(t, 1, len(filteredBundles)) if len(filteredBundles) == 1 { - assert.Equal(t, bundle2, filteredBundles[0].Id) + require.Equal(t, bundle2, filteredBundles[0].Id) } // check that ListRoles only returns bundles with type ROLE roles, err := s.ListBundles(settingsmsg.Bundle_TYPE_ROLE, []string{}) - assert.NoError(t, err) + require.NoError(t, err) for i := range roles { - assert.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type) + require.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type) } } From 721026654d4810f278d93a59db6af9a860d605b2 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 25 Feb 2022 15:58:48 +0100 Subject: [PATCH 06/42] make values unit tests green Signed-off-by: jkoberg --- settings/pkg/store/metadata/values.go | 19 +++++++++++++++++-- settings/pkg/store/metadata/values_test.go | 10 +++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index d7a78421ee6..16a89b7d1fb 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -2,7 +2,9 @@ package store import ( + "encoding/json" "errors" + "fmt" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) @@ -17,7 +19,12 @@ func (s Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, e // ReadValue tries to find a value by the given valueId within the dataPath func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { - return nil, errors.New("not implemented") + b, err := s.mdc.SimpleDownload(nil, valuePath(valueID)) + if err != nil { + return nil, err + } + val := &settingsmsg.Value{} + return val, json.Unmarshal(b, val) } // ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers @@ -27,5 +34,13 @@ func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*set // WriteValue writes the given value into a file within the dataPath func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { - return nil, errors.New("not implemented") + b, err := json.Marshal(value) + if err != nil { + return nil, err + } + return value, s.mdc.SimpleUpload(nil, valuePath(value.Id), b) +} + +func valuePath(id string) string { + return fmt.Sprintf("%s/%s", "settings/values", id) } diff --git a/settings/pkg/store/metadata/values_test.go b/settings/pkg/store/metadata/values_test.go index 4881f958196..0efc4a2034e 100644 --- a/settings/pkg/store/metadata/values_test.go +++ b/settings/pkg/store/metadata/values_test.go @@ -5,7 +5,7 @@ import ( olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var valueScenarios = []struct { @@ -60,12 +60,12 @@ func TestValues(t *testing.T) { t.Run(valueScenarios[index].name, func(t *testing.T) { value := valueScenarios[index].value v, err := s.WriteValue(value) - assert.NoError(t, err) - assert.Equal(t, value, v) + require.NoError(t, err) + require.Equal(t, value, v) v, err = s.ReadValue(value.Id) - assert.NoError(t, err) - assert.Equal(t, value, v) + require.NoError(t, err) + require.Equal(t, value, v) }) } From 11a8b75b2e2ae282c4aec5a4d4505127a93c4e5e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 25 Feb 2022 17:28:36 +0100 Subject: [PATCH 07/42] use cs3storage in metadatastorage Signed-off-by: jkoberg --- go.mod | 2 +- go.sum | 2 + settings/pkg/store/metadata/assignments.go | 15 +++--- .../pkg/store/metadata/assignments_test.go | 2 +- settings/pkg/store/metadata/bundles.go | 2 +- settings/pkg/store/metadata/bundles_test.go | 2 +- settings/pkg/store/metadata/store.go | 52 ++++++++++++++----- settings/pkg/store/metadata/store_test.go | 28 +++++++++- settings/pkg/store/metadata/values.go | 2 +- settings/pkg/store/metadata/values_test.go | 2 +- 10 files changed, 80 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index 49f837a598d..48acfd007b2 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.0 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 - github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a + github.com/cs3org/reva v1.16.1-0.20220225100612-8b6ec49c4068 github.com/disintegration/imaging v1.6.2 github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733 github.com/go-chi/chi/v5 v5.0.7 diff --git a/go.sum b/go.sum index 4557a5b88d9..25b4d537c85 100644 --- a/go.sum +++ b/go.sum @@ -341,6 +341,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvba github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a h1:LgwfJ4N+ekLRFOK2vwVKbgtnQYYcrNiMtu5kekJvJ54= github.com/cs3org/reva v1.16.1-0.20220224115936-e17c65a48a5a/go.mod h1:M+Nausi93NaMDoinwiUX/Ekgrp/RrYv715FG5KrIarY= +github.com/cs3org/reva v1.16.1-0.20220225100612-8b6ec49c4068 h1:erH/cfXGizPxLSWGwDf4iyZW+mU/pcPRFlYtpauza5s= +github.com/cs3org/reva v1.16.1-0.20220225100612-8b6ec49c4068/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index f2db6c57388..9c2dcbb1ee2 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -9,8 +9,6 @@ import ( settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) -var accountsFolderLocation = "settings/accounts" - // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) @@ -39,17 +37,16 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleA // WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account. func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) { // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" - assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) + err := s.mdc.Delete(nil, accountPath(accountUUID)) if err != nil { - return nil, err + // TODO: How to differentiate between 'not found' and other errors? } - for _, assID := range assIDs { - err := s.mdc.Delete(nil, assignmentPath(accountUUID, assID)) - if err != nil { - return nil, err - } + err = s.mdc.MakeDirIfNotExist(nil, accountPath(accountUUID)) + if err != nil { + return nil, err } + ass := &settingsmsg.UserRoleAssignment{ Id: uuid.Must(uuid.NewV4()).String(), AccountUuid: accountUUID, diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index 33052a6487c..a0353b8d6d2 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -24,7 +24,7 @@ var ( olog.Level("info"), ) - mdc = &MockedMetadataClient{data: make(map[string][]byte)} + mdc = NewMDC() bundles = []*settingsmsg.Bundle{ { diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index ee09e583e31..16e700d243c 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -68,5 +68,5 @@ func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error } func bundlePath(id string) string { - return fmt.Sprintf("bundle/%s", id) + return fmt.Sprintf("%s/%s", bundleFolderLocation, id) } diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go index 541945e7d7c..8a690a7deb2 100644 --- a/settings/pkg/store/metadata/bundles_test.go +++ b/settings/pkg/store/metadata/bundles_test.go @@ -102,7 +102,7 @@ var bundleScenarios = []struct { } func TestBundles(t *testing.T) { - mdc := &MockedMetadataClient{data: make(map[string][]byte)} + mdc := NewMDC() s := Store{ Logger: olog.NewLogger( olog.Color(true), diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 4f33c2a72f2..6294392877a 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -3,8 +3,10 @@ package store import ( "context" - "os" + "fmt" + "log" + "github.com/cs3org/reva/pkg/storage/utils/metadata" olog "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/settings/pkg/config" "github.com/owncloud/ocis/settings/pkg/settings" @@ -12,8 +14,13 @@ import ( var ( // Name is the default name for the settings store - Name = "ocis-settings" - managerName = "metadata" + Name = "ocis-settings" + managerName = "metadata" + settingsSpaceID = "f1bdd61a-da7c-49fc-8203-0558109d1b4f" // uuid.Must(uuid.NewV4()).String() + rootFolderLocation = "settings" + bundleFolderLocation = "settings/bundles" + accountsFolderLocation = "settings/accounts" + valuesFolderLocation = "settings/values" ) // MetadataClient is the interface to talk to metadata service @@ -22,6 +29,7 @@ type MetadataClient interface { SimpleUpload(ctx context.Context, id string, content []byte) error Delete(ctx context.Context, id string) error ReadDir(ctx context.Context, id string) ([]string, error) + MakeDirIfNotExist(ctx context.Context, id string) error } // Store interacts with the filesystem to manage settings information @@ -35,23 +43,43 @@ type Store struct { func New(cfg *config.Config) settings.Manager { s := Store{ //Logger: olog.NewLogger( - // olog.Color(cfg.Log.Color), - // olog.Pretty(cfg.Log.Pretty), - // olog.Level(cfg.Log.Level), - // olog.File(cfg.Log.File), + //olog.Color(cfg.Log.Color), + //olog.Pretty(cfg.Log.Pretty), + //olog.Level(cfg.Log.Level), + //olog.File(cfg.Log.File), //), } - if _, err := os.Stat(cfg.DataPath); err != nil { - s.Logger.Info().Msgf("creating container on %v", cfg.DataPath) - err = os.MkdirAll(cfg.DataPath, 0700) + s.mdc = NewMetadataClient(cfg) + return &s +} + +// NewMetadataClient returns the MetadataClient +func NewMetadataClient(cfg *config.Config) MetadataClient { + mdc, err := metadata.NewCS3Storage("127.0.0.1:9142", "127.0.0.1:9215", "058bff95-6708-4fe5-91e4-9ea3d377588b", "change-me-please") + if err != nil { + log.Fatal("error connecting to mdc:", err) + } + fmt.Println(settingsSpaceID) + err = mdc.Init(nil, settingsSpaceID) + if err != nil { + log.Fatal("error initializing mdc:", err) + } + + for _, p := range []string{ + rootFolderLocation, + accountsFolderLocation, + bundleFolderLocation, + valuesFolderLocation, + } { + err = mdc.MakeDirIfNotExist(nil, p) if err != nil { - s.Logger.Err(err).Msgf("providing container on %v", cfg.DataPath) + log.Fatalf("error creating settings folder '%s': %s", p, err) } } + return mdc - return &s } func init() { diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index 8fdf200a877..326ca64765d 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -3,6 +3,8 @@ package store import ( "context" "strings" + + "github.com/owncloud/ocis/settings/pkg/config" ) const ( @@ -31,11 +33,25 @@ const ( //value3 = "b42702d2-5e4d-4d73-b133-e1f9e285355e" ) +// use "unit" or "integration" do define test type. You need a running ocis instance for integration tests +var testtype = "unit" + // MockedMetadataClient mocks the metadataservice inmemory type MockedMetadataClient struct { data map[string][]byte } +// NewMDC instantiates a mocked MetadataClient +func NewMDC() MetadataClient { + switch testtype { + case "unit": + return &MockedMetadataClient{data: make(map[string][]byte)} + case "integration": + return NewMetadataClient(&config.Config{}) + } + return nil +} + func keys(m map[string][]byte) (s []string) { for k := range m { s = append(s, k) @@ -56,12 +72,15 @@ func (m *MockedMetadataClient) SimpleUpload(_ context.Context, id string, conten // Delete can't error either func (m *MockedMetadataClient) Delete(_ context.Context, id string) error { - delete(m.data, id) + for k := range m.data { + if strings.HasPrefix(k, id) { + delete(m.data, k) + } + } return nil } // ReadDir returns nil, nil if not found -// Known flaw: lists also subdirs func (m *MockedMetadataClient) ReadDir(_ context.Context, id string) ([]string, error) { var out []string for k := range m.data { @@ -75,6 +94,11 @@ func (m *MockedMetadataClient) ReadDir(_ context.Context, id string) ([]string, return out, nil } +// MakeDirIfNotExist does nothing +func (m *MockedMetadataClient) MakeDirIfNotExist(_ context.Context, id string) error { + return nil +} + // IDExists is a helper to check if an id exists func (m *MockedMetadataClient) IDExists(id string) bool { _, ok := m.data[id] diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index 16a89b7d1fb..50421b5d5e6 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -42,5 +42,5 @@ func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) } func valuePath(id string) string { - return fmt.Sprintf("%s/%s", "settings/values", id) + return fmt.Sprintf("%s/%s", valuesFolderLocation, id) } diff --git a/settings/pkg/store/metadata/values_test.go b/settings/pkg/store/metadata/values_test.go index 0efc4a2034e..2921e3d0e56 100644 --- a/settings/pkg/store/metadata/values_test.go +++ b/settings/pkg/store/metadata/values_test.go @@ -46,7 +46,7 @@ var valueScenarios = []struct { } func TestValues(t *testing.T) { - mdc := &MockedMetadataClient{data: make(map[string][]byte)} + mdc := NewMDC() s := Store{ Logger: olog.NewLogger( olog.Color(true), From 2452d015066902f5669cd578a57c003476e16965 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 26 Feb 2022 13:18:27 +0100 Subject: [PATCH 08/42] lazy initialize metadataclient Signed-off-by: jkoberg --- ocis-pkg/roles/manager.go | 1 + settings/pkg/service/v0/service.go | 5 ++ settings/pkg/store/metadata/assignments.go | 3 ++ settings/pkg/store/metadata/bundles.go | 3 ++ settings/pkg/store/metadata/store.go | 53 ++++++++++++++++++---- settings/pkg/store/metadata/store_test.go | 7 ++- settings/pkg/store/metadata/values.go | 2 + 7 files changed, 64 insertions(+), 10 deletions(-) diff --git a/ocis-pkg/roles/manager.go b/ocis-pkg/roles/manager.go index 1878db0200a..6c58239ed75 100644 --- a/ocis-pkg/roles/manager.go +++ b/ocis-pkg/roles/manager.go @@ -46,6 +46,7 @@ func (m *Manager) List(ctx context.Context, roleIDs []string) []*settingsmsg.Bun res, err := m.roleService.ListRoles(ctx, request) if err != nil { m.logger.Debug().Err(err).Msg("failed to fetch roles by roleIDs") + return nil } for _, role := range res.Bundles { m.cache.set(role.Id, role) diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index 5c372954bcf..87dc662e2d9 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -88,6 +88,11 @@ func (g Service) CheckPermission(ctx context.Context, req *permissions.CheckPerm // RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist. func (g Service) RegisterDefaultRoles() { + // TODO: we can't register on service start any more because metadata might not be up yet + // we need to lazy initialize + if true { + return + } // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). has to happen only once. for _, role := range generateBundlesDefaultRoles() { bundleID := role.Extension + "." + role.Id diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 9c2dcbb1ee2..6c311b8b213 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -11,6 +11,7 @@ import ( // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { + s.Init() assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) if err != nil { return nil, err @@ -36,6 +37,7 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleA // 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() // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" err := s.mdc.Delete(nil, accountPath(accountUUID)) if err != nil { @@ -61,6 +63,7 @@ func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.Use // RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account. func (s Store) RemoveRoleAssignment(assignmentID string) error { + s.Init() accounts, err := s.mdc.ReadDir(nil, accountsFolderLocation) if err != nil { return err diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 16e700d243c..3dca510b0b8 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -11,6 +11,7 @@ import ( // ListBundles returns all bundles in the dataPath folder that match the given type. func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { + s.Init() var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) @@ -34,6 +35,7 @@ func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []strin // ReadBundle tries to find a bundle by the given id within the dataPath. func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { + s.Init() b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) if err != nil { return nil, err @@ -50,6 +52,7 @@ func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { // WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { + s.Init() b, err := json.Marshal(record) if err != nil { return nil, err diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 6294392877a..791ffbe2907 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -3,8 +3,8 @@ package store import ( "context" - "fmt" "log" + "sync" "github.com/cs3org/reva/pkg/storage/utils/metadata" olog "github.com/owncloud/ocis/ocis-pkg/log" @@ -30,6 +30,7 @@ type MetadataClient interface { Delete(ctx context.Context, id string) error ReadDir(ctx context.Context, id string) ([]string, error) MakeDirIfNotExist(ctx context.Context, id string) error + Init(ctx context.Context, id string) error } // Store interacts with the filesystem to manage settings information @@ -37,6 +38,34 @@ type Store struct { Logger olog.Logger mdc MetadataClient + cfg *config.Config + + init *sync.Once + l *sync.Mutex +} + +// Init initialize the store once, later calls are noops +func (s Store) Init() { + if s.mdc != nil { + return + } + + s.l.Lock() + defer s.l.Unlock() + var err error + s.init.Do(func() { + //b := backoff.NewExponentialBackOff() + //b.MaxElapsedTime = 4 * time.Second + //backoff.Retry(func() error { + err = s.initMetadataClient() + //return err + + //}, b) + + }) + if err != nil { + log.Fatal(err) + } } // New creates a new store @@ -48,9 +77,10 @@ func New(cfg *config.Config) settings.Manager { //olog.Level(cfg.Log.Level), //olog.File(cfg.Log.File), //), + l: &sync.Mutex{}, + init: &sync.Once{}, } - s.mdc = NewMetadataClient(cfg) return &s } @@ -60,11 +90,17 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { if err != nil { log.Fatal("error connecting to mdc:", err) } + return mdc + +} - fmt.Println(settingsSpaceID) - err = mdc.Init(nil, settingsSpaceID) +// we need to lazy initialize the MetadataClient because metadata service might not be ready +func (s Store) initMetadataClient() error { + s.mdc = NewMetadataClient(s.cfg) + + err := s.mdc.Init(nil, settingsSpaceID) if err != nil { - log.Fatal("error initializing mdc:", err) + return err } for _, p := range []string{ @@ -73,13 +109,12 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { bundleFolderLocation, valuesFolderLocation, } { - err = mdc.MakeDirIfNotExist(nil, p) + err = s.mdc.MakeDirIfNotExist(nil, p) if err != nil { - log.Fatalf("error creating settings folder '%s': %s", p, err) + return err } } - return mdc - + return nil } func init() { diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index 326ca64765d..c42f3d02772 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -95,7 +95,12 @@ func (m *MockedMetadataClient) ReadDir(_ context.Context, id string) ([]string, } // MakeDirIfNotExist does nothing -func (m *MockedMetadataClient) MakeDirIfNotExist(_ context.Context, id string) error { +func (*MockedMetadataClient) MakeDirIfNotExist(_ context.Context, _ string) error { + return nil +} + +// Init does nothing +func (*MockedMetadataClient) Init(_ context.Context, _ string) error { return nil } diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index 50421b5d5e6..4f7c23c5393 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -19,6 +19,7 @@ func (s Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, e // ReadValue tries to find a value by the given valueId within the dataPath func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { + s.Init() b, err := s.mdc.SimpleDownload(nil, valuePath(valueID)) if err != nil { return nil, err @@ -34,6 +35,7 @@ func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*set // WriteValue writes the given value into a file within the dataPath func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { + s.Init() b, err := json.Marshal(value) if err != nil { return nil, err From 588a731d6df839b9b52b1ef6c5cbba63ff6e2269 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 26 Feb 2022 14:00:39 +0100 Subject: [PATCH 09/42] delay creation of default roles Signed-off-by: jkoberg --- settings/pkg/service/v0/service.go | 26 +++++++++++-------------- settings/pkg/settings/settings.go | 2 +- settings/pkg/store/filesystem/store.go | 3 ++- settings/pkg/store/metadata/store.go | 27 +++++++++++++++----------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index 87dc662e2d9..747b1ce9376 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -32,12 +32,11 @@ type Service struct { // NewService returns a service implementation for Service. func NewService(cfg *config.Config, logger log.Logger) Service { service := Service{ - id: "ocis-settings", - config: cfg, - logger: logger, - manager: store.New(cfg), + id: "ocis-settings", + config: cfg, + logger: logger, } - service.RegisterDefaultRoles() + service.manager = store.New(cfg, service.RegisterDefaultRoles) return service } @@ -87,23 +86,20 @@ func (g Service) CheckPermission(ctx context.Context, req *permissions.CheckPerm } // RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist. -func (g Service) RegisterDefaultRoles() { - // TODO: we can't register on service start any more because metadata might not be up yet - // we need to lazy initialize - if true { - return - } +// NOTE: we can't register on service start any more because metadata might not be up yet +// we need to lazy initialize +func (g Service) RegisterDefaultRoles(m settings.Manager) { // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). has to happen only once. for _, role := range generateBundlesDefaultRoles() { bundleID := role.Extension + "." + role.Id // check if the role already exists - bundle, _ := g.manager.ReadBundle(role.Id) + bundle, _ := m.ReadBundle(role.Id) if bundle != nil { g.logger.Debug().Str("bundleID", bundleID).Msg("bundle already exists. skipping.") continue } // create the role - _, err := g.manager.WriteBundle(role) + _, err := m.WriteBundle(role) if err != nil { g.logger.Error().Err(err).Str("bundleID", bundleID).Msg("failed to register bundle") } @@ -111,7 +107,7 @@ func (g Service) RegisterDefaultRoles() { } for _, req := range generatePermissionRequests() { - _, err := g.manager.AddSettingToBundle(req.GetBundleId(), req.GetSetting()) + _, err := m.AddSettingToBundle(req.GetBundleId(), req.GetSetting()) if err != nil { g.logger.Error(). Err(err). @@ -122,7 +118,7 @@ func (g Service) RegisterDefaultRoles() { } for _, req := range defaultRoleAssignments() { - if _, err := g.manager.WriteRoleAssignment(req.AccountUuid, req.RoleId); err != nil { + if _, err := m.WriteRoleAssignment(req.AccountUuid, req.RoleId); err != nil { g.logger.Error().Err(err).Msg("failed to register role assignment") } } diff --git a/settings/pkg/settings/settings.go b/settings/pkg/settings/settings.go index 9132423e8f4..0f3cf9fe52c 100644 --- a/settings/pkg/settings/settings.go +++ b/settings/pkg/settings/settings.go @@ -16,7 +16,7 @@ var ( ) // RegisterFunc stores store constructors -type RegisterFunc func(*config.Config) Manager +type RegisterFunc func(*config.Config, func(Manager)) Manager // Manager combines service interfaces for abstraction of storage implementations type Manager interface { diff --git a/settings/pkg/store/filesystem/store.go b/settings/pkg/store/filesystem/store.go index ccd0fe0111a..fee4c7ebd3f 100644 --- a/settings/pkg/store/filesystem/store.go +++ b/settings/pkg/store/filesystem/store.go @@ -22,7 +22,7 @@ type Store struct { } // New creates a new store -func New(cfg *config.Config) settings.Manager { +func New(cfg *config.Config, initStore func(settings.Manager)) settings.Manager { s := Store{ //Logger: olog.NewLogger( // olog.Color(cfg.Log.Color), @@ -42,6 +42,7 @@ func New(cfg *config.Config) settings.Manager { } s.dataPath = cfg.DataPath + initStore(&s) return &s } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 791ffbe2907..aac096ec4df 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -37,8 +37,9 @@ type MetadataClient interface { type Store struct { Logger olog.Logger - mdc MetadataClient - cfg *config.Config + mdc MetadataClient + cfg *config.Config + initStore func(settings.Manager) init *sync.Once l *sync.Mutex @@ -69,16 +70,17 @@ func (s Store) Init() { } // New creates a new store -func New(cfg *config.Config) settings.Manager { +func New(cfg *config.Config, initstore func(settings.Manager)) settings.Manager { s := Store{ - //Logger: olog.NewLogger( - //olog.Color(cfg.Log.Color), - //olog.Pretty(cfg.Log.Pretty), - //olog.Level(cfg.Log.Level), - //olog.File(cfg.Log.File), - //), - l: &sync.Mutex{}, - init: &sync.Once{}, + Logger: olog.NewLogger( + olog.Color(cfg.Log.Color), + olog.Pretty(cfg.Log.Pretty), + olog.Level(cfg.Log.Level), + olog.File(cfg.Log.File), + ), + initStore: initstore, + l: &sync.Mutex{}, + init: &sync.Once{}, } return &s @@ -98,6 +100,7 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { func (s Store) initMetadataClient() error { s.mdc = NewMetadataClient(s.cfg) + // TODO: this fails because of authentication issues err := s.mdc.Init(nil, settingsSpaceID) if err != nil { return err @@ -114,6 +117,8 @@ func (s Store) initMetadataClient() error { return err } } + + s.initStore(s) return nil } From e23448f5812d0f2e29aaaaab4325be1b030e2c2e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 28 Feb 2022 15:35:33 +0100 Subject: [PATCH 10/42] return listaccounts permission when mdc is not yet set Signed-off-by: jkoberg --- settings/pkg/store/metadata/bundles.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 3dca510b0b8..bac42175de7 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -11,6 +11,30 @@ import ( // ListBundles returns all bundles in the dataPath folder that match the given type. func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { + // TODO: this is needed for initialization - we need to find a better way to fix this + if s.mdc == nil && len(bundleIDs) == 1 && bundleIDs[0] == "71881883-1768-46bd-a24d-a356a2afdf7f" { + return []*settingsmsg.Bundle{{ + Id: "71881883-1768-46bd-a24d-a356a2afdf7f", + Settings: []*settingsmsg.Setting{ + { + Id: "8e587774-d929-4215-910b-a317b1e80f73", + Name: "account-management", + DisplayName: "Account Management", + Description: "This permission gives full access to everything that is related to account management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + Id: "all", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + }, + }}, nil + } s.Init() var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { From 4c22c07711b295fa2b41d34abdb795bb3fcced2a Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 28 Feb 2022 16:39:07 +0100 Subject: [PATCH 11/42] add test for appendSetting Signed-off-by: jkoberg --- .../pkg/store/metadata/assignments_test.go | 4 +- settings/pkg/store/metadata/bundles.go | 18 ++++- settings/pkg/store/metadata/bundles_test.go | 68 +++++++++++++++++++ settings/pkg/store/metadata/store.go | 4 +- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index a0353b8d6d2..ec78aed68b4 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -2,6 +2,7 @@ package store import ( "log" + "sync" "testing" olog "github.com/owncloud/ocis/ocis-pkg/log" @@ -16,6 +17,7 @@ var ( s = Store{ Logger: logger, mdc: mdc, + l: &sync.Mutex{}, } logger = olog.NewLogger( @@ -85,7 +87,7 @@ func init() { func setupRoles() { for i := range bundles { if _, err := s.WriteBundle(bundles[i]); err != nil { - log.Fatal(err) + log.Fatal("error initializing ", err) } } } diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index bac42175de7..309685afda9 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) @@ -86,7 +87,22 @@ func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, err // AddSettingToBundle adds the given setting to the bundle with the given bundleID. func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) { - return nil, errors.New("not implemented") + s.Init() + b, err := s.ReadBundle(bundleID) + if err != nil { + // TODO: How to differentiate 'not found'? + b = new(settingsmsg.Bundle) + b.Id = bundleID + b.Type = settingsmsg.Bundle_TYPE_DEFAULT + } + + if setting.Id == "" { + setting.Id = uuid.Must(uuid.NewV4()).String() + } + + b.Settings = append(b.Settings, setting) + _, err = s.WriteBundle(b) + return setting, err } // RemoveSettingFromBundle removes the setting from the bundle with the given ids. diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go index 8a690a7deb2..7e8e47817a5 100644 --- a/settings/pkg/store/metadata/bundles_test.go +++ b/settings/pkg/store/metadata/bundles_test.go @@ -1,6 +1,7 @@ package store import ( + "sync" "testing" olog "github.com/owncloud/ocis/ocis-pkg/log" @@ -101,6 +102,42 @@ var bundleScenarios = []struct { }, } +var ( + appendTestBundleID = "append-test-bundle" + + appendTestSetting1 = &settingsmsg.Setting{ + Id: "append-test-setting-1", + Description: "test-desc-3", + DisplayName: "test-displayname-3", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: setting1, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + } + + appendTestSetting2 = &settingsmsg.Setting{ + Id: "append-test-setting-2", + Description: "test-desc-3", + DisplayName: "test-displayname-3", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: setting1, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + } +) + func TestBundles(t *testing.T) { mdc := NewMDC() s := Store{ @@ -110,6 +147,7 @@ func TestBundles(t *testing.T) { olog.Level("info"), ), + l: &sync.Mutex{}, mdc: mdc, } @@ -147,3 +185,33 @@ func TestBundles(t *testing.T) { require.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type) } } + +func TestAppendSetting(t *testing.T) { + mdc := NewMDC() + s := Store{ + Logger: olog.NewLogger( + olog.Color(true), + olog.Pretty(true), + olog.Level("info"), + ), + + l: &sync.Mutex{}, + mdc: mdc, + } + + // appending to non existing bundle creates new + _, err := s.AddSettingToBundle(appendTestBundleID, appendTestSetting1) + require.NoError(t, err) + + b, err := s.ReadBundle(appendTestBundleID) + require.NoError(t, err) + require.Len(t, b.Settings, 1) + + _, err = s.AddSettingToBundle(appendTestBundleID, appendTestSetting2) + require.NoError(t, err) + + b, err = s.ReadBundle(appendTestBundleID) + require.NoError(t, err) + require.Len(t, b.Settings, 2) + +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index aac096ec4df..28d3d66110d 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -118,7 +118,9 @@ func (s Store) initMetadataClient() error { } } - s.initStore(s) + if s.initStore != nil { + s.initStore(s) + } return nil } From 492419ec7b8047991cbc5b4fb520b2917c651d44 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 28 Feb 2022 17:15:24 +0100 Subject: [PATCH 12/42] rework initialization logic Signed-off-by: jkoberg --- settings/pkg/store/metadata/assignments.go | 6 +-- .../pkg/store/metadata/assignments_test.go | 9 ++-- settings/pkg/store/metadata/bundles.go | 12 ++--- settings/pkg/store/metadata/bundles_test.go | 48 +++++++++---------- settings/pkg/store/metadata/permissions.go | 6 +-- settings/pkg/store/metadata/store.go | 20 ++++---- settings/pkg/store/metadata/store_test.go | 8 ++-- settings/pkg/store/metadata/values.go | 8 ++-- settings/pkg/store/metadata/values_test.go | 19 ++++---- 9 files changed, 66 insertions(+), 70 deletions(-) diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 6c311b8b213..07862ca0d4d 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -10,7 +10,7 @@ import ( ) // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. -func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { +func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { s.Init() assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) if err != nil { @@ -36,7 +36,7 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleA } // WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account. -func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) { +func (s *Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) { s.Init() // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" err := s.mdc.Delete(nil, accountPath(accountUUID)) @@ -62,7 +62,7 @@ func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.Use } // RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account. -func (s Store) RemoveRoleAssignment(assignmentID string) error { +func (s *Store) RemoveRoleAssignment(assignmentID string) error { s.Init() accounts, err := s.mdc.ReadDir(nil, accountsFolderLocation) if err != nil { diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index ec78aed68b4..a2b56e600a0 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -14,19 +14,16 @@ var ( einstein = "a4d07560-a670-4be9-8d60-9b547751a208" //marie = "3c054db3-eec1-4ca4-b985-bc56dcf560cb" - s = Store{ - Logger: logger, - mdc: mdc, - l: &sync.Mutex{}, + s = &Store{ + l: &sync.Mutex{}, } - logger = olog.NewLogger( olog.Color(true), olog.Pretty(true), olog.Level("info"), ) - mdc = NewMDC() + mdc = NewMDC(s) bundles = []*settingsmsg.Bundle{ { diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 309685afda9..a94b69ae18b 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -11,7 +11,7 @@ import ( ) // ListBundles returns all bundles in the dataPath folder that match the given type. -func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { +func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { // TODO: this is needed for initialization - we need to find a better way to fix this if s.mdc == nil && len(bundleIDs) == 1 && bundleIDs[0] == "71881883-1768-46bd-a24d-a356a2afdf7f" { return []*settingsmsg.Bundle{{ @@ -59,7 +59,7 @@ func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []strin } // ReadBundle tries to find a bundle by the given id within the dataPath. -func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { +func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { s.Init() b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) if err != nil { @@ -71,12 +71,12 @@ func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { } // ReadSetting tries to find a setting by the given id within the dataPath. -func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { +func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { return nil, errors.New("not implemented") } // WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons -func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { +func (s *Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { s.Init() b, err := json.Marshal(record) if err != nil { @@ -86,7 +86,7 @@ func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, err } // AddSettingToBundle adds the given setting to the bundle with the given bundleID. -func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) { +func (s *Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) { s.Init() b, err := s.ReadBundle(bundleID) if err != nil { @@ -106,7 +106,7 @@ func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) } // RemoveSettingFromBundle removes the setting from the bundle with the given ids. -func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error { +func (s *Store) RemoveSettingFromBundle(bundleID string, settingID string) error { return errors.New("not implemented") } diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go index 7e8e47817a5..c557dfcc6a1 100644 --- a/settings/pkg/store/metadata/bundles_test.go +++ b/settings/pkg/store/metadata/bundles_test.go @@ -1,10 +1,9 @@ package store import ( - "sync" "testing" - olog "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" "github.com/stretchr/testify/require" ) @@ -103,7 +102,7 @@ var bundleScenarios = []struct { } var ( - appendTestBundleID = "append-test-bundle" + appendTestBundleID = uuid.Must(uuid.NewV4()).String() appendTestSetting1 = &settingsmsg.Setting{ Id: "append-test-setting-1", @@ -139,17 +138,16 @@ var ( ) func TestBundles(t *testing.T) { - mdc := NewMDC() - s := Store{ - Logger: olog.NewLogger( - olog.Color(true), - olog.Pretty(true), - olog.Level("info"), - ), - - l: &sync.Mutex{}, - mdc: mdc, - } + //s := &Store{ + //Logger: olog.NewLogger( + //olog.Color(true), + //olog.Pretty(true), + //olog.Level("info"), + //), + + //l: &sync.Mutex{}, + //} + //NewMDC(s) // write bundles for i := range bundleScenarios { @@ -187,17 +185,17 @@ func TestBundles(t *testing.T) { } func TestAppendSetting(t *testing.T) { - mdc := NewMDC() - s := Store{ - Logger: olog.NewLogger( - olog.Color(true), - olog.Pretty(true), - olog.Level("info"), - ), - - l: &sync.Mutex{}, - mdc: mdc, - } + //mdc := NewMDC() + //s := Store{ + //Logger: olog.NewLogger( + //olog.Color(true), + //olog.Pretty(true), + //olog.Level("info"), + //), + + //l: &sync.Mutex{}, + //mdc: mdc, + //} // appending to non existing bundle creates new _, err := s.AddSettingToBundle(appendTestBundleID, appendTestSetting1) diff --git a/settings/pkg/store/metadata/permissions.go b/settings/pkg/store/metadata/permissions.go index 7819aea38b2..0a6133deb69 100644 --- a/settings/pkg/store/metadata/permissions.go +++ b/settings/pkg/store/metadata/permissions.go @@ -7,16 +7,16 @@ import ( ) // ListPermissionsByResource collects all permissions from the provided roleIDs that match the requested resource -func (s Store) ListPermissionsByResource(resource *settingsmsg.Resource, roleIDs []string) ([]*settingsmsg.Permission, error) { +func (s *Store) ListPermissionsByResource(resource *settingsmsg.Resource, roleIDs []string) ([]*settingsmsg.Permission, error) { return nil, errors.New("not implemented") } // ReadPermissionByID finds the permission in the roles, specified by the provided roleIDs -func (s Store) ReadPermissionByID(permissionID string, roleIDs []string) (*settingsmsg.Permission, error) { +func (s *Store) ReadPermissionByID(permissionID string, roleIDs []string) (*settingsmsg.Permission, error) { return nil, errors.New("not implemented") } // ReadPermissionByName finds the permission in the roles, specified by the provided roleIDs -func (s Store) ReadPermissionByName(name string, roleIDs []string) (*settingsmsg.Permission, error) { +func (s *Store) ReadPermissionByName(name string, roleIDs []string) (*settingsmsg.Permission, error) { return nil, errors.New("not implemented") } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 28d3d66110d..84e09b74ef5 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -46,7 +46,7 @@ type Store struct { } // Init initialize the store once, later calls are noops -func (s Store) Init() { +func (s *Store) Init() { if s.mdc != nil { return } @@ -58,7 +58,7 @@ func (s Store) Init() { //b := backoff.NewExponentialBackOff() //b.MaxElapsedTime = 4 * time.Second //backoff.Retry(func() error { - err = s.initMetadataClient() + err = s.initMetadataClient(NewMetadataClient(s.cfg)) //return err //}, b) @@ -72,12 +72,12 @@ func (s Store) Init() { // New creates a new store func New(cfg *config.Config, initstore func(settings.Manager)) settings.Manager { s := Store{ - Logger: olog.NewLogger( - olog.Color(cfg.Log.Color), - olog.Pretty(cfg.Log.Pretty), - olog.Level(cfg.Log.Level), - olog.File(cfg.Log.File), - ), + //Logger: olog.NewLogger( + //olog.Color(cfg.Log.Color), + //olog.Pretty(cfg.Log.Pretty), + //olog.Level(cfg.Log.Level), + //olog.File(cfg.Log.File), + //), initStore: initstore, l: &sync.Mutex{}, init: &sync.Once{}, @@ -97,8 +97,8 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { } // we need to lazy initialize the MetadataClient because metadata service might not be ready -func (s Store) initMetadataClient() error { - s.mdc = NewMetadataClient(s.cfg) +func (s *Store) initMetadataClient(mdc MetadataClient) error { + s.mdc = mdc // TODO: this fails because of authentication issues err := s.mdc.Init(nil, settingsSpaceID) diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index c42f3d02772..c963901688e 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -42,13 +42,15 @@ type MockedMetadataClient struct { } // NewMDC instantiates a mocked MetadataClient -func NewMDC() MetadataClient { +func NewMDC(s *Store) MetadataClient { + var mdc MetadataClient switch testtype { case "unit": - return &MockedMetadataClient{data: make(map[string][]byte)} + mdc = &MockedMetadataClient{data: make(map[string][]byte)} case "integration": - return NewMetadataClient(&config.Config{}) + mdc = NewMetadataClient(&config.Config{}) } + s.initMetadataClient(mdc) return nil } diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index 4f7c23c5393..df238836897 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -13,12 +13,12 @@ import ( // If the bundleId is empty, it's ignored for filtering. // If the accountUUID is empty, only values with empty accountUUID are returned. // If the accountUUID is not empty, values with an empty or with a matching accountUUID are returned. -func (s Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, error) { +func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, error) { return nil, errors.New("not implemented") } // ReadValue tries to find a value by the given valueId within the dataPath -func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { +func (s *Store) ReadValue(valueID string) (*settingsmsg.Value, error) { s.Init() b, err := s.mdc.SimpleDownload(nil, valuePath(valueID)) if err != nil { @@ -29,12 +29,12 @@ func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { } // ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers -func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) { +func (s *Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) { return nil, errors.New("not implemented") } // WriteValue writes the given value into a file within the dataPath -func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { +func (s *Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { s.Init() b, err := json.Marshal(value) if err != nil { diff --git a/settings/pkg/store/metadata/values_test.go b/settings/pkg/store/metadata/values_test.go index 2921e3d0e56..462460fbcdf 100644 --- a/settings/pkg/store/metadata/values_test.go +++ b/settings/pkg/store/metadata/values_test.go @@ -3,7 +3,6 @@ package store import ( "testing" - olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" "github.com/stretchr/testify/require" ) @@ -46,15 +45,15 @@ var valueScenarios = []struct { } func TestValues(t *testing.T) { - mdc := NewMDC() - s := Store{ - Logger: olog.NewLogger( - olog.Color(true), - olog.Pretty(true), - olog.Level("info"), - ), - mdc: mdc, - } + //mdc := NewMDC() + //s := Store{ + //Logger: olog.NewLogger( + //olog.Color(true), + //olog.Pretty(true), + //olog.Level("info"), + //), + //mdc: mdc, + //} for i := range valueScenarios { index := i t.Run(valueScenarios[index].name, func(t *testing.T) { From a873fdc94261293c62c2adf3183507e492c219e2 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 1 Mar 2022 10:51:07 +0100 Subject: [PATCH 13/42] return default values when mdc is not initialized Signed-off-by: jkoberg --- settings/pkg/store/defaults/defaults.go | 402 +++++++++++++++++++++ settings/pkg/store/metadata/assignments.go | 14 + settings/pkg/store/metadata/bundles.go | 37 +- settings/pkg/store/metadata/store.go | 31 +- 4 files changed, 443 insertions(+), 41 deletions(-) create mode 100644 settings/pkg/store/defaults/defaults.go diff --git a/settings/pkg/store/defaults/defaults.go b/settings/pkg/store/defaults/defaults.go new file mode 100644 index 00000000000..d183714fa71 --- /dev/null +++ b/settings/pkg/store/defaults/defaults.go @@ -0,0 +1,402 @@ +package defaults + +import ( + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" +) + +const ( + // BundleUUIDRoleAdmin represents the admin role + BundleUUIDRoleAdmin = "71881883-1768-46bd-a24d-a356a2afdf7f" + + // BundleUUIDRoleUser represents the user role. + BundleUUIDRoleUser = "d7beeea8-8ff4-406b-8fb6-ab2dd81e6b11" + + // BundleUUIDRoleGuest represents the guest role. + BundleUUIDRoleGuest = "38071a68-456a-4553-846a-fa67bf5596cc" + + // RoleManagementPermissionID is the hardcoded setting UUID for the role management permission + RoleManagementPermissionID string = "a53e601e-571f-4f86-8fec-d4576ef49c62" + // RoleManagementPermissionName is the hardcoded setting name for the role management permission + RoleManagementPermissionName string = "role-management" + + // SettingsManagementPermissionID is the hardcoded setting UUID for the settings management permission + SettingsManagementPermissionID string = "79e13b30-3e22-11eb-bc51-0b9f0bad9a58" + // SettingsManagementPermissionName is the hardcoded setting name for the settings management permission + SettingsManagementPermissionName string = "settings-management" + + // SetSpaceQuotaPermissionID is the hardcoded setting UUID for the set space quota permission + SetSpaceQuotaPermissionID string = "4e6f9709-f9e7-44f1-95d4-b762d27b7896" + // SetSpaceQuotaPermissionName is the hardcoded setting name for the set space quota permission + SetSpaceQuotaPermissionName string = "set-space-quota" + + // ListAllSpacesPermissionID is the hardcoded setting UUID for the list all spaces permission + ListAllSpacesPermissionID string = "016f6ddd-9501-4a0a-8ebe-64a20ee8ec82" + // ListAllSpacesPermissionName is the hardcoded setting name for the list all spaces permission + ListAllSpacesPermissionName string = "list-all-spaces" + + // CreateSpacePermissionID is the hardcoded setting UUID for the create space permission + CreateSpacePermissionID string = "79e13b30-3e22-11eb-bc51-0b9f0bad9a58" + // CreateSpacePermissionName is the hardcoded setting name for the create space permission + CreateSpacePermissionName string = "create-space" + + settingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f" + + // AccountManagementPermissionID is the hardcoded setting UUID for the account management permission + AccountManagementPermissionID string = "8e587774-d929-4215-910b-a317b1e80f73" + // AccountManagementPermissionName is the hardcoded setting name for the account management permission + AccountManagementPermissionName string = "account-management" + // GroupManagementPermissionID is the hardcoded setting UUID for the group management permission + GroupManagementPermissionID string = "522adfbe-5908-45b4-b135-41979de73245" + // GroupManagementPermissionName is the hardcoded setting name for the group management permission + GroupManagementPermissionName string = "group-management" + // SelfManagementPermissionID is the hardcoded setting UUID for the self management permission + SelfManagementPermissionID string = "e03070e9-4362-4cc6-a872-1c7cb2eb2b8e" + // SelfManagementPermissionName is the hardcoded setting name for the self management permission + SelfManagementPermissionName string = "self-management" +) + +// GenerateBundlesDefaultRoles bootstraps the default roles. +func GenerateBundlesDefaultRoles() []*settingsmsg.Bundle { + return []*settingsmsg.Bundle{ + generateBundleAdminRole(), + generateBundleUserRole(), + generateBundleGuestRole(), + generateBundleProfileRequest(), + } +} + +func generateBundleAdminRole() *settingsmsg.Bundle { + return &settingsmsg.Bundle{ + Id: BundleUUIDRoleAdmin, + Name: "admin", + Type: settingsmsg.Bundle_TYPE_ROLE, + Extension: "ocis-roles", + DisplayName: "Admin", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: RoleManagementPermissionID, + Name: RoleManagementPermissionName, + DisplayName: "Role Management", + Description: "This permission gives full access to everything that is related to role management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + Id: "all", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: SettingsManagementPermissionID, + Name: SettingsManagementPermissionName, + DisplayName: "Settings Management", + Description: "This permission gives full access to everything that is related to settings management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + Id: "all", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: "7d81f103-0488-4853-bce5-98dcce36d649", + Name: "language-readwrite", + DisplayName: "Permission to read and set the language (anyone)", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: settingUUIDProfileLanguage, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: AccountManagementPermissionID, + Name: AccountManagementPermissionName, + DisplayName: "Account Management", + Description: "This permission gives full access to everything that is related to account management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + Id: "all", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: GroupManagementPermissionID, + Name: GroupManagementPermissionName, + DisplayName: "Group Management", + Description: "This permission gives full access to everything that is related to group management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_GROUP, + Id: "all", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: SetSpaceQuotaPermissionID, + Name: SetSpaceQuotaPermissionName, + DisplayName: "Set Space Quota", + Description: "This permission allows to manage space quotas.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: CreateSpacePermissionID, + Name: CreateSpacePermissionName, + DisplayName: "Create Space", + Description: "This permission allows to create new spaces.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + { + Id: ListAllSpacesPermissionID, + Name: ListAllSpacesPermissionName, + DisplayName: "List All Spaces", + Description: "This permission allows list all spaces.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READ, + Constraint: settingsmsg.Permission_CONSTRAINT_ALL, + }, + }, + }, + }, + } +} + +func generateBundleUserRole() *settingsmsg.Bundle { + return &settingsmsg.Bundle{ + Id: BundleUUIDRoleUser, + Name: "user", + Type: settingsmsg.Bundle_TYPE_ROLE, + Extension: "ocis-roles", + DisplayName: "User", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: "640e00d2-4df8-41bd-b1c2-9f30a01e0e99", + Name: "language-readwrite", + DisplayName: "Permission to read and set the language (self)", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: settingUUIDProfileLanguage, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, + { + Id: SelfManagementPermissionID, + Name: SelfManagementPermissionName, + DisplayName: "Self Management", + Description: "This permission gives access to self management.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + Id: "me", + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + } +} + +func generateBundleGuestRole() *settingsmsg.Bundle { + return &settingsmsg.Bundle{ + Id: BundleUUIDRoleGuest, + Name: "guest", + Type: settingsmsg.Bundle_TYPE_ROLE, + Extension: "ocis-roles", + DisplayName: "Guest", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: "ca878636-8b1a-4fae-8282-8617a4c13597", + Name: "language-readwrite", + DisplayName: "Permission to read and set the language (self)", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + Id: settingUUIDProfileLanguage, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + } +} + +func generateBundleProfileRequest() *settingsmsg.Bundle { + return &settingsmsg.Bundle{ + Id: "2a506de7-99bd-4f0d-994e-c38e72c28fd9", + Name: "profile", + Extension: "ocis-accounts", + Type: settingsmsg.Bundle_TYPE_DEFAULT, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + DisplayName: "Profile", + Settings: []*settingsmsg.Setting{ + { + Id: settingUUIDProfileLanguage, + Name: "language", + DisplayName: "Language", + Description: "User language", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + }, + Value: &languageSetting, + }, + }, + } +} + +// TODO: languageSetting needed? +var languageSetting = settingsmsg.Setting_SingleChoiceValue{ + SingleChoiceValue: &settingsmsg.SingleChoiceList{ + Options: []*settingsmsg.ListOption{ + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "cs", + }, + }, + DisplayValue: "Czech", + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "de", + }, + }, + DisplayValue: "Deutsch", + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "en", + }, + }, + DisplayValue: "English", + Default: true, + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "es", + }, + }, + DisplayValue: "Español", + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "fr", + }, + }, + DisplayValue: "Français", + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "gl", + }, + }, + DisplayValue: "Galego", + }, + { + Value: &settingsmsg.ListOptionValue{ + Option: &settingsmsg.ListOptionValue_StringValue{ + StringValue: "it", + }, + }, + DisplayValue: "Italiano", + }, + }, + }, +} + +// DefaultRoleAssignments returns (as one might guess) the default role assignments +func DefaultRoleAssignments() []*settingsmsg.UserRoleAssignment { + return []*settingsmsg.UserRoleAssignment{ + // default admin users + { + AccountUuid: "058bff95-6708-4fe5-91e4-9ea3d377588b", + RoleId: BundleUUIDRoleAdmin, + }, { + AccountUuid: "ddc2004c-0977-11eb-9d3f-a793888cd0f8", + RoleId: BundleUUIDRoleAdmin, + }, { + AccountUuid: "820ba2a1-3f54-4538-80a4-2d73007e30bf", + RoleId: BundleUUIDRoleAdmin, + }, { + AccountUuid: "bc596f3c-c955-4328-80a0-60d018b4ad57", + RoleId: BundleUUIDRoleAdmin, + }, + // default users with role "user" + { + AccountUuid: "4c510ada-c86b-4815-8820-42cdf82c3d51", + RoleId: BundleUUIDRoleUser, + }, { + AccountUuid: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + RoleId: BundleUUIDRoleUser, + }, { + AccountUuid: "932b4540-8d16-481e-8ef4-588e4b6b151c", + RoleId: BundleUUIDRoleUser, + }, + } +} diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 07862ca0d4d..4fe6c9173ed 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -7,10 +7,14 @@ import ( "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/owncloud/ocis/settings/pkg/store/defaults" ) // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { + if s.mdc == nil { + return defaultRoleAssignments(accountUUID), nil + } s.Init() assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) if err != nil { @@ -86,6 +90,16 @@ func (s *Store) RemoveRoleAssignment(assignmentID string) error { return fmt.Errorf("assignmentID '%s' not found", assignmentID) } +func defaultRoleAssignments(accID string) []*settingsmsg.UserRoleAssignment { + var assmnts []*settingsmsg.UserRoleAssignment + for _, r := range defaults.DefaultRoleAssignments() { + if r.AccountUuid == accID { + assmnts = append(assmnts, r) + } + } + return assmnts +} + func accountPath(accountUUID string) string { return fmt.Sprintf("%s/%s", accountsFolderLocation, accountUUID) } diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index a94b69ae18b..00f5773e39f 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -8,35 +8,16 @@ import ( "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/owncloud/ocis/settings/pkg/store/defaults" ) // ListBundles returns all bundles in the dataPath folder that match the given type. func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { // TODO: this is needed for initialization - we need to find a better way to fix this - if s.mdc == nil && len(bundleIDs) == 1 && bundleIDs[0] == "71881883-1768-46bd-a24d-a356a2afdf7f" { - return []*settingsmsg.Bundle{{ - Id: "71881883-1768-46bd-a24d-a356a2afdf7f", - Settings: []*settingsmsg.Setting{ - { - Id: "8e587774-d929-4215-910b-a317b1e80f73", - Name: "account-management", - DisplayName: "Account Management", - Description: "This permission gives full access to everything that is related to account management.", - Resource: &settingsmsg.Resource{ - Type: settingsmsg.Resource_TYPE_USER, - Id: "all", - }, - Value: &settingsmsg.Setting_PermissionValue{ - PermissionValue: &settingsmsg.Permission{ - Operation: settingsmsg.Permission_OPERATION_READWRITE, - Constraint: settingsmsg.Permission_CONSTRAINT_ALL, - }, - }, - }, - }, - }}, nil + if s.mdc == nil { + return defaultBundle(bundleType, bundleIDs[0]), nil } - s.Init() + //s.Init() var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) @@ -113,3 +94,13 @@ func (s *Store) RemoveSettingFromBundle(bundleID string, settingID string) error func bundlePath(id string) string { return fmt.Sprintf("%s/%s", bundleFolderLocation, id) } + +func defaultBundle(bundleType settingsmsg.Bundle_Type, bundleID string) []*settingsmsg.Bundle { + var bundles []*settingsmsg.Bundle + for _, b := range defaults.GenerateBundlesDefaultRoles() { + if b.Type == bundleType && b.Id == bundleID { + bundles = append(bundles, b) + } + } + return bundles +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 84e09b74ef5..b77a6770fec 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -47,25 +47,22 @@ type Store struct { // Init initialize the store once, later calls are noops func (s *Store) Init() { - if s.mdc != nil { - return - } - s.l.Lock() defer s.l.Unlock() + var err error - s.init.Do(func() { - //b := backoff.NewExponentialBackOff() - //b.MaxElapsedTime = 4 * time.Second - //backoff.Retry(func() error { - err = s.initMetadataClient(NewMetadataClient(s.cfg)) - //return err + //s.init.Do(func() { + //b := backoff.NewExponentialBackOff() + //b.MaxElapsedTime = 4 * time.Second + //backoff.Retry(func() error { + err = s.initMetadataClient(NewMetadataClient(s.cfg)) + //return err - //}, b) + //}, b) - }) + //}) if err != nil { - log.Fatal(err) + log.Fatal("error initializing metadata client: ", err) } } @@ -98,10 +95,7 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { // we need to lazy initialize the MetadataClient because metadata service might not be ready func (s *Store) initMetadataClient(mdc MetadataClient) error { - s.mdc = mdc - - // TODO: this fails because of authentication issues - err := s.mdc.Init(nil, settingsSpaceID) + err := mdc.Init(nil, settingsSpaceID) if err != nil { return err } @@ -112,12 +106,13 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { bundleFolderLocation, valuesFolderLocation, } { - err = s.mdc.MakeDirIfNotExist(nil, p) + err = mdc.MakeDirIfNotExist(nil, p) if err != nil { return err } } + s.mdc = mdc if s.initStore != nil { s.initStore(s) } From 7fcf6f5aa01d5d60b1f6ef6ce7677cb2a10bf79a Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 1 Mar 2022 11:37:26 +0100 Subject: [PATCH 14/42] implement permission unit tests Signed-off-by: jkoberg --- .../pkg/store/metadata/assignments_test.go | 9 +++ settings/pkg/store/metadata/permissions.go | 60 +++++++++++++++++-- .../pkg/store/metadata/permissions_test.go | 27 +++++++++ settings/pkg/store/metadata/store.go | 4 ++ 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 settings/pkg/store/metadata/permissions_test.go diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index a2b56e600a0..5dae88ae945 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -37,20 +37,28 @@ var ( }, Settings: []*settingsmsg.Setting{ { + Id: "updateID", Name: "update", Value: &settingsmsg.Setting_PermissionValue{ PermissionValue: &settingsmsg.Permission{ Operation: settingsmsg.Permission_OPERATION_UPDATE, }, }, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SETTING, + }, }, { + Id: "readID", Name: "read", Value: &settingsmsg.Setting_PermissionValue{ PermissionValue: &settingsmsg.Permission{ Operation: settingsmsg.Permission_OPERATION_READ, }, }, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_BUNDLE, + }, }, }, }, @@ -65,6 +73,7 @@ var ( }, Settings: []*settingsmsg.Setting{ { + Id: "readID", Name: "read", Value: &settingsmsg.Setting_PermissionValue{ PermissionValue: &settingsmsg.Permission{ diff --git a/settings/pkg/store/metadata/permissions.go b/settings/pkg/store/metadata/permissions.go index 0a6133deb69..50ebe12a532 100644 --- a/settings/pkg/store/metadata/permissions.go +++ b/settings/pkg/store/metadata/permissions.go @@ -1,22 +1,72 @@ package store import ( - "errors" - settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/owncloud/ocis/settings/pkg/settings" + "github.com/owncloud/ocis/settings/pkg/util" ) // ListPermissionsByResource collects all permissions from the provided roleIDs that match the requested resource func (s *Store) ListPermissionsByResource(resource *settingsmsg.Resource, roleIDs []string) ([]*settingsmsg.Permission, error) { - return nil, errors.New("not implemented") + records := make([]*settingsmsg.Permission, 0) + for _, roleID := range roleIDs { + role, err := s.ReadBundle(roleID) + if err != nil { + s.Logger.Debug().Str("roleID", roleID).Msg("role not found, skipping") + continue + } + records = append(records, extractPermissionsByResource(resource, role)...) + } + return records, nil } // ReadPermissionByID finds the permission in the roles, specified by the provided roleIDs func (s *Store) ReadPermissionByID(permissionID string, roleIDs []string) (*settingsmsg.Permission, error) { - return nil, errors.New("not implemented") + for _, roleID := range roleIDs { + role, err := s.ReadBundle(roleID) + if err != nil { + s.Logger.Debug().Str("roleID", roleID).Msg("role not found, skipping") + continue + } + for _, permission := range role.Settings { + if permission.Id == permissionID { + if value, ok := permission.Value.(*settingsmsg.Setting_PermissionValue); ok { + return value.PermissionValue, nil + } + } + } + } + return nil, nil } // ReadPermissionByName finds the permission in the roles, specified by the provided roleIDs func (s *Store) ReadPermissionByName(name string, roleIDs []string) (*settingsmsg.Permission, error) { - return nil, errors.New("not implemented") + for _, roleID := range roleIDs { + role, err := s.ReadBundle(roleID) + if err != nil { + s.Logger.Debug().Str("roleID", roleID).Msg("role not found, skipping") + continue + } + for _, permission := range role.Settings { + if permission.Name == name { + if value, ok := permission.Value.(*settingsmsg.Setting_PermissionValue); ok { + return value.PermissionValue, nil + } + } + } + } + return nil, settings.ErrPermissionNotFound +} + +// extractPermissionsByResource collects all permissions from the provided role that match the requested resource +func extractPermissionsByResource(resource *settingsmsg.Resource, role *settingsmsg.Bundle) []*settingsmsg.Permission { + permissions := make([]*settingsmsg.Permission, 0) + for _, setting := range role.Settings { + if value, ok := setting.Value.(*settingsmsg.Setting_PermissionValue); ok { + if util.IsResourceMatched(setting.Resource, resource) { + permissions = append(permissions, value.PermissionValue) + } + } + } + return permissions } diff --git a/settings/pkg/store/metadata/permissions_test.go b/settings/pkg/store/metadata/permissions_test.go new file mode 100644 index 00000000000..db3283cb461 --- /dev/null +++ b/settings/pkg/store/metadata/permissions_test.go @@ -0,0 +1,27 @@ +package store + +import ( + "testing" + + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/stretchr/testify/require" +) + +func TestPermission(t *testing.T) { + // bunldes are initialized within init func + p, err := s.ReadPermissionByID("readID", []string{"f36db5e6-a03c-40df-8413-711c67e40b47"}) + require.NoError(t, err) + require.Equal(t, settingsmsg.Permission_OPERATION_READ, p.Operation) + + p, err = s.ReadPermissionByName("read", []string{"f36db5e6-a03c-40df-8413-711c67e40b47"}) + require.NoError(t, err) + require.Equal(t, settingsmsg.Permission_OPERATION_READ, p.Operation) + + pms, err := s.ListPermissionsByResource(&settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_BUNDLE, + }, []string{"f36db5e6-a03c-40df-8413-711c67e40b47"}) + require.NoError(t, err) + require.Len(t, pms, 1) + require.Equal(t, settingsmsg.Permission_OPERATION_READ, pms[0].Operation) + +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index b77a6770fec..f7d987eecd2 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -50,6 +50,10 @@ func (s *Store) Init() { s.l.Lock() defer s.l.Unlock() + if s.mdc != nil { + return + } + var err error //s.init.Do(func() { //b := backoff.NewExponentialBackOff() From f64280188ac4206ebb28178592f5fb6034cecd70 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 1 Mar 2022 14:53:03 +0100 Subject: [PATCH 15/42] refine initialization logic again Signed-off-by: jkoberg --- settings/pkg/store/metadata/bundles.go | 15 ++++++++-- settings/pkg/store/metadata/store.go | 41 ++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 00f5773e39f..c9099c843af 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -14,10 +14,19 @@ import ( // ListBundles returns all bundles in the dataPath folder that match the given type. func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { // TODO: this is needed for initialization - we need to find a better way to fix this - if s.mdc == nil { + if s.mdc == nil && len(bundleIDs) == 1 { return defaultBundle(bundleType, bundleIDs[0]), nil } - //s.Init() + s.Init() + + if len(bundleIDs) == 0 { + bIDs, err := s.mdc.ReadDir(nil, bundleFolderLocation) + if err != nil { + return nil, err + } + + bundleIDs = bIDs + } var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) @@ -53,6 +62,7 @@ func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { // ReadSetting tries to find a setting by the given id within the dataPath. func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { + fmt.Println("ReadSetting not implemented") return nil, errors.New("not implemented") } @@ -88,6 +98,7 @@ func (s *Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting // RemoveSettingFromBundle removes the setting from the bundle with the given ids. func (s *Store) RemoveSettingFromBundle(bundleID string, settingID string) error { + fmt.Println("RemoveSettingFromBundle not implemented") return errors.New("not implemented") } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index f7d987eecd2..ad415a3ea20 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -3,13 +3,17 @@ package store import ( "context" + "encoding/json" "log" "sync" "github.com/cs3org/reva/pkg/storage/utils/metadata" + "github.com/gofrs/uuid" olog "github.com/owncloud/ocis/ocis-pkg/log" + settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" "github.com/owncloud/ocis/settings/pkg/config" "github.com/owncloud/ocis/settings/pkg/settings" + "github.com/owncloud/ocis/settings/pkg/store/defaults" ) var ( @@ -116,10 +120,41 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { } } - s.mdc = mdc - if s.initStore != nil { - s.initStore(s) + for _, p := range defaults.GenerateBundlesDefaultRoles() { + b, err := json.Marshal(p) + if err != nil { + return err + } + err = mdc.SimpleUpload(nil, bundlePath(p.Id), b) + if err != nil { + return err + } + } + + for _, p := range defaults.DefaultRoleAssignments() { + accountUUID := p.AccountUuid + roleID := p.RoleId + err = mdc.MakeDirIfNotExist(nil, accountPath(accountUUID)) + if err != nil { + return err + } + + ass := &settingsmsg.UserRoleAssignment{ + Id: uuid.Must(uuid.NewV4()).String(), + AccountUuid: accountUUID, + RoleId: roleID, + } + b, err := json.Marshal(ass) + if err != nil { + return err + } + err = mdc.SimpleUpload(nil, assignmentPath(accountUUID, ass.Id), b) + if err != nil { + return err + } } + + s.mdc = mdc return nil } From a647f56bb0cc36c660e99442ca6a1da04472c4a7 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 1 Mar 2022 15:22:19 +0100 Subject: [PATCH 16/42] unitests for list values Signed-off-by: jkoberg --- settings/pkg/store/metadata/store_test.go | 2 +- settings/pkg/store/metadata/values.go | 38 +++++++++++++++- settings/pkg/store/metadata/values_test.go | 51 +++++++++++++++++----- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index c963901688e..6ce91a16d3d 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -30,7 +30,7 @@ const ( // value ids value1 = "fd3b6221-dc13-4a22-824d-2480495f1cdb" value2 = "2a0bd9b0-ca1d-491a-8c56-d2ddfd68ded8" - //value3 = "b42702d2-5e4d-4d73-b133-e1f9e285355e" + value3 = "b42702d2-5e4d-4d73-b133-e1f9e285355e" ) // use "unit" or "integration" do define test type. You need a running ocis instance for integration tests diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index df238836897..c79cc0361ef 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -14,7 +14,42 @@ import ( // If the accountUUID is empty, only values with empty accountUUID are returned. // If the accountUUID is not empty, values with an empty or with a matching accountUUID are returned. func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, error) { - return nil, errors.New("not implemented") + s.Init() + + vIDs, err := s.mdc.ReadDir(nil, valuesFolderLocation) + if err != nil { + return nil, err + } + + // TODO: refine logic not to spam metadata service + var values []*settingsmsg.Value + for _, vid := range vIDs { + b, err := s.mdc.SimpleDownload(nil, valuePath(vid)) + if err != nil { + return nil, err + } + + v := &settingsmsg.Value{} + err = json.Unmarshal(b, v) + if err != nil { + return nil, err + } + + if bundleID != "" && v.BundleId != bundleID { + continue + } + + if v.AccountUuid == "" { + values = append(values, v) + continue + } + + if v.AccountUuid == accountUUID { + values = append(values, v) + continue + } + } + return values, nil } // ReadValue tries to find a value by the given valueId within the dataPath @@ -30,6 +65,7 @@ func (s *Store) ReadValue(valueID string) (*settingsmsg.Value, error) { // ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers func (s *Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) { + fmt.Println("ReadValueByUniqueIdentifiers not implemented") return nil, errors.New("not implemented") } diff --git a/settings/pkg/store/metadata/values_test.go b/settings/pkg/store/metadata/values_test.go index 462460fbcdf..62c71867e0d 100644 --- a/settings/pkg/store/metadata/values_test.go +++ b/settings/pkg/store/metadata/values_test.go @@ -30,7 +30,7 @@ var valueScenarios = []struct { name: "generic-test-with-file-resource", value: &settingsmsg.Value{ Id: value2, - BundleId: bundle1, + BundleId: bundle2, SettingId: setting2, AccountUuid: accountUUID1, Resource: &settingsmsg.Resource{ @@ -42,18 +42,25 @@ var valueScenarios = []struct { }, }, }, + { + name: "value without accountUUID", + value: &settingsmsg.Value{ + Id: value3, + BundleId: bundle3, + SettingId: setting2, + AccountUuid: "", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_FILE, + Id: "adfba82d-919a-41c3-9cd1-5a3f83b2bf76", + }, + Value: &settingsmsg.Value_StringValue{ + StringValue: "tralala", + }, + }, + }, } func TestValues(t *testing.T) { - //mdc := NewMDC() - //s := Store{ - //Logger: olog.NewLogger( - //olog.Color(true), - //olog.Pretty(true), - //olog.Level("info"), - //), - //mdc: mdc, - //} for i := range valueScenarios { index := i t.Run(valueScenarios[index].name, func(t *testing.T) { @@ -65,7 +72,29 @@ func TestValues(t *testing.T) { v, err = s.ReadValue(value.Id) require.NoError(t, err) require.Equal(t, value, v) - }) } } + +func TestListValues(t *testing.T) { + for _, v := range valueScenarios { + _, err := s.WriteValue(v.value) + require.NoError(t, err) + } + + // empty accountid returns only values with empty accountud + vs, err := s.ListValues("", "") + require.NoError(t, err) + require.Len(t, vs, 1) + + // filled accountid returns matching and empty accountUUID values + vs, err = s.ListValues("", accountUUID1) + require.NoError(t, err) + require.Len(t, vs, 3) + + // filled bundleid only returns matching values + vs, err = s.ListValues(bundle3, accountUUID1) + require.NoError(t, err) + require.Len(t, vs, 1) + +} From c80022b0c6d8cc4cd478a71a9af8621218d8817e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 1 Mar 2022 15:52:57 +0100 Subject: [PATCH 17/42] ReadSetting unit test & implementation Signed-off-by: jkoberg --- settings/pkg/store/metadata/bundles.go | 26 ++++++++++++++++++--- settings/pkg/store/metadata/bundles_test.go | 17 ++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index c9099c843af..8a49bfae9a3 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -60,10 +60,30 @@ func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { return bundle, json.Unmarshal(b, bundle) } -// ReadSetting tries to find a setting by the given id within the dataPath. +// ReadSetting tries to find a setting by the given id from the metadata service func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { - fmt.Println("ReadSetting not implemented") - return nil, errors.New("not implemented") + s.Init() + + ids, err := s.mdc.ReadDir(nil, bundleFolderLocation) + if err != nil { + return nil, err + } + + // TODO: avoid spamming metadata service + for _, id := range ids { + b, err := s.ReadBundle(id) + if err != nil { + return nil, err + } + + for _, setting := range b.Settings { + if setting.Id == settingID { + return setting, nil + } + } + + } + return nil, fmt.Errorf("setting '%s' not found", settingID) } // WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons diff --git a/settings/pkg/store/metadata/bundles_test.go b/settings/pkg/store/metadata/bundles_test.go index c557dfcc6a1..0aadbd3b72e 100644 --- a/settings/pkg/store/metadata/bundles_test.go +++ b/settings/pkg/store/metadata/bundles_test.go @@ -138,18 +138,6 @@ var ( ) func TestBundles(t *testing.T) { - //s := &Store{ - //Logger: olog.NewLogger( - //olog.Color(true), - //olog.Pretty(true), - //olog.Level("info"), - //), - - //l: &sync.Mutex{}, - //} - //NewMDC(s) - - // write bundles for i := range bundleScenarios { b := bundleScenarios[i] t.Run(b.name, func(t *testing.T) { @@ -182,6 +170,11 @@ func TestBundles(t *testing.T) { for i := range roles { require.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type) } + + // check that ReadSetting works + setting, err := s.ReadSetting(setting1) + require.NoError(t, err) + require.Equal(t, "test-desc-1", setting.Description) // could be tested better ;) } func TestAppendSetting(t *testing.T) { From 7731de91f18c5fd31b0015737d9f307066a99f12 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 2 Mar 2022 10:14:27 +0100 Subject: [PATCH 18/42] create id for values if not given Signed-off-by: jkoberg --- settings/pkg/store/metadata/store.go | 6 +++--- settings/pkg/store/metadata/values.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index ad415a3ea20..ef7c2b2a6a1 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -51,13 +51,13 @@ type Store struct { // Init initialize the store once, later calls are noops func (s *Store) Init() { - s.l.Lock() - defer s.l.Unlock() - if s.mdc != nil { return } + s.l.Lock() + defer s.l.Unlock() + var err error //s.init.Do(func() { //b := backoff.NewExponentialBackOff() diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index c79cc0361ef..212527160a3 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "github.com/gofrs/uuid" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" ) @@ -72,6 +73,9 @@ func (s *Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*se // WriteValue writes the given value into a file within the dataPath func (s *Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { s.Init() + if value.Id == "" { + value.Id = uuid.Must(uuid.NewV4()).String() + } b, err := json.Marshal(value) if err != nil { return nil, err From 62ec3cf8018281abac21d3e3477964a5c03705ff Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 2 Mar 2022 12:41:57 +0100 Subject: [PATCH 19/42] add new defaults Signed-off-by: jkoberg --- settings/pkg/store/defaults/defaults.go | 54 +++++++++++++++++++++++++ settings/pkg/store/metadata/bundles.go | 3 ++ 2 files changed, 57 insertions(+) diff --git a/settings/pkg/store/defaults/defaults.go b/settings/pkg/store/defaults/defaults.go index d183714fa71..c4a209b7b18 100644 --- a/settings/pkg/store/defaults/defaults.go +++ b/settings/pkg/store/defaults/defaults.go @@ -14,6 +14,9 @@ const ( // BundleUUIDRoleGuest represents the guest role. BundleUUIDRoleGuest = "38071a68-456a-4553-846a-fa67bf5596cc" + // BundleUUIDRoleMetadata represents the metadata user role + BundleUUIDRoleMetadata = "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad" + // RoleManagementPermissionID is the hardcoded setting UUID for the role management permission RoleManagementPermissionID string = "a53e601e-571f-4f86-8fec-d4576ef49c62" // RoleManagementPermissionName is the hardcoded setting name for the role management permission @@ -62,6 +65,7 @@ func GenerateBundlesDefaultRoles() []*settingsmsg.Bundle { generateBundleUserRole(), generateBundleGuestRole(), generateBundleProfileRequest(), + generateBundleMetadataRole(), } } @@ -246,6 +250,21 @@ func generateBundleUserRole() *settingsmsg.Bundle { }, }, }, + { + Id: CreateSpacePermissionID, + Name: CreateSpacePermissionName, + DisplayName: "Create own Space", + Description: "This permission allows to create a space owned by the current user.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, // TODO resource type space? self? me? own? + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_CREATE, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, }, } } @@ -305,6 +324,36 @@ func generateBundleProfileRequest() *settingsmsg.Bundle { } } +func generateBundleMetadataRole() *settingsmsg.Bundle { + return &settingsmsg.Bundle{ + Id: BundleUUIDRoleMetadata, + Name: "metadata", + Type: settingsmsg.Bundle_TYPE_ROLE, + Extension: "ocis-roles", + DisplayName: "Metadata", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Settings: []*settingsmsg.Setting{ + { + Id: CreateSpacePermissionID, + Name: CreateSpacePermissionName, + DisplayName: "Create own Space", + Description: "This permission allows to create a space owned by the current user.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, // TODO resource type space? self? me? own? + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_CREATE, + Constraint: settingsmsg.Permission_CONSTRAINT_OWN, + }, + }, + }, + }, + } +} + // TODO: languageSetting needed? var languageSetting = settingsmsg.Setting_SingleChoiceValue{ SingleChoiceValue: &settingsmsg.SingleChoiceList{ @@ -373,6 +422,11 @@ var languageSetting = settingsmsg.Setting_SingleChoiceValue{ // DefaultRoleAssignments returns (as one might guess) the default role assignments func DefaultRoleAssignments() []*settingsmsg.UserRoleAssignment { return []*settingsmsg.UserRoleAssignment{ + // accounts service user for the metadata user is allowed to create spaces + { + AccountUuid: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + RoleId: BundleUUIDRoleAdmin, + }, // default admin users { AccountUuid: "058bff95-6708-4fe5-91e4-9ea3d377588b", diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 8a49bfae9a3..3c3d449dba7 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -50,6 +50,9 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri // ReadBundle tries to find a bundle by the given id within the dataPath. func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { + if s.mdc == nil { + return defaultBundle(settingsmsg.Bundle_TYPE_ROLE, bundleID)[0], nil + } s.Init() b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) if err != nil { From 0d49316495f0c1501bcdf56e5d26e080cb461dbe Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 2 Mar 2022 13:11:01 +0100 Subject: [PATCH 20/42] downgrade reva temporarilly Signed-off-by: jkoberg --- go.mod | 2 ++ go.sum | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 0723ab5a636..a23a98e0449 100644 --- a/go.mod +++ b/go.mod @@ -275,3 +275,5 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 + +replace github.com/cs3org/reva => github.com/cs3org/reva v1.16.1-0.20220228144359-3e80be7f6667 diff --git a/go.sum b/go.sum index 58b85d1be99..092bf569793 100644 --- a/go.sum +++ b/go.sum @@ -342,8 +342,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva v1.16.1-0.20220301071903-1fd81b097801 h1:FOjP9FbcvD48as7Q7TjOtnaNHlQ5va2IEIed1GWqEag= -github.com/cs3org/reva v1.16.1-0.20220301071903-1fd81b097801/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= +github.com/cs3org/reva v1.16.1-0.20220228144359-3e80be7f6667 h1:6Cjm0dV/6RcneBhnMAJmUDYgxzeEizumRnDyqiVvDJQ= +github.com/cs3org/reva v1.16.1-0.20220228144359-3e80be7f6667/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= From 1cde2fa36bbe5d48e56fb6916989da833289fa0a Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 3 Mar 2022 11:15:36 +0100 Subject: [PATCH 21/42] use feature reva Signed-off-by: jkoberg --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a23a98e0449..d7965c817c4 100644 --- a/go.mod +++ b/go.mod @@ -276,4 +276,4 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 -replace github.com/cs3org/reva => github.com/cs3org/reva v1.16.1-0.20220228144359-3e80be7f6667 +replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303101200-03258eac912d From 15ac5d89996a0cdcf755dcf21589da258545de89 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 3 Mar 2022 16:06:33 +0100 Subject: [PATCH 22/42] make it configurable Signed-off-by: jkoberg --- settings/pkg/config/config.go | 14 +++++++++++++- settings/pkg/config/defaultconfig.go | 10 +++++++++- settings/pkg/store/metadata/store.go | 25 +++++++++---------------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/settings/pkg/config/config.go b/settings/pkg/config/config.go index 8e9e5f1efff..bc25dbc7cdb 100644 --- a/settings/pkg/config/config.go +++ b/settings/pkg/config/config.go @@ -19,7 +19,10 @@ type Config struct { HTTP HTTP `ocisConfig:"http"` GRPC GRPC `ocisConfig:"grpc"` - DataPath string `ocisConfig:"data_path" env:"SETTINGS_DATA_PATH"` + StoreType string `ocisConfig:"store_type" env:"SETTINGS_STORE_TYPE"` + DataPath string `ocisConfig:"data_path" env:"SETTINGS_DATA_PATH"` + Metadata Metadata `ocisConfig:"metadata_config"` + Asset Asset `ocisConfig:"asset"` TokenManager TokenManager `ocisConfig:"token_manager"` @@ -30,3 +33,12 @@ type Config struct { type Asset struct { Path string `ocisConfig:"path" env:"SETTINGS_ASSET_PATH"` } + +// Metadata configures the metadata store to use +type Metadata struct { + GatewayAddress string `ocisConfig:"gateway_addr" env:"STORAGE_GATEWAY_GRPC_ADDR"` + StorageAddress string `ocisConfig:"storage_addr" env:"STORAGE_GRPC_ADDR"` + + ServiceUserID string `ocisConfig:"service_user_id" env:"METADATA_SERVICE_USER_UUID"` + MachineAuthAPIKey string `ocisConfig:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` +} diff --git a/settings/pkg/config/defaultconfig.go b/settings/pkg/config/defaultconfig.go index 7f72e50a300..363c002f31d 100644 --- a/settings/pkg/config/defaultconfig.go +++ b/settings/pkg/config/defaultconfig.go @@ -33,12 +33,20 @@ func DefaultConfig() *Config { Addr: "127.0.0.1:9191", Namespace: "com.owncloud.api", }, - DataPath: path.Join(defaults.BaseDataPath(), "settings"), + StoreType: "metadata", // use metadata or filesystem + DataPath: path.Join(defaults.BaseDataPath(), "settings"), Asset: Asset{ Path: "", }, TokenManager: TokenManager{ JWTSecret: "Pive-Fumkiu4", }, + + Metadata: Metadata{ + GatewayAddress: "127.0.0.1:9142", + StorageAddress: "127.0.0.1:9215", + ServiceUserID: "058bff95-6708-4fe5-91e4-9ea3d377588b", + MachineAuthAPIKey: "change-me-please", + }, } } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index ef7c2b2a6a1..e1edb8bb105 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -41,9 +41,9 @@ type MetadataClient interface { type Store struct { Logger olog.Logger - mdc MetadataClient - cfg *config.Config - initStore func(settings.Manager) + mdc MetadataClient + cfg *config.Config + //initStore func(settings.Manager) init *sync.Once l *sync.Mutex @@ -60,14 +60,7 @@ func (s *Store) Init() { var err error //s.init.Do(func() { - //b := backoff.NewExponentialBackOff() - //b.MaxElapsedTime = 4 * time.Second - //backoff.Retry(func() error { - err = s.initMetadataClient(NewMetadataClient(s.cfg)) - //return err - - //}, b) - + err = s.initMetadataClient(NewMetadataClient(s.cfg.Metadata)) //}) if err != nil { log.Fatal("error initializing metadata client: ", err) @@ -83,17 +76,17 @@ func New(cfg *config.Config, initstore func(settings.Manager)) settings.Manager //olog.Level(cfg.Log.Level), //olog.File(cfg.Log.File), //), - initStore: initstore, - l: &sync.Mutex{}, - init: &sync.Once{}, + cfg: cfg, + l: &sync.Mutex{}, + init: &sync.Once{}, } return &s } // NewMetadataClient returns the MetadataClient -func NewMetadataClient(cfg *config.Config) MetadataClient { - mdc, err := metadata.NewCS3Storage("127.0.0.1:9142", "127.0.0.1:9215", "058bff95-6708-4fe5-91e4-9ea3d377588b", "change-me-please") +func NewMetadataClient(cfg config.Metadata) MetadataClient { + mdc, err := metadata.NewCS3Storage(cfg.GatewayAddress, cfg.StorageAddress, cfg.ServiceUserID, cfg.MachineAuthAPIKey) if err != nil { log.Fatal("error connecting to mdc:", err) } From ba698aa6d9717a65298492cbebd34d6ea2405e66 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 3 Mar 2022 16:07:46 +0100 Subject: [PATCH 23/42] next reva version Signed-off-by: jkoberg --- go.mod | 2 +- go.sum | 4 ++-- settings/pkg/store/metadata/store_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 234f66a0734..413b18b3aad 100644 --- a/go.mod +++ b/go.mod @@ -276,4 +276,4 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 -replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303101200-03258eac912d +replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63 diff --git a/go.sum b/go.sum index 65f3c08232c..48b003db544 100644 --- a/go.sum +++ b/go.sum @@ -910,8 +910,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= -github.com/kobergj/reva v1.13.1-0.20220303101200-03258eac912d h1:pEytDpB4JhfL+iieFUHyccJ0yY04pXTogIuypT8yEDI= -github.com/kobergj/reva v1.13.1-0.20220303101200-03258eac912d/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= +github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63 h1:21BFxUUBOYqEGHTEsXSSJLhESpXPU5rXp+9cVS0cqWI= +github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index 6ce91a16d3d..b1315809436 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -48,7 +48,7 @@ func NewMDC(s *Store) MetadataClient { case "unit": mdc = &MockedMetadataClient{data: make(map[string][]byte)} case "integration": - mdc = NewMetadataClient(&config.Config{}) + mdc = NewMetadataClient(config.DefaultConfig().Metadata) } s.initMetadataClient(mdc) return nil From 8f102269639edd086125eb9364e187e3b5df3c34 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 3 Mar 2022 16:45:52 +0100 Subject: [PATCH 24/42] next reva bump Signed-off-by: jkoberg --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 413b18b3aad..982128bc43d 100644 --- a/go.mod +++ b/go.mod @@ -276,4 +276,4 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 -replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63 +replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf diff --git a/go.sum b/go.sum index 48b003db544..9755c39732c 100644 --- a/go.sum +++ b/go.sum @@ -910,8 +910,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= -github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63 h1:21BFxUUBOYqEGHTEsXSSJLhESpXPU5rXp+9cVS0cqWI= -github.com/kobergj/reva v1.13.1-0.20220303150541-5d26b3f53d63/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= +github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf h1:SOzP8F2D1er8MWjafd4cIp2IHjkj28QwBZEIjukY/eg= +github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= From da3fc4c898f6fb52ae46b185992915922de5bd03 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Thu, 3 Mar 2022 16:47:51 +0100 Subject: [PATCH 25/42] don't log fatal on startup Signed-off-by: jkoberg --- settings/pkg/store/metadata/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index e1edb8bb105..703579db207 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -63,7 +63,7 @@ func (s *Store) Init() { err = s.initMetadataClient(NewMetadataClient(s.cfg.Metadata)) //}) if err != nil { - log.Fatal("error initializing metadata client: ", err) + s.Logger.Error().Err(err).Msg("error initializing metadata client") } } From 634c69e2b8e7299ea6c34ca63970306989bd977b Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 4 Mar 2022 12:11:06 +0100 Subject: [PATCH 26/42] bump web master Signed-off-by: jkoberg --- .drone.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.env b/.drone.env index 6225affdba1..ea935556411 100644 --- a/.drone.env +++ b/.drone.env @@ -3,5 +3,5 @@ CORE_COMMITID=4512f46e7196a8c1f1cfc56ec397628cbf540407 CORE_BRANCH=master # The test runner source for UI tests -WEB_COMMITID=b240ba9117e998edc0cd7d1d5586ba19591e1511 +WEB_COMMITID=fbbb6544210ee072bb154071e8466b1dc074885f WEB_BRANCH=master From b8aaed66a09ebc03c27dde0cd6136fd3de542ef8 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 4 Mar 2022 14:11:03 +0100 Subject: [PATCH 27/42] tmp: use custom web branch to uncover the error Signed-off-by: jkoberg --- .drone.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.env b/.drone.env index ea935556411..3838a9e7790 100644 --- a/.drone.env +++ b/.drone.env @@ -3,5 +3,5 @@ CORE_COMMITID=4512f46e7196a8c1f1cfc56ec397628cbf540407 CORE_BRANCH=master # The test runner source for UI tests -WEB_COMMITID=fbbb6544210ee072bb154071e8466b1dc074885f -WEB_BRANCH=master +WEB_COMMITID=9c653448915aee3075ff5bb9475f9e8f74649359 +WEB_BRANCH=ExtendConfirmBtnTimeout From 2ae4959afb696557712b7000d85357b11d7008e4 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 4 Mar 2022 15:42:46 +0100 Subject: [PATCH 28/42] sonarcloud suggestions Signed-off-by: jkoberg --- settings/pkg/store/metadata/assignments.go | 22 +++++++++++-------- .../pkg/store/metadata/assignments_test.go | 7 +++--- settings/pkg/store/metadata/bundles.go | 16 +++++++++----- settings/pkg/store/metadata/store.go | 17 +++++++------- settings/pkg/store/metadata/store_test.go | 12 ++-------- settings/pkg/store/metadata/values.go | 14 ++++++++---- 6 files changed, 48 insertions(+), 40 deletions(-) diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 4fe6c9173ed..bf80cb71e04 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -2,6 +2,7 @@ package store import ( + "context" "encoding/json" "fmt" @@ -16,14 +17,15 @@ func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRole return defaultRoleAssignments(accountUUID), nil } s.Init() - assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) + ctx := context.TODO() + assIDs, err := s.mdc.ReadDir(ctx, accountPath(accountUUID)) if err != nil { return nil, err } - var ass []*settingsmsg.UserRoleAssignment + ass := make([]*settingsmsg.UserRoleAssignment, 0, len(assIDs)) for _, assID := range assIDs { - b, err := s.mdc.SimpleDownload(nil, assignmentPath(accountUUID, assID)) + b, err := s.mdc.SimpleDownload(ctx, assignmentPath(accountUUID, assID)) if err != nil { return nil, err } @@ -42,13 +44,14 @@ func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRole // 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(nil, accountPath(accountUUID)) + err := s.mdc.Delete(ctx, accountPath(accountUUID)) if err != nil { // TODO: How to differentiate between 'not found' and other errors? } - err = s.mdc.MakeDirIfNotExist(nil, accountPath(accountUUID)) + err = s.mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID)) if err != nil { return nil, err } @@ -62,20 +65,21 @@ func (s *Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.Us if err != nil { return nil, err } - return ass, s.mdc.SimpleUpload(nil, assignmentPath(accountUUID, ass.Id), b) + 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() - accounts, err := s.mdc.ReadDir(nil, accountsFolderLocation) + ctx := context.TODO() + accounts, err := s.mdc.ReadDir(ctx, accountsFolderLocation) if err != nil { return err } // TODO: use indexer to avoid spamming Metadata service for _, accID := range accounts { - assIDs, err := s.mdc.ReadDir(nil, accountPath(accID)) + assIDs, err := s.mdc.ReadDir(ctx, accountPath(accID)) if err != nil { // TODO: error? continue @@ -83,7 +87,7 @@ func (s *Store) RemoveRoleAssignment(assignmentID string) error { for _, assID := range assIDs { if assID == assignmentID { - return s.mdc.Delete(nil, assignmentPath(accID, assID)) + return s.mdc.Delete(ctx, assignmentPath(accID, assID)) } } } diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index 5dae88ae945..8c436927977 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -15,16 +15,16 @@ var ( //marie = "3c054db3-eec1-4ca4-b985-bc56dcf560cb" s = &Store{ - l: &sync.Mutex{}, + Logger: logger, + l: &sync.Mutex{}, } + logger = olog.NewLogger( olog.Color(true), olog.Pretty(true), olog.Level("info"), ) - mdc = NewMDC(s) - bundles = []*settingsmsg.Bundle{ { Id: "f36db5e6-a03c-40df-8413-711c67e40b47", @@ -87,6 +87,7 @@ var ( ) func init() { + NewMDC(s) setupRoles() } diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 3c3d449dba7..816f0e4aa36 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -2,6 +2,7 @@ package store import ( + "context" "encoding/json" "errors" "fmt" @@ -18,9 +19,10 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri return defaultBundle(bundleType, bundleIDs[0]), nil } s.Init() + ctx := context.TODO() if len(bundleIDs) == 0 { - bIDs, err := s.mdc.ReadDir(nil, bundleFolderLocation) + bIDs, err := s.mdc.ReadDir(ctx, bundleFolderLocation) if err != nil { return nil, err } @@ -29,7 +31,7 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri } var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { - b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) + b, err := s.mdc.SimpleDownload(ctx, bundlePath(id)) if err != nil { return nil, err } @@ -54,7 +56,8 @@ func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { return defaultBundle(settingsmsg.Bundle_TYPE_ROLE, bundleID)[0], nil } s.Init() - b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) + ctx := context.TODO() + b, err := s.mdc.SimpleDownload(ctx, bundlePath(bundleID)) if err != nil { return nil, err } @@ -66,8 +69,9 @@ func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { // ReadSetting tries to find a setting by the given id from the metadata service func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { s.Init() + ctx := context.TODO() - ids, err := s.mdc.ReadDir(nil, bundleFolderLocation) + ids, err := s.mdc.ReadDir(ctx, bundleFolderLocation) if err != nil { return nil, err } @@ -92,11 +96,13 @@ func (s *Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { // WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons func (s *Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { s.Init() + ctx := context.TODO() + b, err := json.Marshal(record) if err != nil { return nil, err } - return record, s.mdc.SimpleUpload(nil, bundlePath(record.Id), b) + return record, s.mdc.SimpleUpload(ctx, bundlePath(record.Id), b) } // AddSettingToBundle adds the given setting to the bundle with the given bundleID. diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 703579db207..6ba5fcab2cc 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -58,13 +58,11 @@ func (s *Store) Init() { s.l.Lock() defer s.l.Unlock() - var err error //s.init.Do(func() { - err = s.initMetadataClient(NewMetadataClient(s.cfg.Metadata)) - //}) - if err != nil { + if err := s.initMetadataClient(NewMetadataClient(s.cfg.Metadata)); err != nil { s.Logger.Error().Err(err).Msg("error initializing metadata client") } + //}) } // New creates a new store @@ -96,7 +94,8 @@ func NewMetadataClient(cfg config.Metadata) MetadataClient { // we need to lazy initialize the MetadataClient because metadata service might not be ready func (s *Store) initMetadataClient(mdc MetadataClient) error { - err := mdc.Init(nil, settingsSpaceID) + ctx := context.TODO() + err := mdc.Init(ctx, settingsSpaceID) if err != nil { return err } @@ -107,7 +106,7 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { bundleFolderLocation, valuesFolderLocation, } { - err = mdc.MakeDirIfNotExist(nil, p) + err = mdc.MakeDirIfNotExist(ctx, p) if err != nil { return err } @@ -118,7 +117,7 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { if err != nil { return err } - err = mdc.SimpleUpload(nil, bundlePath(p.Id), b) + err = mdc.SimpleUpload(ctx, bundlePath(p.Id), b) if err != nil { return err } @@ -127,7 +126,7 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { for _, p := range defaults.DefaultRoleAssignments() { accountUUID := p.AccountUuid roleID := p.RoleId - err = mdc.MakeDirIfNotExist(nil, accountPath(accountUUID)) + err = mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID)) if err != nil { return err } @@ -141,7 +140,7 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error { if err != nil { return err } - err = mdc.SimpleUpload(nil, assignmentPath(accountUUID, ass.Id), b) + err = mdc.SimpleUpload(ctx, assignmentPath(accountUUID, ass.Id), b) if err != nil { return err } diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index b1315809436..8772ac29681 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -42,7 +42,7 @@ type MockedMetadataClient struct { } // NewMDC instantiates a mocked MetadataClient -func NewMDC(s *Store) MetadataClient { +func NewMDC(s *Store) error { var mdc MetadataClient switch testtype { case "unit": @@ -50,15 +50,7 @@ func NewMDC(s *Store) MetadataClient { case "integration": mdc = NewMetadataClient(config.DefaultConfig().Metadata) } - s.initMetadataClient(mdc) - return nil -} - -func keys(m map[string][]byte) (s []string) { - for k := range m { - s = append(s, k) - } - return + return s.initMetadataClient(mdc) } // SimpleDownload returns nil if not found diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index 212527160a3..9dd73b16d1b 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -2,6 +2,7 @@ package store import ( + "context" "encoding/json" "errors" "fmt" @@ -16,8 +17,9 @@ import ( // If the accountUUID is not empty, values with an empty or with a matching accountUUID are returned. func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, error) { s.Init() + ctx := context.TODO() - vIDs, err := s.mdc.ReadDir(nil, valuesFolderLocation) + vIDs, err := s.mdc.ReadDir(ctx, valuesFolderLocation) if err != nil { return nil, err } @@ -25,7 +27,7 @@ func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, // TODO: refine logic not to spam metadata service var values []*settingsmsg.Value for _, vid := range vIDs { - b, err := s.mdc.SimpleDownload(nil, valuePath(vid)) + b, err := s.mdc.SimpleDownload(ctx, valuePath(vid)) if err != nil { return nil, err } @@ -56,7 +58,9 @@ func (s *Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, // ReadValue tries to find a value by the given valueId within the dataPath func (s *Store) ReadValue(valueID string) (*settingsmsg.Value, error) { s.Init() - b, err := s.mdc.SimpleDownload(nil, valuePath(valueID)) + ctx := context.TODO() + + b, err := s.mdc.SimpleDownload(ctx, valuePath(valueID)) if err != nil { return nil, err } @@ -73,6 +77,8 @@ func (s *Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*se // WriteValue writes the given value into a file within the dataPath func (s *Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { s.Init() + ctx := context.TODO() + if value.Id == "" { value.Id = uuid.Must(uuid.NewV4()).String() } @@ -80,7 +86,7 @@ func (s *Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) if err != nil { return nil, err } - return value, s.mdc.SimpleUpload(nil, valuePath(value.Id), b) + return value, s.mdc.SimpleUpload(ctx, valuePath(value.Id), b) } func valuePath(id string) string { From fc5a67c45e21f05007f59836fd3b6c9d4ace0c6d Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 4 Mar 2022 16:04:40 +0100 Subject: [PATCH 29/42] sonarcloud part II Signed-off-by: jkoberg --- settings/pkg/store/metadata/assignments.go | 8 +++----- settings/pkg/store/metadata/assignments_test.go | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index bf80cb71e04..7095ab69262 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -46,12 +46,10 @@ 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" - err := s.mdc.Delete(ctx, accountPath(accountUUID)) - if err != nil { - // TODO: How to differentiate between 'not found' and other errors? - } + _ = s.mdc.Delete(ctx, accountPath(accountUUID)) + // TODO: How to differentiate between 'not found' and other errors? - err = s.mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID)) + err := s.mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID)) if err != nil { return nil, err } diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index 8c436927977..6f75ef1be29 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -87,7 +87,7 @@ var ( ) func init() { - NewMDC(s) + _ = NewMDC(s) setupRoles() } From 1d98e4827ee1f741b43d0d434b1715d2a836ce1f Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 5 Mar 2022 12:57:57 +0100 Subject: [PATCH 30/42] add caching Signed-off-by: jkoberg --- settings/pkg/store/metadata/cache.go | 124 +++++++++++++++++++++++++++ settings/pkg/store/metadata/store.go | 7 +- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 settings/pkg/store/metadata/cache.go diff --git a/settings/pkg/store/metadata/cache.go b/settings/pkg/store/metadata/cache.go new file mode 100644 index 00000000000..f2e80d8ca26 --- /dev/null +++ b/settings/pkg/store/metadata/cache.go @@ -0,0 +1,124 @@ +package store + +import ( + "context" + "path" + "strings" + "time" + + "github.com/ReneKroon/ttlcache/v2" +) + +var ( + cachettl = 0 + // these need to be global instances for now as the `Service` (and therefore the `Store`) are instantiated twice (for grpc and http) + // therefore caches need to cover both instances + dircache = initCache(cachettl) + filescache = initCache(cachettl) +) + +// CachedMDC is cache for the metadataclient +type CachedMDC struct { + next MetadataClient + + files *ttlcache.Cache + dirs *ttlcache.Cache +} + +// SimpleDownload caches the answer from SimpleDownload or returns the cached one +func (c *CachedMDC) SimpleDownload(ctx context.Context, id string) ([]byte, error) { + if b, err := c.files.Get(id); err == nil { + return b.([]byte), nil + } + b, err := c.next.SimpleDownload(ctx, id) + if err != nil { + return nil, err + } + + c.files.Set(id, b) + return b, nil +} + +// SimpleUpload caches the answer from SimpleUpload and invalidates the cache +func (c *CachedMDC) SimpleUpload(ctx context.Context, id string, content []byte) error { + b, err := c.files.Get(id) + if err == nil && string(b.([]byte)) == string(content) { + // no need to bug mdc + return nil + } + + err = c.next.SimpleUpload(ctx, id, content) + if err != nil { + return err + } + + // invalidate caches + err = c.dirs.Remove(path.Dir(id)) + err = c.files.Set(id, content) + return nil +} + +// Delete invalidates the cache when operation was successful +func (c *CachedMDC) Delete(ctx context.Context, id string) error { + err := c.next.Delete(ctx, id) + if err != nil { + return err + } + + // invalidate caches + _ = removePrefix(c.files, id) + _ = removePrefix(c.dirs, id) + return nil +} + +// ReadDir caches the response from ReadDir or returnes the cached one +func (c *CachedMDC) ReadDir(ctx context.Context, id string) ([]string, error) { + i, err := c.dirs.Get(id) + if err == nil { + return i.([]string), nil + } + + s, err := c.next.ReadDir(ctx, id) + if err != nil { + return nil, err + } + + return s, c.dirs.Set(id, s) +} + +// MakeDirIfNotExist invalidates the cache +func (c *CachedMDC) MakeDirIfNotExist(ctx context.Context, id string) error { + err := c.next.MakeDirIfNotExist(ctx, id) + if err != nil { + return err + } + + // invalidate caches + _ = c.dirs.Remove(path.Dir(id)) + return nil +} + +// Init instantiates the caches +func (c *CachedMDC) Init(ctx context.Context, id string) error { + c.dirs = dircache + c.files = filescache + return c.next.Init(ctx, id) +} + +func initCache(ttlSeconds int) *ttlcache.Cache { + cache := ttlcache.NewCache() + _ = cache.SetTTL(time.Duration(ttlSeconds) * time.Second) + cache.SkipTTLExtensionOnHit(true) + return cache +} + +func removePrefix(cache *ttlcache.Cache, prefix string) error { + for _, k := range cache.GetKeys() { + if strings.HasPrefix(k, prefix) { + if err := cache.Remove(k); err != nil { + return err + } + } + } + return nil +} diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 6ba5fcab2cc..e0106f6ca7d 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -58,8 +58,13 @@ func (s *Store) Init() { s.l.Lock() defer s.l.Unlock() + if s.mdc != nil { + return + } + //s.init.Do(func() { - if err := s.initMetadataClient(NewMetadataClient(s.cfg.Metadata)); err != nil { + mdc := &CachedMDC{next: NewMetadataClient(s.cfg.Metadata)} + if err := s.initMetadataClient(mdc); err != nil { s.Logger.Error().Err(err).Msg("error initializing metadata client") } //}) From 1205d3489ed47b12e381e3095057bab8add79745 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 5 Mar 2022 13:01:11 +0100 Subject: [PATCH 31/42] illustrate the problem Signed-off-by: jkoberg --- settings/pkg/store/metadata/cache.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/settings/pkg/store/metadata/cache.go b/settings/pkg/store/metadata/cache.go index f2e80d8ca26..48977858a6c 100644 --- a/settings/pkg/store/metadata/cache.go +++ b/settings/pkg/store/metadata/cache.go @@ -2,6 +2,7 @@ package store import ( "context" + "fmt" "path" "strings" "time" @@ -78,7 +79,9 @@ func (c *CachedMDC) ReadDir(ctx context.Context, id string) ([]string, error) { return i.([]string), nil } + fmt.Println("readdir calling metadataservice", id) s, err := c.next.ReadDir(ctx, id) + fmt.Println("readdir calling metadataservice result", s, err) if err != nil { return nil, err } From 429ed2ee7672fd002c2342ccbf1335e9c4e32f7e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 5 Mar 2022 13:11:09 +0100 Subject: [PATCH 32/42] use different user Signed-off-by: jkoberg --- settings/pkg/config/defaultconfig.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/pkg/config/defaultconfig.go b/settings/pkg/config/defaultconfig.go index 363c002f31d..ff41af872e7 100644 --- a/settings/pkg/config/defaultconfig.go +++ b/settings/pkg/config/defaultconfig.go @@ -45,7 +45,7 @@ func DefaultConfig() *Config { Metadata: Metadata{ GatewayAddress: "127.0.0.1:9142", StorageAddress: "127.0.0.1:9215", - ServiceUserID: "058bff95-6708-4fe5-91e4-9ea3d377588b", + ServiceUserID: "ddc2004c-0977-11eb-9d3f-a793888cd0f8", MachineAuthAPIKey: "change-me-please", }, } From d8242232e4c28c62f499cd4fac4c0179eced3389 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 5 Mar 2022 13:46:10 +0100 Subject: [PATCH 33/42] clean up Signed-off-by: jkoberg --- settings/pkg/service/v0/service.go | 27 +++++++++++++++++--------- settings/pkg/settings/settings.go | 2 +- settings/pkg/store/filesystem/store.go | 3 +-- settings/pkg/store/metadata/cache.go | 9 ++++----- settings/pkg/store/metadata/store.go | 25 ++++++++++-------------- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index 77bae1945eb..a59c17ffce0 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -15,7 +15,8 @@ import ( settingssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/settings/v0" "github.com/owncloud/ocis/settings/pkg/config" "github.com/owncloud/ocis/settings/pkg/settings" - store "github.com/owncloud/ocis/settings/pkg/store/metadata" + filestore "github.com/owncloud/ocis/settings/pkg/store/filesystem" + metastore "github.com/owncloud/ocis/settings/pkg/store/metadata" merrors "go-micro.dev/v4/errors" "go-micro.dev/v4/metadata" "google.golang.org/protobuf/types/known/emptypb" @@ -36,7 +37,17 @@ func NewService(cfg *config.Config, logger log.Logger) Service { config: cfg, logger: logger, } - service.manager = store.New(cfg, service.RegisterDefaultRoles) + + switch cfg.StoreType { + default: + fallthrough + case "metadata": + service.manager = metastore.New(cfg) + case "filesystem": + service.manager = filestore.New(cfg) + // TODO: if we want to further support filesystem store it should use default permissions from store/defaults.go instead using this duplicate + service.RegisterDefaultRoles() + } return service } @@ -86,20 +97,18 @@ func (g Service) CheckPermission(ctx context.Context, req *permissions.CheckPerm } // RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist. -// NOTE: we can't register on service start any more because metadata might not be up yet -// we need to lazy initialize -func (g Service) RegisterDefaultRoles(m settings.Manager) { +func (g Service) RegisterDefaultRoles() { // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). has to happen only once. for _, role := range generateBundlesDefaultRoles() { bundleID := role.Extension + "." + role.Id // check if the role already exists - bundle, _ := m.ReadBundle(role.Id) + bundle, _ := g.manager.ReadBundle(role.Id) if bundle != nil { g.logger.Debug().Str("bundleID", bundleID).Msg("bundle already exists. skipping.") continue } // create the role - _, err := m.WriteBundle(role) + _, err := g.manager.WriteBundle(role) if err != nil { g.logger.Error().Err(err).Str("bundleID", bundleID).Msg("failed to register bundle") } @@ -107,7 +116,7 @@ func (g Service) RegisterDefaultRoles(m settings.Manager) { } for _, req := range generatePermissionRequests() { - _, err := m.AddSettingToBundle(req.GetBundleId(), req.GetSetting()) + _, err := g.manager.AddSettingToBundle(req.GetBundleId(), req.GetSetting()) if err != nil { g.logger.Error(). Err(err). @@ -118,7 +127,7 @@ func (g Service) RegisterDefaultRoles(m settings.Manager) { } for _, req := range defaultRoleAssignments() { - if _, err := m.WriteRoleAssignment(req.AccountUuid, req.RoleId); err != nil { + if _, err := g.manager.WriteRoleAssignment(req.AccountUuid, req.RoleId); err != nil { g.logger.Error().Err(err).Msg("failed to register role assignment") } } diff --git a/settings/pkg/settings/settings.go b/settings/pkg/settings/settings.go index 0f3cf9fe52c..9132423e8f4 100644 --- a/settings/pkg/settings/settings.go +++ b/settings/pkg/settings/settings.go @@ -16,7 +16,7 @@ var ( ) // RegisterFunc stores store constructors -type RegisterFunc func(*config.Config, func(Manager)) Manager +type RegisterFunc func(*config.Config) Manager // Manager combines service interfaces for abstraction of storage implementations type Manager interface { diff --git a/settings/pkg/store/filesystem/store.go b/settings/pkg/store/filesystem/store.go index fee4c7ebd3f..ccd0fe0111a 100644 --- a/settings/pkg/store/filesystem/store.go +++ b/settings/pkg/store/filesystem/store.go @@ -22,7 +22,7 @@ type Store struct { } // New creates a new store -func New(cfg *config.Config, initStore func(settings.Manager)) settings.Manager { +func New(cfg *config.Config) settings.Manager { s := Store{ //Logger: olog.NewLogger( // olog.Color(cfg.Log.Color), @@ -42,7 +42,6 @@ func New(cfg *config.Config, initStore func(settings.Manager)) settings.Manager } s.dataPath = cfg.DataPath - initStore(&s) return &s } diff --git a/settings/pkg/store/metadata/cache.go b/settings/pkg/store/metadata/cache.go index 48977858a6c..0f036c592db 100644 --- a/settings/pkg/store/metadata/cache.go +++ b/settings/pkg/store/metadata/cache.go @@ -36,7 +36,7 @@ func (c *CachedMDC) SimpleDownload(ctx context.Context, id string) ([]byte, erro return nil, err } - c.files.Set(id, b) + _ = c.files.Set(id, b) return b, nil } @@ -54,15 +54,14 @@ func (c *CachedMDC) SimpleUpload(ctx context.Context, id string, content []byte) } // invalidate caches - err = c.dirs.Remove(path.Dir(id)) - err = c.files.Set(id, content) + _ = c.dirs.Remove(path.Dir(id)) + _ = c.files.Set(id, content) return nil } // Delete invalidates the cache when operation was successful func (c *CachedMDC) Delete(ctx context.Context, id string) error { - err := c.next.Delete(ctx, id) - if err != nil { + if err := c.next.Delete(ctx, id); err != nil { return err } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index e0106f6ca7d..50e32596a8c 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -43,10 +43,8 @@ type Store struct { mdc MetadataClient cfg *config.Config - //initStore func(settings.Manager) - init *sync.Once - l *sync.Mutex + l *sync.Mutex } // Init initialize the store once, later calls are noops @@ -62,26 +60,23 @@ func (s *Store) Init() { return } - //s.init.Do(func() { mdc := &CachedMDC{next: NewMetadataClient(s.cfg.Metadata)} if err := s.initMetadataClient(mdc); err != nil { s.Logger.Error().Err(err).Msg("error initializing metadata client") } - //}) } // New creates a new store -func New(cfg *config.Config, initstore func(settings.Manager)) settings.Manager { +func New(cfg *config.Config) settings.Manager { s := Store{ - //Logger: olog.NewLogger( - //olog.Color(cfg.Log.Color), - //olog.Pretty(cfg.Log.Pretty), - //olog.Level(cfg.Log.Level), - //olog.File(cfg.Log.File), - //), - cfg: cfg, - l: &sync.Mutex{}, - init: &sync.Once{}, + Logger: olog.NewLogger( + olog.Color(cfg.Log.Color), + olog.Pretty(cfg.Log.Pretty), + olog.Level(cfg.Log.Level), + olog.File(cfg.Log.File), + ), + cfg: cfg, + l: &sync.Mutex{}, } return &s From 0af1c98d38652af800645cbf6f24b93edabaadde Mon Sep 17 00:00:00 2001 From: jkoberg Date: Sat, 5 Mar 2022 13:47:13 +0100 Subject: [PATCH 34/42] Revert "tmp: use custom web branch to uncover the error" This reverts commit b8aaed66a09ebc03c27dde0cd6136fd3de542ef8. --- .drone.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.env b/.drone.env index 3838a9e7790..ea935556411 100644 --- a/.drone.env +++ b/.drone.env @@ -3,5 +3,5 @@ CORE_COMMITID=4512f46e7196a8c1f1cfc56ec397628cbf540407 CORE_BRANCH=master # The test runner source for UI tests -WEB_COMMITID=9c653448915aee3075ff5bb9475f9e8f74649359 -WEB_BRANCH=ExtendConfirmBtnTimeout +WEB_COMMITID=fbbb6544210ee072bb154071e8466b1dc074885f +WEB_BRANCH=master From 7bfeb162bc28ecc25ae7eb9f3bbb69a600988738 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 7 Mar 2022 10:47:29 +0100 Subject: [PATCH 35/42] use settings user Signed-off-by: jkoberg --- accounts/pkg/config/defaultconfig.go | 2 +- settings/pkg/config/defaultconfig.go | 2 +- settings/pkg/service/v0/service.go | 2 +- settings/pkg/store/metadata/assignments_test.go | 2 ++ settings/pkg/store/metadata/bundles.go | 2 +- settings/pkg/store/metadata/cache.go | 3 --- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/accounts/pkg/config/defaultconfig.go b/accounts/pkg/config/defaultconfig.go index 394cf2155ff..f04d1af2cf1 100644 --- a/accounts/pkg/config/defaultconfig.go +++ b/accounts/pkg/config/defaultconfig.go @@ -60,7 +60,7 @@ func DefaultConfig() *Config { }, ServiceUser: ServiceUser{ UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Username: "", + Username: "service user", UID: 0, GID: 0, }, diff --git a/settings/pkg/config/defaultconfig.go b/settings/pkg/config/defaultconfig.go index ff41af872e7..44d522a5f87 100644 --- a/settings/pkg/config/defaultconfig.go +++ b/settings/pkg/config/defaultconfig.go @@ -45,7 +45,7 @@ func DefaultConfig() *Config { Metadata: Metadata{ GatewayAddress: "127.0.0.1:9142", StorageAddress: "127.0.0.1:9215", - ServiceUserID: "ddc2004c-0977-11eb-9d3f-a793888cd0f8", + ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", MachineAuthAPIKey: "change-me-please", }, } diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index a59c17ffce0..3d15a226dd2 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -45,7 +45,7 @@ func NewService(cfg *config.Config, logger log.Logger) Service { service.manager = metastore.New(cfg) case "filesystem": service.manager = filestore.New(cfg) - // TODO: if we want to further support filesystem store it should use default permissions from store/defaults.go instead using this duplicate + // TODO: if we want to further support filesystem store it should use default permissions from store/defaults/defaults.go instead using this duplicate service.RegisterDefaultRoles() } return service diff --git a/settings/pkg/store/metadata/assignments_test.go b/settings/pkg/store/metadata/assignments_test.go index 6f75ef1be29..6e7bf3574dd 100644 --- a/settings/pkg/store/metadata/assignments_test.go +++ b/settings/pkg/store/metadata/assignments_test.go @@ -7,6 +7,7 @@ import ( olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" + "github.com/owncloud/ocis/settings/pkg/config" "github.com/stretchr/testify/require" ) @@ -17,6 +18,7 @@ var ( s = &Store{ Logger: logger, l: &sync.Mutex{}, + cfg: config.DefaultConfig(), } logger = olog.NewLogger( diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 816f0e4aa36..766d6cf2625 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -50,7 +50,7 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri return bundles, nil } -// ReadBundle tries to find a bundle by the given id within the dataPath. +// ReadBundle tries to find a bundle by the given id from the metadata service func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { if s.mdc == nil { return defaultBundle(settingsmsg.Bundle_TYPE_ROLE, bundleID)[0], nil diff --git a/settings/pkg/store/metadata/cache.go b/settings/pkg/store/metadata/cache.go index 0f036c592db..2b00496202b 100644 --- a/settings/pkg/store/metadata/cache.go +++ b/settings/pkg/store/metadata/cache.go @@ -2,7 +2,6 @@ package store import ( "context" - "fmt" "path" "strings" "time" @@ -78,9 +77,7 @@ func (c *CachedMDC) ReadDir(ctx context.Context, id string) ([]string, error) { return i.([]string), nil } - fmt.Println("readdir calling metadataservice", id) s, err := c.next.ReadDir(ctx, id) - fmt.Println("readdir calling metadataservice result", s, err) if err != nil { return nil, err } From f4619dbb4706b422c061518fce8de158e168b4b2 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 7 Mar 2022 11:55:33 +0100 Subject: [PATCH 36/42] make service user configurable Signed-off-by: jkoberg --- go.mod | 2 +- go.sum | 4 ++-- settings/pkg/config/config.go | 1 + settings/pkg/config/defaultconfig.go | 1 + settings/pkg/store/metadata/store.go | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index b39fd09e619..c77dc1ffda6 100644 --- a/go.mod +++ b/go.mod @@ -277,4 +277,4 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 -replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf +replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae diff --git a/go.sum b/go.sum index ac2efc71b9b..21e6b1d3882 100644 --- a/go.sum +++ b/go.sum @@ -912,8 +912,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= -github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf h1:SOzP8F2D1er8MWjafd4cIp2IHjkj28QwBZEIjukY/eg= -github.com/kobergj/reva v1.13.1-0.20220303154205-2c903784bfdf/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= +github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae h1:gbjYn6OqFtTIX9wkX5Hhh4GMSoLSByN1O48WvSJ9jy8= +github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= diff --git a/settings/pkg/config/config.go b/settings/pkg/config/config.go index bc25dbc7cdb..b9a56236c31 100644 --- a/settings/pkg/config/config.go +++ b/settings/pkg/config/config.go @@ -40,5 +40,6 @@ type Metadata struct { StorageAddress string `ocisConfig:"storage_addr" env:"STORAGE_GRPC_ADDR"` ServiceUserID string `ocisConfig:"service_user_id" env:"METADATA_SERVICE_USER_UUID"` + ServiceUserIDP string `ocisConfig:"service_user_idp" env:"METADATA_SERVICE_USER_IDP"` MachineAuthAPIKey string `ocisConfig:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` } diff --git a/settings/pkg/config/defaultconfig.go b/settings/pkg/config/defaultconfig.go index 44d522a5f87..8680140e3de 100644 --- a/settings/pkg/config/defaultconfig.go +++ b/settings/pkg/config/defaultconfig.go @@ -46,6 +46,7 @@ func DefaultConfig() *Config { GatewayAddress: "127.0.0.1:9142", StorageAddress: "127.0.0.1:9215", ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + ServiceUserIDP: "localhost:9200", MachineAuthAPIKey: "change-me-please", }, } diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 50e32596a8c..cd0b97a883b 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -84,7 +84,7 @@ func New(cfg *config.Config) settings.Manager { // NewMetadataClient returns the MetadataClient func NewMetadataClient(cfg config.Metadata) MetadataClient { - mdc, err := metadata.NewCS3Storage(cfg.GatewayAddress, cfg.StorageAddress, cfg.ServiceUserID, cfg.MachineAuthAPIKey) + mdc, err := metadata.NewCS3Storage(cfg.GatewayAddress, cfg.StorageAddress, cfg.ServiceUserID, cfg.ServiceUserIDP, cfg.MachineAuthAPIKey) if err != nil { log.Fatal("error connecting to mdc:", err) } From 9f8e7e8a93b4bcc46960eae5f61be58903b97935 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 7 Mar 2022 11:56:30 +0100 Subject: [PATCH 37/42] TMP: use adminuser/disable service user Signed-off-by: jkoberg --- accounts/pkg/config/defaultconfig.go | 8 ++++---- settings/pkg/config/defaultconfig.go | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/accounts/pkg/config/defaultconfig.go b/accounts/pkg/config/defaultconfig.go index f04d1af2cf1..3cbc396251d 100644 --- a/accounts/pkg/config/defaultconfig.go +++ b/accounts/pkg/config/defaultconfig.go @@ -59,10 +59,10 @@ func DefaultConfig() *Config { }, }, ServiceUser: ServiceUser{ - UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Username: "service user", - UID: 0, - GID: 0, + UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + // Username: "service user", + UID: 0, + GID: 0, }, } } diff --git a/settings/pkg/config/defaultconfig.go b/settings/pkg/config/defaultconfig.go index 8680140e3de..b254fb92c06 100644 --- a/settings/pkg/config/defaultconfig.go +++ b/settings/pkg/config/defaultconfig.go @@ -1,6 +1,7 @@ package config import ( + "os" "path" "github.com/owncloud/ocis/ocis-pkg/config/defaults" @@ -45,8 +46,8 @@ func DefaultConfig() *Config { Metadata: Metadata{ GatewayAddress: "127.0.0.1:9142", StorageAddress: "127.0.0.1:9215", - ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - ServiceUserIDP: "localhost:9200", + ServiceUserID: "ddc2004c-0977-11eb-9d3f-a793888cd0f8", + ServiceUserIDP: os.Getenv("OCIS_URL"), MachineAuthAPIKey: "change-me-please", }, } From 40cfa90b28ab2b6c50b1507de62986eaab8346dc Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 8 Mar 2022 10:27:46 +0100 Subject: [PATCH 38/42] rebase to edge reva Signed-off-by: jkoberg --- go.mod | 7 ++----- go.sum | 6 ++---- settings/pkg/store/metadata/store.go | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index c77dc1ffda6..a2ea6b87b40 100644 --- a/go.mod +++ b/go.mod @@ -22,8 +22,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.1 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 - github.com/cs3org/reva v0.0.0-00010101000000-000000000000 - github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81 + github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98 github.com/disintegration/imaging v1.6.2 github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733 github.com/go-chi/chi/v5 v5.0.7 @@ -47,6 +46,7 @@ require ( github.com/mennanov/fieldmask-utils v0.5.0 github.com/mitchellh/mapstructure v1.4.3 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 + github.com/nats-io/nats-server/v2 v2.7.3 github.com/nats-io/nats-streaming-server v0.24.2 github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 github.com/nmcclain/ldap v0.0.0-20210720162743-7f8d1e44eeba @@ -209,7 +209,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 // indirect - github.com/nats-io/nats-server/v2 v2.7.3 // indirect github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d // indirect github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect @@ -276,5 +275,3 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 - -replace github.com/cs3org/reva => github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae diff --git a/go.sum b/go.sum index 21e6b1d3882..b4e77e94860 100644 --- a/go.sum +++ b/go.sum @@ -342,8 +342,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81 h1:g6c1HYGTSpDnf6uNPXYIOySVk0P545zWUPmdPWEcMps= -github.com/cs3org/reva/v2 v2.0.0-20220304131900-b8be80d1ba81/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= +github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98 h1:yttz8BjGwdmI/sd81Xretzpss/wXnnmCsdJWDOiZfWs= +github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -912,8 +912,6 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= -github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae h1:gbjYn6OqFtTIX9wkX5Hhh4GMSoLSByN1O48WvSJ9jy8= -github.com/kobergj/reva v1.13.1-0.20220307095710-5e1b13a62aae/go.mod h1:fdlrnZ0f+UtAdpZfLG+4LM0ZrhT5V8tPEQt6ycYm82c= github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index cd0b97a883b..db0abdcb552 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -7,7 +7,7 @@ import ( "log" "sync" - "github.com/cs3org/reva/pkg/storage/utils/metadata" + "github.com/cs3org/reva/v2/pkg/storage/utils/metadata" "github.com/gofrs/uuid" olog "github.com/owncloud/ocis/ocis-pkg/log" settingsmsg "github.com/owncloud/ocis/protogen/gen/ocis/messages/settings/v0" From 1a9d4462b644fa286736720e42f4d2100291521c Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Fri, 11 Mar 2022 16:20:17 +0100 Subject: [PATCH 39/42] resolve conflicts --- .drone.env | 4 ++-- go.mod | 20 ++++++++++---------- go.sum | 37 ++++++++++++++++++++----------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/.drone.env b/.drone.env index ea935556411..26a22530078 100644 --- a/.drone.env +++ b/.drone.env @@ -1,7 +1,7 @@ # The test runner source for API tests -CORE_COMMITID=4512f46e7196a8c1f1cfc56ec397628cbf540407 +CORE_COMMITID=a293d131eb9475542c72e048ddd44b8b6cbe2c01 CORE_BRANCH=master # The test runner source for UI tests -WEB_COMMITID=fbbb6544210ee072bb154071e8466b1dc074885f +WEB_COMMITID=bb612cfc1c63316a159c7e29b81438595cef8fdb WEB_BRANCH=master diff --git a/go.mod b/go.mod index a2ea6b87b40..e4b41d946c3 100644 --- a/go.mod +++ b/go.mod @@ -41,25 +41,25 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0 github.com/iancoleman/strcase v0.2.0 github.com/justinas/alice v1.2.0 - github.com/libregraph/idm v0.3.1-0.20220222123017-f9d520ac1f11 + github.com/libregraph/idm v0.3.1-0.20220309072604-7a05922a056f github.com/libregraph/lico v0.53.1 github.com/mennanov/fieldmask-utils v0.5.0 github.com/mitchellh/mapstructure v1.4.3 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 - github.com/nats-io/nats-server/v2 v2.7.3 - github.com/nats-io/nats-streaming-server v0.24.2 + github.com/nats-io/nats-server/v2 v2.7.4 + github.com/nats-io/nats-streaming-server v0.24.3 github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 github.com/nmcclain/ldap v0.0.0-20210720162743-7f8d1e44eeba github.com/oklog/run v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.18.1 - github.com/owncloud/libre-graph-api-go v0.11.0 + github.com/owncloud/libre-graph-api-go v0.12.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.12.1 github.com/rs/zerolog v1.26.1 github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.3.0 + github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.0 github.com/thejerf/suture/v4 v4.0.2 github.com/urfave/cli/v2 v2.3.0 @@ -70,12 +70,12 @@ require ( go.opentelemetry.io/otel/exporters/jaeger v1.4.1 go.opentelemetry.io/otel/sdk v1.4.1 go.opentelemetry.io/otel/trace v1.4.1 - golang.org/x/crypto v0.0.0-20220214200702-86341886e292 + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 golang.org/x/image v0.0.0-20211028202545-6944b10bf410 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a - google.golang.org/grpc v1.44.0 + google.golang.org/grpc v1.45.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gotest.tools/v3 v3.1.0 @@ -171,7 +171,7 @@ require ( github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/raft v1.3.5 // indirect + github.com/hashicorp/raft v1.3.6 // indirect github.com/hashicorp/serf v0.9.6 // indirect github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect github.com/huandu/xstrings v1.3.2 // indirect @@ -209,7 +209,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 // indirect - github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d // indirect + github.com/nats-io/nats.go v1.13.1-0.20220308171302-2f2f6968e98d // indirect github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nats-io/stan.go v0.10.2 // indirect @@ -258,7 +258,7 @@ require ( go.uber.org/zap v1.19.1 // indirect golang.org/x/mod v0.5.1 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect + golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect golang.org/x/tools v0.1.8 // indirect diff --git a/go.sum b/go.sum index b4e77e94860..35a9710e615 100644 --- a/go.sum +++ b/go.sum @@ -826,8 +826,8 @@ github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/raft v1.3.1/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/raft v1.3.3/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.3.5 h1:93YBXmHWW2MuyMZfMxN1PsAnPXAt+hBfG0S0ZrZxRrY= -github.com/hashicorp/raft v1.3.5/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= +github.com/hashicorp/raft v1.3.6 h1:v5xW5KzByoerQlN/o31VJrFNiozgzGyDoMgDJgXpsto= +github.com/hashicorp/raft v1.3.6/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= @@ -939,8 +939,8 @@ github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libregraph/idm v0.3.1-0.20220222123017-f9d520ac1f11 h1:ReFrghRLQhQdt5BW7HXtEzySmsgUCXL1U36gnmka73U= -github.com/libregraph/idm v0.3.1-0.20220222123017-f9d520ac1f11/go.mod h1:wB8ApGAQsXDXXGWEeFimK/3q8Z/jRa+m3nqnvoYjBsQ= +github.com/libregraph/idm v0.3.1-0.20220309072604-7a05922a056f h1:FKa0JYnkhto9Z4UsQHdEM/bxRklqiICaOHhGN+s9cnI= +github.com/libregraph/idm v0.3.1-0.20220309072604-7a05922a056f/go.mod h1:wB8ApGAQsXDXXGWEeFimK/3q8Z/jRa+m3nqnvoYjBsQ= github.com/libregraph/lico v0.53.1 h1:c5JYFg0mrIgk6Ktj77rNJ2K8X01hs28JJ9Vw1N1iMAk= github.com/libregraph/lico v0.53.1/go.mod h1:EXf6Y9s9TygW6unSXosBpVXWUURoN2sPX0053o4zVfQ= github.com/linode/linodego v0.25.3/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE= @@ -1090,18 +1090,19 @@ github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnl github.com/nats-io/nats-server/v2 v2.6.2/go.mod h1:CNi6dJQ5H+vWqaoWKjCGtqBt7ai/xOTLiocUqhK6ews= github.com/nats-io/nats-server/v2 v2.6.4/go.mod h1:LlMieumxNUnCloOTVFv7Wog0YnasScxARUMXVXv9/+M= github.com/nats-io/nats-server/v2 v2.7.2/go.mod h1:tckmrt0M6bVaDT3kmh9UrIq/CBOBBse+TpXQi5ldaa8= -github.com/nats-io/nats-server/v2 v2.7.3 h1:P0NgsnbTxrPMMPZ1/rLXWjS5bbPpRMCcPwlMd4nBDK4= -github.com/nats-io/nats-server/v2 v2.7.3/go.mod h1:eJUrA5gm0ch6sJTEv85xmXIgQWsB0OyjkTsKXvlHbYc= +github.com/nats-io/nats-server/v2 v2.7.4 h1:c+BZJ3rGzUKCBIM4IXO8uNT2u1vajGbD1kPA6wqCEaM= +github.com/nats-io/nats-server/v2 v2.7.4/go.mod h1:1vZ2Nijh8tcyNe8BDVyTviCd9NYzRbubQYiEHsvOQWc= github.com/nats-io/nats-streaming-server v0.23.0/go.mod h1:1asNNRpUKbgwoPqRLEWbJE65uqmWjG1YN/Xlo3WgkTY= github.com/nats-io/nats-streaming-server v0.24.1/go.mod h1:N2Q05hKD+aW2Ur1VYP85yUR2zUWHbqJG88CxAFLRrd4= -github.com/nats-io/nats-streaming-server v0.24.2 h1:beQTSDcAm2Pe1uUZm2P3gVo/xbcgeZmnb5x3x/bMXRk= -github.com/nats-io/nats-streaming-server v0.24.2/go.mod h1:pFJ379pPvxtpnO5dtfypdbJUrjHp08LYqy+qNCFFAbw= +github.com/nats-io/nats-streaming-server v0.24.3 h1:uZez8jBkXscua++jaDsK7DhpSAkizdetar6yWbPMRco= +github.com/nats-io/nats-streaming-server v0.24.3/go.mod h1:rqWfyCbxlhKj//fAp8POdQzeADwqkVhZcoWlbhkuU5w= github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= github.com/nats-io/nats.go v1.11.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nats.go v1.13.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nats.go v1.13.1-0.20211018182449-f2416a8b1483/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d h1:GRSmEJutHkdoxKsRypP575IIdoXe7Bm6yHQF6GcDBnA= github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= +github.com/nats-io/nats.go v1.13.1-0.20220308171302-2f2f6968e98d h1:zJf4l8Kp67RIZhoVeniSLZs69SHNgjLHz0aNsqPPlx8= +github.com/nats-io/nats.go v1.13.1-0.20220308171302-2f2f6968e98d/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= @@ -1162,8 +1163,8 @@ github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:L github.com/orcaman/concurrent-map v1.0.0 h1:I/2A2XPCb4IuQWcQhBhSwGfiuybl/J0ev9HDbW65HOY= github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= -github.com/owncloud/libre-graph-api-go v0.11.0 h1:E260P0EJQvtdkUHYk/l2GeKoDxcbsazAqY9MnAQxUt8= -github.com/owncloud/libre-graph-api-go v0.11.0/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U= +github.com/owncloud/libre-graph-api-go v0.12.0 h1:2EzBEzs2r5wP3PYss2woNhTl/0/NZfMOzFe/bvtdsEU= +github.com/owncloud/libre-graph-api-go v0.12.0/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1345,8 +1346,9 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1570,8 +1572,8 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1842,8 +1844,8 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00= -golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 h1:8IVLkfbr2cLhv0a/vKq4UFUcJym8RmDoDboxCFWEjYE= +golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2112,8 +2114,9 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20210902184326-c93e472777b9/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU= From edf845225ad135236b5945939f34df2e799242ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Tue, 8 Mar 2022 15:01:01 +0100 Subject: [PATCH 40/42] Only add the service user to the index once (lazily) Adding and removing it again with each ListAccounts() call was a huge overhead. This is a temporary workaround, the whole service is gonna be replaced by the idm service soon anyway. --- accounts/pkg/service/v0/accounts.go | 29 ----------------------------- accounts/pkg/service/v0/service.go | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/accounts/pkg/service/v0/accounts.go b/accounts/pkg/service/v0/accounts.go index bd28223106e..7fab6a7d187 100644 --- a/accounts/pkg/service/v0/accounts.go +++ b/accounts/pkg/service/v0/accounts.go @@ -99,33 +99,6 @@ func (s Service) hasSelfManagementPermissions(ctx context.Context) bool { return s.RoleManager.FindPermissionByID(ctx, roleIDs, SelfManagementPermissionID) != nil } -// serviceUserToIndex temporarily adds a service user to the index, which is supposed to be removed before the lock on the handler function is released -func (s Service) serviceUserToIndex() (teardownServiceUser func()) { - if s.Config.ServiceUser.Username != "" && s.Config.ServiceUser.UUID != "" { - _, err := s.index.Add(s.getInMemoryServiceUser()) - if err != nil { - s.log.Logger.Err(err).Msg("service user was configured but failed to be added to the index") - } else { - return func() { - _ = s.index.Delete(s.getInMemoryServiceUser()) - } - } - } - return func() {} -} - -func (s Service) getInMemoryServiceUser() accountsmsg.Account { - return accountsmsg.Account{ - AccountEnabled: true, - Id: s.Config.ServiceUser.UUID, - PreferredName: s.Config.ServiceUser.Username, - OnPremisesSamAccountName: s.Config.ServiceUser.Username, - DisplayName: s.Config.ServiceUser.Username, - UidNumber: s.Config.ServiceUser.UID, - GidNumber: s.Config.ServiceUser.GID, - } -} - // ListAccounts implements the AccountsServiceHandler interface // the query contains account properties func (s Service) ListAccounts(ctx context.Context, in *accountssvc.ListAccountsRequest, out *accountssvc.ListAccountsResponse) (err error) { @@ -145,8 +118,6 @@ func (s Service) ListAccounts(ctx context.Context, in *accountssvc.ListAccountsR } onlySelf := hasSelf && !hasManagement - teardownServiceUser := s.serviceUserToIndex() - defer teardownServiceUser() match, authRequest := getAuthQueryMatch(in.Query) if authRequest { password := match[2] diff --git a/accounts/pkg/service/v0/service.go b/accounts/pkg/service/v0/service.go index f709b70f20b..7c19e26618e 100644 --- a/accounts/pkg/service/v0/service.go +++ b/accounts/pkg/service/v0/service.go @@ -86,9 +86,33 @@ func New(opts ...Option) (s *Service, err error) { if err = s.createDefaultGroups(cfg.DemoUsersAndGroups); err != nil { return nil, err } + + s.serviceUserToIndex() return } +// serviceUserToIndex temporarily adds a service user to the index, which is supposed to be removed before the lock on the handler function is released +func (s Service) serviceUserToIndex() { + if s.Config.ServiceUser.Username != "" && s.Config.ServiceUser.UUID != "" { + _, err := s.index.Add(s.getInMemoryServiceUser()) + if err != nil { + s.log.Logger.Err(err).Msg("service user was configured but failed to be added to the index") + } + } +} + +func (s Service) getInMemoryServiceUser() accountsmsg.Account { + return accountsmsg.Account{ + AccountEnabled: true, + Id: s.Config.ServiceUser.UUID, + PreferredName: s.Config.ServiceUser.Username, + OnPremisesSamAccountName: s.Config.ServiceUser.Username, + DisplayName: s.Config.ServiceUser.Username, + UidNumber: s.Config.ServiceUser.UID, + GidNumber: s.Config.ServiceUser.GID, + } +} + func (s Service) buildIndex() (*indexer.Indexer, error) { var indexcfg *idxcfg.Config From b7c934b1b1c295db44eaa984d1299e79208bd7bc Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 15 Mar 2022 10:15:43 +0100 Subject: [PATCH 41/42] use service user / hardcode idp Signed-off-by: jkoberg --- accounts/pkg/config/defaults/defaultconfig.go | 2 +- settings/pkg/config/config.go | 2 +- settings/pkg/config/defaults/defaultconfig.go | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/accounts/pkg/config/defaults/defaultconfig.go b/accounts/pkg/config/defaults/defaultconfig.go index bf62637ece3..9b404b65dae 100644 --- a/accounts/pkg/config/defaults/defaultconfig.go +++ b/accounts/pkg/config/defaults/defaultconfig.go @@ -71,7 +71,7 @@ func DefaultConfig() *config.Config { }, ServiceUser: config.ServiceUser{ UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Username: "", + Username: "service user", UID: 0, GID: 0, }, diff --git a/settings/pkg/config/config.go b/settings/pkg/config/config.go index fd63d84312d..4ee5d895d3a 100644 --- a/settings/pkg/config/config.go +++ b/settings/pkg/config/config.go @@ -40,6 +40,6 @@ type Metadata struct { StorageAddress string `ocisConfig:"storage_addr" env:"STORAGE_GRPC_ADDR"` ServiceUserID string `ocisConfig:"service_user_id" env:"METADATA_SERVICE_USER_UUID"` - ServiceUserIDP string `ocisConfig:"service_user_idp" env:"METADATA_SERVICE_USER_IDP"` + ServiceUserIDP string `ocisConfig:"service_user_idp" env:"OCIS_URL;METADATA_SERVICE_USER_IDP"` MachineAuthAPIKey string `ocisConfig:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` } diff --git a/settings/pkg/config/defaults/defaultconfig.go b/settings/pkg/config/defaults/defaultconfig.go index abb4bb2723a..f7b9ead4c4c 100644 --- a/settings/pkg/config/defaults/defaultconfig.go +++ b/settings/pkg/config/defaults/defaultconfig.go @@ -1,7 +1,6 @@ package defaults import ( - "os" "path" "strings" @@ -58,8 +57,8 @@ func DefaultConfig() *config.Config { Metadata: config.Metadata{ GatewayAddress: "127.0.0.1:9142", StorageAddress: "127.0.0.1:9215", - ServiceUserID: "ddc2004c-0977-11eb-9d3f-a793888cd0f8", - ServiceUserIDP: os.Getenv("OCIS_URL"), + ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + ServiceUserIDP: "https://localhost:9200", MachineAuthAPIKey: "change-me-please", }, } From d54f75df8b51e0503ddb34f4527128537bd805a7 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 15 Mar 2022 12:11:52 +0100 Subject: [PATCH 42/42] don't store service user data in metadataservice Signed-off-by: jkoberg --- accounts/pkg/config/defaults/defaultconfig.go | 2 +- settings/pkg/store/metadata/assignments.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/pkg/config/defaults/defaultconfig.go b/accounts/pkg/config/defaults/defaultconfig.go index 9b404b65dae..8e8a82266f3 100644 --- a/accounts/pkg/config/defaults/defaultconfig.go +++ b/accounts/pkg/config/defaults/defaultconfig.go @@ -71,7 +71,7 @@ func DefaultConfig() *config.Config { }, ServiceUser: config.ServiceUser{ UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Username: "service user", + Username: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", UID: 0, GID: 0, }, diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 7095ab69262..9f71ce0440c 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -13,7 +13,7 @@ import ( // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { - if s.mdc == nil { + if s.mdc == nil || accountUUID == "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad" { return defaultRoleAssignments(accountUUID), nil } s.Init()