mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-04-11 02:48:05 -04:00
settings: Remove deprecated filesystem backend
We changed the default to `metadata` before the 2.0 release. This PR alos removes the associated `SETTINGS_STORE_TYPE` and `SETTINGS_DATA_PATH` settings as they are no longer needed with `metadata` as the only available backend.
This commit is contained in:
committed by
Ralf Haferkamp
parent
4177f43cdb
commit
5b38fa149d
@@ -0,0 +1,6 @@
|
||||
Change: The `filesystem` backend for the settings service has been removed
|
||||
|
||||
The only remaining backend for the settings service is `metadata`, which has been the
|
||||
default backend since ocis 2.0
|
||||
|
||||
https://github.com/owncloud/ocis/pull/9138
|
||||
@@ -12,12 +12,7 @@ The settings service is currently used for managing the:
|
||||
|
||||
As an example, user profile settings that can be changed in the Web UI must be persistent.
|
||||
|
||||
The settings service supports two different backends for persisting the data. The backend can be set via the `SETTINGS_STORE_TYPE` environment variable. Supported values are:
|
||||
|
||||
* `metadata`: The default. This backend persists the settings data via the `storage-system` service.
|
||||
* `filesystem`: (deprecated) This backend persists the settings data in a directory on the local filesystem.
|
||||
The directory can be configured with `SETTINGS_DATA_PATH`. This backend is **not** suitable for running
|
||||
multiple intances of the `settings` service in a scale-out deployment and was therefore deprecated.
|
||||
The settings service persists the settings data via the `storage-system` service.
|
||||
|
||||
<!--- Note: The diagramm is outdate, leaving it here for a future rework
|
||||
The diagram shows how the settings service integrates into oCIS:
|
||||
@@ -37,7 +32,7 @@ graph TD
|
||||
|
||||
## Caching
|
||||
|
||||
When using `SETTINGS_STORE_TYPE=metadata`, the `settings` service caches the results of queries against the storage backend to provide faster responses. The content of this cache is independent of the cache used in the `storage-system` service as it caches directory listing and settings content stored in files.
|
||||
The `settings` service caches the results of queries against the storage backend to provide faster responses. The content of this cache is independent of the cache used in the `storage-system` service as it caches directory listing and settings content stored in files.
|
||||
|
||||
The store used for the cache can be configured using the `SETTINGS_CACHE_STORE` environment variable. Possible stores are:
|
||||
- `memory`: Basic in-memory store and the default.
|
||||
|
||||
@@ -25,8 +25,6 @@ type Config struct {
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GrpcClient client.Client `yaml:"-"`
|
||||
|
||||
StoreType string `yaml:"store_type" env:"SETTINGS_STORE_TYPE" desc:"Store type configures the persistency driver. Supported values are 'metadata' and 'filesystem'. Note that the value 'filesystem' is considered deprecated." introductionVersion:"pre5.0"`
|
||||
DataPath string `yaml:"data_path" env:"SETTINGS_DATA_PATH" desc:"The directory where the filesystem storage will store ocis settings. If not defined, the root directory derives from $OCIS_BASE_DATA_PATH:/settings." introductionVersion:"pre5.0"`
|
||||
Metadata Metadata `yaml:"metadata_config"`
|
||||
BundlesPath string `yaml:"bundles_path" env:"SETTINGS_BUNDLES_PATH" desc:"The path to a JSON file with a list of bundles. If not defined, the default bundles will be loaded." introductionVersion:"pre5.0"`
|
||||
Bundles []*settingsmsg.Bundle `yaml:"-"`
|
||||
|
||||
@@ -3,11 +3,9 @@ package defaults
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/defaults"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/structs"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/config"
|
||||
rdefaults "github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
|
||||
@@ -49,8 +47,6 @@ func DefaultConfig() *config.Config {
|
||||
Addr: "127.0.0.1:9191",
|
||||
Namespace: "com.owncloud.api",
|
||||
},
|
||||
StoreType: "metadata", // use metadata or filesystem
|
||||
DataPath: path.Join(defaults.BaseDataPath(), "settings"),
|
||||
SetupDefaultAssignments: false,
|
||||
Metadata: config.Metadata{
|
||||
GatewayAddress: "com.owncloud.api.storage-system",
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
|
||||
filestore "github.com/owncloud/ocis/v2/services/settings/pkg/store/filesystem"
|
||||
metastore "github.com/owncloud/ocis/v2/services/settings/pkg/store/metadata"
|
||||
merrors "go-micro.dev/v4/errors"
|
||||
"go-micro.dev/v4/metadata"
|
||||
@@ -40,17 +39,7 @@ func NewService(cfg *config.Config, logger log.Logger) settings.ServiceHandler {
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
switch cfg.StoreType {
|
||||
default:
|
||||
fallthrough
|
||||
case "metadata":
|
||||
service.manager = metastore.New(cfg)
|
||||
case "filesystem":
|
||||
fmt.Println("WARNING: filesystem store is deprecated and will be removed in the future. Please use metadata store instead.")
|
||||
service.manager = filestore.New(cfg)
|
||||
// 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()
|
||||
}
|
||||
service.manager = metastore.New(cfg)
|
||||
return service
|
||||
}
|
||||
|
||||
@@ -101,45 +90,6 @@ func (g Service) CheckPermission(ctx context.Context, req *cs3permissions.CheckP
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist.
|
||||
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, _ := g.manager.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)
|
||||
if err != nil {
|
||||
g.logger.Error().Err(err).Str("bundleID", bundleID).Msg("failed to register bundle")
|
||||
}
|
||||
g.logger.Debug().Str("bundleID", bundleID).Msg("successfully registered bundle")
|
||||
}
|
||||
|
||||
for _, req := range generatePermissionRequests() {
|
||||
_, err := g.manager.AddSettingToBundle(req.GetBundleId(), req.GetSetting())
|
||||
if err != nil {
|
||||
g.logger.Error().
|
||||
Err(err).
|
||||
Str("bundleID", req.GetBundleId()).
|
||||
Interface("setting", req.GetSetting()).
|
||||
Msg("failed to register permission")
|
||||
}
|
||||
}
|
||||
|
||||
if g.config.SetupDefaultAssignments {
|
||||
for _, req := range g.defaultRoleAssignments() {
|
||||
if _, err := g.manager.WriteRoleAssignment(req.AccountUuid, req.RoleId); err != nil {
|
||||
g.logger.Error().Err(err).Msg("failed to register role assignment")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check permissions on every request
|
||||
|
||||
// SaveBundle implements the BundleServiceHandler interface
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
)
|
||||
|
||||
const (
|
||||
// BundleUUIDRoleAdmin represents the admin role
|
||||
BundleUUIDRoleAdmin = "71881883-1768-46bd-a24d-a356a2afdf7f"
|
||||
@@ -64,567 +59,3 @@ const (
|
||||
// ChangeLogoPermissionName is the hardcoded setting name for the change-logo permission
|
||||
ChangeLogoPermissionName string = "change-logo"
|
||||
)
|
||||
|
||||
// generateBundlesDefaultRoles bootstraps the default roles.
|
||||
func generateBundlesDefaultRoles() []*settingsmsg.Bundle {
|
||||
return []*settingsmsg.Bundle{
|
||||
generateBundleAdminRole(),
|
||||
generateBundleSpaceAdminRole(),
|
||||
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{},
|
||||
}
|
||||
}
|
||||
|
||||
func generateBundleSpaceAdminRole() *settingsmsg.Bundle {
|
||||
return &settingsmsg.Bundle{
|
||||
Id: BundleUUIDRoleSpaceAdmin,
|
||||
Name: "spaceadmin",
|
||||
Type: settingsmsg.Bundle_TYPE_ROLE,
|
||||
Extension: "ocis-roles",
|
||||
DisplayName: "Space Admin",
|
||||
Resource: &settingsmsg.Resource{
|
||||
Type: settingsmsg.Resource_TYPE_SYSTEM,
|
||||
},
|
||||
Settings: []*settingsmsg.Setting{},
|
||||
}
|
||||
}
|
||||
|
||||
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{},
|
||||
}
|
||||
}
|
||||
|
||||
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{},
|
||||
}
|
||||
}
|
||||
|
||||
var languageSetting = settingsmsg.Setting_SingleChoiceValue{
|
||||
SingleChoiceValue: &settingsmsg.SingleChoiceList{
|
||||
Options: []*settingsmsg.ListOption{
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "bg",
|
||||
},
|
||||
},
|
||||
DisplayValue: "български",
|
||||
},
|
||||
{
|
||||
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",
|
||||
},
|
||||
{
|
||||
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",
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "nl",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Nederlands",
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "ko",
|
||||
},
|
||||
},
|
||||
DisplayValue: "한국어",
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "sq",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Shqipja",
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "sv",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Svenska",
|
||||
},
|
||||
{
|
||||
Value: &settingsmsg.ListOptionValue{
|
||||
Option: &settingsmsg.ListOptionValue_StringValue{
|
||||
StringValue: "tr",
|
||||
},
|
||||
},
|
||||
DisplayValue: "Türkçe",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest {
|
||||
return []*settingssvc.AddSettingToBundleRequest{
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleUser,
|
||||
Setting: &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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleGuest,
|
||||
Setting: &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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleUser,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: SetSpaceQuotaPermissionID,
|
||||
Name: SetSpaceQuotaPermissionName,
|
||||
DisplayName: "Set Space Quota",
|
||||
Description: "This permission allows managing 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleUser,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: CreateSpacePermissionID,
|
||||
Name: CreateSpacePermissionName,
|
||||
DisplayName: "Create own Space",
|
||||
Description: "This permission allows creating 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: CreateSpacePermissionID,
|
||||
Name: CreateSpacePermissionName,
|
||||
DisplayName: "Create Space",
|
||||
Description: "This permission allows creating 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: ChangeLogoPermissionID,
|
||||
Name: ChangeLogoPermissionName,
|
||||
DisplayName: "Change logo",
|
||||
Description: "This permission permits to change the system logo.",
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleSpaceAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: CreateSpacePermissionID,
|
||||
Name: CreateSpacePermissionName,
|
||||
DisplayName: "Create Space",
|
||||
Description: "This permission allows creating 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleSpaceAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
Id: SetSpaceQuotaPermissionID,
|
||||
Name: SetSpaceQuotaPermissionName,
|
||||
DisplayName: "Set Space Quota",
|
||||
Description: "This permission allows managing 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleSpaceAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleSpaceAdmin,
|
||||
Setting: &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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BundleId: BundleUUIDRoleSpaceAdmin,
|
||||
Setting: &settingsmsg.Setting{
|
||||
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 (g Service) defaultRoleAssignments() []*settingsmsg.UserRoleAssignment {
|
||||
return []*settingsmsg.UserRoleAssignment{
|
||||
// default admin users
|
||||
{
|
||||
AccountUuid: g.config.AdminUserID,
|
||||
RoleId: BundleUUIDRoleAdmin,
|
||||
},
|
||||
// default users with role "user"
|
||||
{
|
||||
AccountUuid: "4c510ada-c86b-4815-8820-42cdf82c3d51", // demo user "einstein"
|
||||
RoleId: BundleUUIDRoleUser,
|
||||
}, {
|
||||
AccountUuid: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", // demo user "marie"
|
||||
RoleId: BundleUUIDRoleUser,
|
||||
},
|
||||
// default users with role "spaceadmin"
|
||||
{
|
||||
AccountUuid: "058bff95-6708-4fe5-91e4-9ea3d377588b", // demo user "moss"
|
||||
RoleId: BundleUUIDRoleSpaceAdmin,
|
||||
}, {
|
||||
AccountUuid: "534bb038-6f9d-4093-946f-133be61fa4e7", // demo user "katherine"
|
||||
RoleId: BundleUUIDRoleSpaceAdmin,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// Package store implements the go-micro store interface
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/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) {
|
||||
var records []*settingsmsg.UserRoleAssignment
|
||||
assignmentsFolder := s.buildFolderPathForRoleAssignments(false)
|
||||
assignmentFiles, err := os.ReadDir(assignmentsFolder)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, assignmentFile := range assignmentFiles {
|
||||
record := settingsmsg.UserRoleAssignment{}
|
||||
err = s.parseRecordFromFile(&record, filepath.Join(assignmentsFolder, assignmentFile.Name()))
|
||||
if err == nil {
|
||||
if record.AccountUuid == accountUUID {
|
||||
records = append(records, &record)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return records, 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) {
|
||||
// as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role"
|
||||
list, err := s.ListRoleAssignments(accountUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(list) > 0 {
|
||||
filePath := s.buildFilePathForRoleAssignment(list[0].Id, true)
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
assignment := &settingsmsg.UserRoleAssignment{
|
||||
Id: uuid.Must(uuid.NewV4()).String(),
|
||||
AccountUuid: accountUUID,
|
||||
RoleId: roleID,
|
||||
}
|
||||
filePath := s.buildFilePathForRoleAssignment(assignment.Id, true)
|
||||
if err := s.writeRecordToFile(assignment, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Logger.Debug().Msgf("request contents written to file: %v", filePath)
|
||||
return assignment, nil
|
||||
}
|
||||
|
||||
// RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account.
|
||||
func (s Store) RemoveRoleAssignment(assignmentID string) error {
|
||||
filePath := s.buildFilePathForRoleAssignment(assignmentID, false)
|
||||
return os.Remove(filePath)
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/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{
|
||||
dataPath: dataRoot,
|
||||
Logger: logger,
|
||||
}
|
||||
|
||||
logger = olog.NewLogger(
|
||||
olog.Color(true),
|
||||
olog.Pretty(true),
|
||||
olog.Level("info"),
|
||||
)
|
||||
|
||||
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)
|
||||
assert.FileExists(t, filepath.Join(dataRoot, "assignments", firstAssignment.Id+".json"))
|
||||
|
||||
list, err := s.ListRoleAssignments(scenario.userID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(list))
|
||||
|
||||
// creating another assignment shouldn't add another entry, as we support max one role per user.
|
||||
secondAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.secondRole)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(list))
|
||||
|
||||
// assigning the second role should remove the old file and create a new one.
|
||||
list, err = s.ListRoleAssignments(scenario.userID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(list))
|
||||
assert.Equal(t, secondAssignment.RoleId, scenario.secondRole)
|
||||
assert.NoFileExists(t, filepath.Join(dataRoot, "assignments", firstAssignment.Id+".json"))
|
||||
assert.FileExists(t, filepath.Join(dataRoot, "assignments", secondAssignment.Id+".json"))
|
||||
})
|
||||
}
|
||||
burnRoot()
|
||||
}
|
||||
|
||||
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)
|
||||
assert.FileExists(t, filepath.Join(dataRoot, "assignments", assignment.Id+".json"))
|
||||
|
||||
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)
|
||||
|
||||
list, err = s.ListRoleAssignments(scenario.userID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(list))
|
||||
|
||||
err = s.RemoveRoleAssignment(assignment.Id)
|
||||
merr := &os.PathError{}
|
||||
assert.Equal(t, true, errors.As(err, &merr))
|
||||
})
|
||||
}
|
||||
burnRoot()
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
// Package store implements the go-micro store interface
|
||||
package store
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
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) {
|
||||
// FIXME: list requests should be ran against a cache, not FS
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
|
||||
bundlesFolder := s.buildFolderPathForBundles(false)
|
||||
bundleFiles, err := os.ReadDir(bundlesFolder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := make([]*settingsmsg.Bundle, 0, len(bundleFiles))
|
||||
for _, bundleFile := range bundleFiles {
|
||||
record := settingsmsg.Bundle{}
|
||||
err = s.parseRecordFromFile(&record, filepath.Join(bundlesFolder, bundleFile.Name()))
|
||||
if err != nil {
|
||||
s.Logger.Warn().Msgf("error reading %v", bundleFile)
|
||||
continue
|
||||
}
|
||||
if record.Type != bundleType {
|
||||
continue
|
||||
}
|
||||
if len(bundleIDs) > 0 && !containsStr(record.Id, bundleIDs) {
|
||||
continue
|
||||
}
|
||||
records = append(records, &record)
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
// containsStr checks if the strs slice contains str
|
||||
func containsStr(str string, strs []string) bool {
|
||||
for _, s := range strs {
|
||||
if s == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ReadBundle tries to find a bundle by the given id within the dataPath.
|
||||
func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
|
||||
filePath := s.buildFilePathForBundle(bundleID, false)
|
||||
record := settingsmsg.Bundle{}
|
||||
if err := s.parseRecordFromFile(&record, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Logger.Debug().Msgf("read contents from file: %v", filePath)
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
// ReadSetting tries to find a setting by the given id within the dataPath.
|
||||
func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
|
||||
bundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, bundle := range bundles {
|
||||
for _, setting := range bundle.Settings {
|
||||
if setting.Id == settingID {
|
||||
return setting, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("could not read setting: %v", settingID)
|
||||
}
|
||||
|
||||
// WriteBundle writes the given record into a file within the dataPath.
|
||||
func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) {
|
||||
// FIXME: locking should happen on the file here, not globally.
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
if record.Id == "" {
|
||||
record.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
filePath := s.buildFilePathForBundle(record.Id, true)
|
||||
if err := s.writeRecordToFile(record, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Logger.Debug().Msgf("request contents written to file: %v", filePath)
|
||||
return record, nil
|
||||
}
|
||||
|
||||
// AddSettingToBundle adds the given setting to the bundle with the given bundleID.
|
||||
func (s Store) AddSettingToBundle(bundleID string, setting *settingsmsg.Setting) (*settingsmsg.Setting, error) {
|
||||
bundle, err := s.ReadBundle(bundleID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, settings.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
bundle = new(settingsmsg.Bundle)
|
||||
bundle.Id = bundleID
|
||||
bundle.Type = settingsmsg.Bundle_TYPE_DEFAULT
|
||||
}
|
||||
if setting.Id == "" {
|
||||
setting.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
setSetting(bundle, setting)
|
||||
_, err = s.WriteBundle(bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return setting, nil
|
||||
}
|
||||
|
||||
// RemoveSettingFromBundle removes the setting from the bundle with the given ids.
|
||||
func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error {
|
||||
bundle, err := s.ReadBundle(bundleID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok := removeSetting(bundle, settingID); ok {
|
||||
if _, err := s.WriteBundle(bundle); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// indexOfSetting finds the index of the given setting within the given bundle.
|
||||
// returns -1 if the setting was not found.
|
||||
func indexOfSetting(bundle *settingsmsg.Bundle, settingID string) int {
|
||||
for index := range bundle.Settings {
|
||||
s := bundle.Settings[index]
|
||||
if s.Id == settingID {
|
||||
return index
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// setSetting will append or overwrite the given setting within the given bundle
|
||||
func setSetting(bundle *settingsmsg.Bundle, setting *settingsmsg.Setting) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
index := indexOfSetting(bundle, setting.Id)
|
||||
if index == -1 {
|
||||
bundle.Settings = append(bundle.Settings, setting)
|
||||
} else {
|
||||
bundle.Settings[index] = setting
|
||||
}
|
||||
}
|
||||
|
||||
// removeSetting will remove the given setting from the given bundle
|
||||
func removeSetting(bundle *settingsmsg.Bundle, settingID string) bool {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
index := indexOfSetting(bundle, settingID)
|
||||
if index == -1 {
|
||||
return false
|
||||
}
|
||||
bundle.Settings = append(bundle.Settings[:index], bundle.Settings[index+1:]...)
|
||||
return true
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/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) {
|
||||
s := Store{
|
||||
dataPath: dataRoot,
|
||||
Logger: olog.NewLogger(
|
||||
olog.Color(true),
|
||||
olog.Pretty(true),
|
||||
olog.Level("info"),
|
||||
),
|
||||
}
|
||||
|
||||
// write bundles
|
||||
for i := range bundleScenarios {
|
||||
index := i
|
||||
t.Run(bundleScenarios[index].name, func(t *testing.T) {
|
||||
filePath := s.buildFilePathForBundle(bundleScenarios[index].bundle.Id, true)
|
||||
if err := s.writeRecordToFile(bundleScenarios[index].bundle, filePath); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.FileExists(t, filePath)
|
||||
})
|
||||
}
|
||||
|
||||
// check that ListBundles only returns bundles with type DEFAULT
|
||||
bundles, err := s.ListBundles(settingsmsg.Bundle_TYPE_DEFAULT, []string{})
|
||||
if err != nil {
|
||||
t.Error(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})
|
||||
if err != nil {
|
||||
t.Error(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{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for i := range roles {
|
||||
assert.Equal(t, settingsmsg.Bundle_TYPE_ROLE, roles[i].Type)
|
||||
}
|
||||
|
||||
burnRoot()
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Unmarshal file into record
|
||||
func (s Store) parseRecordFromFile(record proto.Message, filePath string) error {
|
||||
_, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%q: %w", filePath, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
b, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return fmt.Errorf("%q: %w", filePath, settings.ErrNotFound)
|
||||
}
|
||||
|
||||
if err := protojson.Unmarshal(b, record); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal record into file
|
||||
func (s Store) writeRecordToFile(record proto.Message, filePath string) error {
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
v, err := protojson.Marshal(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = file.Write(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const folderNameBundles = "bundles"
|
||||
const folderNameValues = "values"
|
||||
const folderNameAssignments = "assignments"
|
||||
|
||||
// buildFolderPathForBundles builds the folder path for storing settings bundles. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFolderPathForBundles(mkdir bool) string {
|
||||
folderPath := filepath.Join(s.dataPath, folderNameBundles)
|
||||
if mkdir {
|
||||
s.ensureFolderExists(folderPath)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
// buildFilePathForBundle builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFilePathForBundle(bundleID string, mkdir bool) string {
|
||||
extensionFolder := s.buildFolderPathForBundles(mkdir)
|
||||
return filepath.Join(extensionFolder, bundleID+".json")
|
||||
}
|
||||
|
||||
// buildFolderPathForValues builds the folder path for storing settings values. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFolderPathForValues(mkdir bool) string {
|
||||
folderPath := filepath.Join(s.dataPath, folderNameValues)
|
||||
if mkdir {
|
||||
s.ensureFolderExists(folderPath)
|
||||
}
|
||||
return folderPath
|
||||
}
|
||||
|
||||
// buildFilePathForValue builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFilePathForValue(valueID string, mkdir bool) string {
|
||||
extensionFolder := s.buildFolderPathForValues(mkdir)
|
||||
return filepath.Join(extensionFolder, valueID+".json")
|
||||
}
|
||||
|
||||
// buildFolderPathForRoleAssignments builds the folder path for storing role assignments. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFolderPathForRoleAssignments(mkdir bool) string {
|
||||
roleAssignmentsFolder := filepath.Join(s.dataPath, folderNameAssignments)
|
||||
if mkdir {
|
||||
s.ensureFolderExists(roleAssignmentsFolder)
|
||||
}
|
||||
return roleAssignmentsFolder
|
||||
}
|
||||
|
||||
// buildFilePathForRoleAssignment builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
|
||||
func (s Store) buildFilePathForRoleAssignment(assignmentID string, mkdir bool) string {
|
||||
roleAssignmentsFolder := s.buildFolderPathForRoleAssignments(mkdir)
|
||||
return filepath.Join(roleAssignmentsFolder, assignmentID+".json")
|
||||
}
|
||||
|
||||
// ensureFolderExists checks if the given path is an existing folder and creates one if not existing
|
||||
func (s Store) ensureFolderExists(path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
err = os.MkdirAll(path, 0700)
|
||||
if err != nil {
|
||||
s.Logger.Err(err).Msgf("Error creating folder %v", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
"github.com/owncloud/ocis/v2/services/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) {
|
||||
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) {
|
||||
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) {
|
||||
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.ErrNotFound
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
checks = ["all", "-ST1003", "-ST1000", "-SA1019"]
|
||||
@@ -1,50 +0,0 @@
|
||||
// Package store implements the go-micro store interface
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
||||
)
|
||||
|
||||
var (
|
||||
// Name is the default name for the settings store
|
||||
Name = "ocis-settings"
|
||||
managerName = "filesystem"
|
||||
)
|
||||
|
||||
// Store interacts with the filesystem to manage settings information
|
||||
type Store struct {
|
||||
dataPath string
|
||||
Logger olog.Logger
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
s.dataPath = cfg.DataPath
|
||||
return &s
|
||||
}
|
||||
|
||||
func init() {
|
||||
settings.Registry[managerName] = New
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
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"
|
||||
|
||||
dataRoot = "/tmp/herecomesthesun"
|
||||
)
|
||||
|
||||
func burnRoot() {
|
||||
os.RemoveAll(filepath.Join(dataRoot, "values"))
|
||||
os.RemoveAll(filepath.Join(dataRoot, "bundles"))
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
// Package store implements the go-micro store interface
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/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) {
|
||||
valuesFolder := s.buildFolderPathForValues(false)
|
||||
valueFiles, err := os.ReadDir(valuesFolder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := make([]*settingsmsg.Value, 0, len(valueFiles))
|
||||
for _, valueFile := range valueFiles {
|
||||
record := settingsmsg.Value{}
|
||||
err := s.parseRecordFromFile(&record, filepath.Join(valuesFolder, valueFile.Name()))
|
||||
if err != nil {
|
||||
s.Logger.Warn().Msgf("error reading %v", valueFile)
|
||||
continue
|
||||
}
|
||||
if bundleID != "" && record.BundleId != bundleID {
|
||||
continue
|
||||
}
|
||||
// if requested accountUUID empty -> fetch all system level values
|
||||
if accountUUID == "" && record.AccountUuid != "" {
|
||||
continue
|
||||
}
|
||||
// if requested accountUUID empty -> fetch all individual + all system level values
|
||||
if accountUUID != "" && record.AccountUuid != "" && record.AccountUuid != accountUUID {
|
||||
continue
|
||||
}
|
||||
records = append(records, &record)
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
// ReadValue tries to find a value by the given valueId within the dataPath
|
||||
func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) {
|
||||
filePath := s.buildFilePathForValue(valueID, false)
|
||||
record := settingsmsg.Value{}
|
||||
if err := s.parseRecordFromFile(&record, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Logger.Debug().Msgf("read contents from file: %v", filePath)
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
// ReadValueByUniqueIdentifiers tries to find a value given a set of unique identifiers
|
||||
func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*settingsmsg.Value, error) {
|
||||
valuesFolder := s.buildFolderPathForValues(false)
|
||||
files, err := os.ReadDir(valuesFolder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range files {
|
||||
if !files[i].IsDir() {
|
||||
r := settingsmsg.Value{}
|
||||
s.Logger.Debug().Msgf("reading contents from file: %v", filepath.Join(valuesFolder, files[i].Name()))
|
||||
if err := s.parseRecordFromFile(&r, filepath.Join(valuesFolder, files[i].Name())); err != nil {
|
||||
s.Logger.Debug().Msgf("match found: %v", filepath.Join(valuesFolder, files[i].Name()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if value saved without accountUUID, then it's a global value
|
||||
if r.AccountUuid == "" && r.SettingId == settingID {
|
||||
return &r, nil
|
||||
}
|
||||
// if value saved with accountUUID, then it's a user specific value
|
||||
if r.AccountUuid == accountUUID && r.SettingId == settingID {
|
||||
return &r, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("could not read value by settingID=%v and accountID=%v", settingID, accountUUID)
|
||||
}
|
||||
|
||||
// WriteValue writes the given value into a file within the dataPath
|
||||
func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) {
|
||||
s.Logger.Debug().Str("value", value.String()).Msg("writing value")
|
||||
if value.Id == "" {
|
||||
value.Id = uuid.Must(uuid.NewV4()).String()
|
||||
}
|
||||
|
||||
// modify value depending on associated resource
|
||||
if value.Resource.Type == settingsmsg.Resource_TYPE_SYSTEM {
|
||||
value.AccountUuid = ""
|
||||
}
|
||||
|
||||
// write the value
|
||||
filePath := s.buildFilePathForValue(value.Id, true)
|
||||
if err := s.writeRecordToFile(value, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/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) {
|
||||
s := Store{
|
||||
dataPath: dataRoot,
|
||||
Logger: olog.NewLogger(
|
||||
olog.Color(true),
|
||||
olog.Pretty(true),
|
||||
olog.Level("info"),
|
||||
),
|
||||
}
|
||||
for i := range valueScenarios {
|
||||
index := i
|
||||
t.Run(valueScenarios[index].name, func(t *testing.T) {
|
||||
|
||||
filePath := s.buildFilePathForValue(valueScenarios[index].value.Id, true)
|
||||
if err := s.writeRecordToFile(valueScenarios[index].value, filePath); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.FileExists(t, filePath)
|
||||
})
|
||||
}
|
||||
|
||||
burnRoot()
|
||||
}
|
||||
@@ -2,6 +2,5 @@ package store
|
||||
|
||||
import (
|
||||
// init filesystem store
|
||||
_ "github.com/owncloud/ocis/v2/services/settings/pkg/store/filesystem"
|
||||
_ "github.com/owncloud/ocis/v2/services/settings/pkg/store/metadata"
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@ services:
|
||||
STORAGE_USERS_DRIVER_OCIS_ROOT: /srv/app/tmp/ocis/storage/users
|
||||
STORAGE_SYSTEM_DRIVER_OCIS_ROOT: /srv/app/tmp/ocis/storage/metadata
|
||||
SHARING_USER_JSON_FILE: /srv/app/tmp/ocis/shares.json
|
||||
SETTINGS_DATA_PATH: "/srv/app/tmp/ocis/settings"
|
||||
PROXY_ENABLE_BASIC_AUTH: "true"
|
||||
WEB_UI_CONFIG_FILE: /drone/src/tests/config/drone/ocis-config.json
|
||||
ACCOUNTS_HASH_DIFFICULTY: 4
|
||||
|
||||
Reference in New Issue
Block a user