diff --git a/changelog/unreleased/validate-config.md b/changelog/unreleased/validate-config.md new file mode 100644 index 0000000000..f4fbe1aa32 --- /dev/null +++ b/changelog/unreleased/validate-config.md @@ -0,0 +1,7 @@ +Enhancement: Enforce/validate configuration of services + +Every driver can now specify some validation rules on the +configuration. If the validation rules are not respected, +reva will bail out on startup with a clear error. + +https://github.com/cs3org/reva/pull/4035 diff --git a/cmd/revad/runtime/runtime.go b/cmd/revad/runtime/runtime.go index d895b122f1..b22afa0f2a 100644 --- a/cmd/revad/runtime/runtime.go +++ b/cmd/revad/runtime/runtime.go @@ -115,7 +115,7 @@ func New(config *config.Config, opt ...Option) (*Reva, error) { return nil, err } - serverless, err := newServerless(config, log) + serverless, err := newServerless(ctx, config, log) if err != nil { watcher.Clean() return nil, err @@ -144,7 +144,7 @@ func servicesAddresses(cfg *config.Config) map[string]grace.Addressable { return a } -func newServerless(config *config.Config, log *zerolog.Logger) (*rserverless.Serverless, error) { +func newServerless(ctx context.Context, config *config.Config, log *zerolog.Logger) (*rserverless.Serverless, error) { sl := make(map[string]rserverless.Service) logger := log.With().Str("pkg", "serverless").Logger() if err := config.Serverless.ForEach(func(name string, config map[string]any) error { @@ -153,7 +153,8 @@ func newServerless(config *config.Config, log *zerolog.Logger) (*rserverless.Ser return fmt.Errorf("serverless service %s does not exist", name) } log := logger.With().Str("service", name).Logger() - svc, err := new(config, &log) + ctx := appctx.WithLogger(ctx, &log) + svc, err := new(ctx, config) if err != nil { return errors.Wrapf(err, "serverless service %s could not be initialized", name) } diff --git a/go.mod b/go.mod index 59e7e61716..6e25780e1f 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,8 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/ceph/go-ceph v0.15.0 github.com/cheggaaa/pb v1.0.29 + github.com/coreos/go-oidc/v3 v3.5.0 + github.com/creasty/defaults v1.7.0 github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e github.com/cs3org/go-cs3apis v0.0.0-20230606135123-b799d47a6648 github.com/dgraph-io/ristretto v0.1.1 @@ -23,6 +25,8 @@ require ( github.com/glpatcern/go-mime v0.0.0-20221026162842-2a8d71ad17a9 github.com/go-chi/chi/v5 v5.0.8 github.com/go-ldap/ldap/v3 v3.4.4 + github.com/go-playground/locales v0.14.1 + github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.11.2 github.com/go-sql-driver/mysql v1.7.0 github.com/golang-jwt/jwt v3.2.2+incompatible @@ -76,12 +80,6 @@ require ( gotest.tools v2.2.0+incompatible ) -require ( - github.com/creasty/defaults v1.7.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect - github.com/hashicorp/go-msgpack/v2 v2.1.0 // indirect -) - require ( github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -92,13 +90,13 @@ require ( github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/coreos/go-oidc/v3 v3.5.0 github.com/davecgh/go-spew v1.1.1 // indirect github.com/dolthub/vitess v0.0.0-20221031111135-9aad77e7b39f // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-kit/kit v0.10.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect @@ -106,8 +104,6 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/errors v0.20.2 // indirect github.com/go-openapi/strfmt v0.21.2 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/gocraft/dbr/v2 v2.7.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -116,6 +112,7 @@ require ( github.com/google/flatbuffers v2.0.6+incompatible // indirect github.com/hashicorp/go-immutable-radix v1.0.0 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/raft v1.4.0 // indirect github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect diff --git a/go.sum b/go.sum index 5fa1a06c16..e3848a5c97 100644 --- a/go.sum +++ b/go.sum @@ -308,8 +308,6 @@ github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdB github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJffz4pz0o1WuQxJ28+5x5JgaHD8= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= -github.com/cs3org/go-cs3apis v0.0.0-20230508132523-e0d062e63b3b h1:UCO7Rnf5bvIvRtETguV8IaTx73cImLlFWxrApCB0QsQ= -github.com/cs3org/go-cs3apis v0.0.0-20230508132523-e0d062e63b3b/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20230606135123-b799d47a6648 h1:gBz1JSC2u6o/TkUhWSdJZvacyTsVUzDouegRzvrJye4= github.com/cs3org/go-cs3apis v0.0.0-20230606135123-b799d47a6648/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= diff --git a/internal/grpc/services/applicationauth/applicationauth.go b/internal/grpc/services/applicationauth/applicationauth.go index e05bd38a70..387a75904e 100644 --- a/internal/grpc/services/applicationauth/applicationauth.go +++ b/internal/grpc/services/applicationauth/applicationauth.go @@ -27,8 +27,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -46,7 +45,7 @@ type service struct { am appauth.Manager } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -63,30 +62,19 @@ func getAppAuthManager(ctx context.Context, c *config) (appauth.Manager, error) return nil, errtypes.NotFound("driver not found: " + c.Driver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a app auth provider svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - am, err := getAppAuthManager(ctx, c) + am, err := getAppAuthManager(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, am: am, } diff --git a/internal/grpc/services/appprovider/appprovider.go b/internal/grpc/services/appprovider/appprovider.go index 5b44681cad..53f5b89a27 100644 --- a/internal/grpc/services/appprovider/appprovider.go +++ b/internal/grpc/services/appprovider/appprovider.go @@ -40,8 +40,8 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/juliangruber/go-intersect" - "github.com/mitchellh/mapstructure" "google.golang.org/grpc" ) @@ -65,7 +65,7 @@ type config struct { Language string `mapstructure:"language"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "demo" } @@ -73,35 +73,25 @@ func (c *config) init() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - c.init() - return c, nil -} - // New creates a new AppProviderService. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } // read and register custom mime types if configured - err = registerMimeTypes(c.CustomMimeTypesJSON) - if err != nil { + if err := registerMimeTypes(c.CustomMimeTypesJSON); err != nil { return nil, err } - provider, err := getProvider(ctx, c) + provider, err := getProvider(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, provider: provider, } diff --git a/internal/grpc/services/appprovider/appprovider_test.go b/internal/grpc/services/appprovider/appprovider_test.go index e53468cbae..6ac998a65a 100644 --- a/internal/grpc/services/appprovider/appprovider_test.go +++ b/internal/grpc/services/appprovider/appprovider_test.go @@ -21,6 +21,7 @@ package appprovider import ( "testing" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/assert" ) @@ -80,9 +81,12 @@ func Test_parseConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := parseConfig(tt.m) + var got config + err := cfg.Decode(tt.m, &got) assert.Equal(t, tt.wantErr, err) - assert.Equal(t, tt.want, got) + if tt.wantErr == nil { + assert.Equal(t, tt.want, &got) + } }) } } diff --git a/internal/grpc/services/appregistry/appregistry.go b/internal/grpc/services/appregistry/appregistry.go index 0ba769ff94..0acea9c12f 100644 --- a/internal/grpc/services/appregistry/appregistry.go +++ b/internal/grpc/services/appregistry/appregistry.go @@ -27,7 +27,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -56,7 +56,7 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "static" } @@ -64,12 +64,12 @@ func (c *config) init() { // New creates a new StorageRegistryService. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - reg, err := getRegistry(ctx, c) + reg, err := getRegistry(ctx, &c) if err != nil { return nil, err } @@ -81,15 +81,6 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { return svc, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - c.init() - return c, nil -} - func getRegistry(ctx context.Context, c *config) (app.Registry, error) { if f, ok := registry.NewFuncs[c.Driver]; ok { return f(ctx, c.Drivers[c.Driver]) diff --git a/internal/grpc/services/authprovider/authprovider.go b/internal/grpc/services/authprovider/authprovider.go index 58765c4dad..71427f34cc 100644 --- a/internal/grpc/services/authprovider/authprovider.go +++ b/internal/grpc/services/authprovider/authprovider.go @@ -33,7 +33,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/user" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -48,7 +48,7 @@ type config struct { blockedUsers []string } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.AuthManager == "" { c.AuthManager = "json" } @@ -62,16 +62,6 @@ type service struct { blockedUsers user.BlockedUsers } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - func getAuthManager(ctx context.Context, manager string, m map[string]map[string]interface{}) (auth.Manager, *plugin.RevaPlugin, error) { if manager == "" { return nil, nil, errtypes.InternalError("authsvc: driver not configured for auth manager") @@ -101,8 +91,8 @@ func getAuthManager(ctx context.Context, manager string, m map[string]map[string // New returns a new AuthProviderServiceServer. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -112,7 +102,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { } svc := &service{ - conf: c, + conf: &c, authmgr: authManager, plugin: plug, blockedUsers: user.NewBlockedUsersSet(c.blockedUsers), diff --git a/internal/grpc/services/authregistry/authregistry.go b/internal/grpc/services/authregistry/authregistry.go index 267ea3b6b0..1e6969667f 100644 --- a/internal/grpc/services/authregistry/authregistry.go +++ b/internal/grpc/services/authregistry/authregistry.go @@ -27,7 +27,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -59,7 +59,7 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "static" } @@ -67,14 +67,12 @@ func (c *config) init() { // New creates a new AuthRegistry. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - reg, err := getRegistry(ctx, c) + reg, err := getRegistry(ctx, &c) if err != nil { return nil, err } @@ -86,14 +84,6 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { return service, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func getRegistry(ctx context.Context, c *config) (auth.Registry, error) { if f, ok := registry.NewFuncs[c.Driver]; ok { return f(ctx, c.Drivers[c.Driver]) diff --git a/internal/grpc/services/datatx/datatx.go b/internal/grpc/services/datatx/datatx.go index 98bf545b65..ef953d744d 100644 --- a/internal/grpc/services/datatx/datatx.go +++ b/internal/grpc/services/datatx/datatx.go @@ -30,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -54,7 +54,7 @@ type service struct { storageDriver txdriver.Repository } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.TxDriver == "" { c.TxDriver = "rclone" } @@ -78,35 +78,25 @@ func getStorageManager(ctx context.Context, c *config) (txdriver.Repository, err return nil, errtypes.NotFound("datatx service: driver not found: " + c.StorageDriver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "datatx service: error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new datatx svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - txManager, err := getDatatxManager(ctx, c) + txManager, err := getDatatxManager(ctx, &c) if err != nil { return nil, err } - storageDriver, err := getStorageManager(ctx, c) + storageDriver, err := getStorageManager(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, txManager: txManager, storageDriver: storageDriver, } diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index d766b00c5e..a85d18fdf1 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -32,8 +32,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -75,7 +74,7 @@ type config struct { } // sets defaults. -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.ShareFolder == "" { c.ShareFolder = "MyShares" } @@ -126,13 +125,11 @@ type svc struct { // The gateway is responsible for high-level controls: rate-limiting, coordination between svcs // like sharing and storage acls, asynchronous transactions, ... func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - // ensure DataGatewayEndpoint is a valid URI u, err := url.Parse(c.DataGatewayEndpoint) if err != nil { @@ -153,7 +150,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { createHomeCache.SkipTTLExtensionOnHit(true) s := &svc{ - c: c, + c: &c, dataGatewayURL: *u, tokenmgr: tokenManager, etagCache: etagCache, @@ -176,15 +173,6 @@ func (s *svc) UnprotectedEndpoints() []string { return []string{"/cs3.gateway.v1beta1.GatewayAPI"} } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "gateway: error decoding conf") - return nil, err - } - return c, nil -} - func getTokenManager(manager string, m map[string]map[string]interface{}) (token.Manager, error) { if f, ok := registry.NewFuncs[manager]; ok { return f(m[manager]) diff --git a/internal/grpc/services/groupprovider/groupprovider.go b/internal/grpc/services/groupprovider/groupprovider.go index b72704b95c..7ab63af7bc 100644 --- a/internal/grpc/services/groupprovider/groupprovider.go +++ b/internal/grpc/services/groupprovider/groupprovider.go @@ -29,7 +29,7 @@ import ( "github.com/cs3org/reva/pkg/group/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -43,22 +43,12 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - func getDriver(ctx context.Context, c *config) (group.Manager, error) { if f, ok := registry.NewFuncs[c.Driver]; ok { return f(ctx, c.Drivers[c.Driver]) @@ -69,12 +59,12 @@ func getDriver(ctx context.Context, c *config) (group.Manager, error) { // New returns a new GroupProviderServiceServer. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - groupManager, err := getDriver(ctx, c) + groupManager, err := getDriver(ctx, &c) if err != nil { return nil, err } diff --git a/internal/grpc/services/helloworld/helloworld.go b/internal/grpc/services/helloworld/helloworld.go index 3249457f59..8d4eab0566 100644 --- a/internal/grpc/services/helloworld/helloworld.go +++ b/internal/grpc/services/helloworld/helloworld.go @@ -24,8 +24,7 @@ import ( "github.com/cs3org/reva/internal/grpc/services/helloworld/proto" "github.com/cs3org/reva/pkg/rgrpc" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -40,20 +39,21 @@ type service struct { conf *conf } +func (c *conf) ApplyDefaults() { + if c.Message == "" { + c.Message = "Hello" + } +} + // New returns a new PreferencesServiceServer // It can be tested like this: // prototool grpc --address 0.0.0.0:9999 --method 'revad.helloworld.HelloWorldService/Hello' --data '{"name": "Alice"}'. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c := &conf{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "helloworld: error decoding conf") + var c conf + if err := cfg.Decode(m, &c); err != nil { return nil, err } - - if c.Message == "" { - c.Message = "Hello" - } - service := &service{conf: c} + service := &service{conf: &c} return service, nil } diff --git a/internal/grpc/services/ocmcore/ocmcore.go b/internal/grpc/services/ocmcore/ocmcore.go index c9f8dfe71b..54bf50c616 100644 --- a/internal/grpc/services/ocmcore/ocmcore.go +++ b/internal/grpc/services/ocmcore/ocmcore.go @@ -32,8 +32,7 @@ import ( "github.com/cs3org/reva/pkg/ocm/share/repository/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -51,7 +50,7 @@ type service struct { repo share.Repository } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -68,30 +67,20 @@ func getShareRepository(ctx context.Context, c *config) (share.Repository, error return nil, errtypes.NotFound(fmt.Sprintf("driver not found: %s", c.Driver)) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new ocm core svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - repo, err := getShareRepository(ctx, c) + repo, err := getShareRepository(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, repo: repo, } diff --git a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go index e4a3989cbe..7906a38bc3 100644 --- a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go +++ b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go @@ -36,7 +36,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -51,8 +51,8 @@ type config struct { TokenExpiration string `mapstructure:"token_expiration"` OCMClientTimeout int `mapstructure:"ocm_timeout"` OCMClientInsecure bool `mapstructure:"ocm_insecure"` - GatewaySVC string `mapstructure:"gateway_svc"` - ProviderDomain string `mapstructure:"provider_domain" docs:"The same domain registered in the provider authorizer"` + GatewaySVC string `mapstructure:"gatewaysvc" validate:"required"` + ProviderDomain string `mapstructure:"provider_domain" validate:"required" docs:"The same domain registered in the provider authorizer"` tokenExpiration time.Duration } @@ -63,7 +63,7 @@ type service struct { ocmClient *client.OCMClient } -func (c *config) init() error { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -71,15 +71,7 @@ func (c *config) init() error { c.TokenExpiration = "24h" } - p, err := time.ParseDuration(c.TokenExpiration) - if err != nil { - return err - } - c.tokenExpiration = p - c.GatewaySVC = sharedconf.GetGatewaySVC(c.GatewaySVC) - - return nil } func (s *service) Register(ss *grpc.Server) { @@ -93,32 +85,26 @@ func getInviteRepository(ctx context.Context, c *config) (invite.Repository, err return nil, errtypes.NotFound("driver not found: " + c.Driver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new OCM invite manager svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - if err := c.init(); err != nil { + + p, err := time.ParseDuration(c.TokenExpiration) + if err != nil { return nil, err } + c.tokenExpiration = p - repo, err := getInviteRepository(ctx, c) + repo, err := getInviteRepository(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, repo: repo, ocmClient: client.New(&client.Config{ Timeout: time.Duration(c.OCMClientTimeout) * time.Second, diff --git a/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go b/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go index fe26f8ebe1..18e436bee6 100644 --- a/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go +++ b/internal/grpc/services/ocmproviderauthorizer/ocmproviderauthorizer.go @@ -28,8 +28,7 @@ import ( "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -47,7 +46,7 @@ type service struct { pa provider.Authorizer } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -64,30 +63,20 @@ func getProviderAuthorizer(ctx context.Context, c *config) (provider.Authorizer, return nil, errtypes.NotFound("driver not found: " + c.Driver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new OCM provider authorizer svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - pa, err := getProviderAuthorizer(ctx, c) + pa, err := getProviderAuthorizer(ctx, &c) if err != nil { return nil, err } service := &service{ - conf: c, + conf: &c, pa: pa, } return service, nil diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index 6bd9f73011..acdc56f9c5 100644 --- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -46,7 +46,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/walker" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -60,9 +60,9 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` ClientTimeout int `mapstructure:"client_timeout"` ClientInsecure bool `mapstructure:"client_insecure"` - GatewaySVC string `mapstructure:"gatewaysvc"` - ProviderDomain string `mapstructure:"provider_domain" docs:"The same domain registered in the provider authorizer"` - WebDAVEndpoint string `mapstructure:"webdav_endpoint"` + GatewaySVC string `mapstructure:"gatewaysvc" validate:"required"` + ProviderDomain string `mapstructure:"provider_domain" validate:"required" docs:"The same domain registered in the provider authorizer"` + WebDAVEndpoint string `mapstructure:"webdav_endpoint" validate:"required"` WebappTemplate string `mapstructure:"webapp_template"` } @@ -75,7 +75,7 @@ type service struct { walker walker.Walker } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -100,24 +100,14 @@ func getShareRepository(ctx context.Context, c *config) (share.Repository, error return nil, errtypes.NotFound("driver not found: " + c.Driver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new ocm share provider svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - repo, err := getShareRepository(ctx, c) + repo, err := getShareRepository(ctx, &c) if err != nil { return nil, err } @@ -139,7 +129,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { walker := walker.NewWalker(gateway) service := &service{ - conf: c, + conf: &c, repo: repo, client: client, gateway: gateway, diff --git a/internal/grpc/services/permissions/permissions.go b/internal/grpc/services/permissions/permissions.go index cc1b75786b..eec9c7e22f 100644 --- a/internal/grpc/services/permissions/permissions.go +++ b/internal/grpc/services/permissions/permissions.go @@ -27,8 +27,7 @@ import ( "github.com/cs3org/reva/pkg/permission" "github.com/cs3org/reva/pkg/permission/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -41,23 +40,14 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers" docs:"url:pkg/permission/permission.go"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - type service struct { manager permission.Manager } // New returns a new PermissionsServiceServer. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } diff --git a/internal/grpc/services/preferences/preferences.go b/internal/grpc/services/preferences/preferences.go index b5e0003241..b45c6afbca 100644 --- a/internal/grpc/services/preferences/preferences.go +++ b/internal/grpc/services/preferences/preferences.go @@ -27,8 +27,7 @@ import ( "github.com/cs3org/reva/pkg/preferences/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -41,7 +40,7 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "memory" } @@ -59,31 +58,20 @@ func getPreferencesManager(ctx context.Context, c *config) (preferences.Manager, return nil, errtypes.NotFound("driver not found: " + c.Driver) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns a new PreferencesServiceServer. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - pm, err := getPreferencesManager(ctx, c) + pm, err := getPreferencesManager(ctx, &c) if err != nil { return nil, err } return &service{ - conf: c, + conf: &c, pm: pm, }, nil } diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index b30f6653c6..91ce7a0547 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -31,8 +31,7 @@ import ( "github.com/cs3org/reva/pkg/publicshare/manager/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -46,7 +45,7 @@ type config struct { AllowedPathsForShares []string `mapstructure:"allowed_paths_for_shares"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -69,6 +68,7 @@ func getShareManager(ctx context.Context, c *config) (publicshare.Manager, error func (s *service) Close() error { return nil } + func (s *service) UnprotectedEndpoints() []string { return []string{"/cs3.sharing.link.v1beta1.LinkAPI/GetPublicShareByToken"} } @@ -77,25 +77,14 @@ func (s *service) Register(ss *grpc.Server) { link.RegisterLinkAPIServer(ss, s) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new user share provider svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - sm, err := getShareManager(ctx, c) + sm, err := getShareManager(ctx, &c) if err != nil { return nil, err } @@ -110,7 +99,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { } service := &service{ - conf: c, + conf: &c, sm: sm, allowedPathsForShares: allowedPathsForShares, } diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 85e541fc02..48b7eba838 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -36,7 +36,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" @@ -73,19 +73,10 @@ func (s *service) Register(ss *grpc.Server) { provider.RegisterProviderAPIServer(ss, s) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new IsPublic Storage Provider service. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -98,7 +89,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { } service := &service{ - conf: c, + conf: &c, mountPath: mountPath, mountID: mountID, gateway: gateway, diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index da0f826d91..0ef056cc53 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -42,8 +42,8 @@ import ( "github.com/cs3org/reva/pkg/storage/fs/registry" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/google/uuid" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" @@ -66,7 +66,7 @@ type config struct { MinimunAllowedPathLevelForShare int `mapstructure:"minimum_allowed_path_level_for_share"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "localhome" } @@ -133,15 +133,6 @@ func parseXSTypes(xsTypes map[string]uint32) ([]*provider.ResourceChecksumPriori return types, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - func registerMimeTypes(mappingFile string) error { if mappingFile != "" { f, err := os.ReadFile(mappingFile) @@ -163,13 +154,11 @@ func registerMimeTypes(mappingFile string) error { // New creates a new storage provider svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - if err := os.MkdirAll(c.TmpFolder, 0755); err != nil { return nil, err } @@ -177,7 +166,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { mountPath := c.MountPath mountID := c.MountID - fs, err := getFS(ctx, c) + fs, err := getFS(ctx, &c) if err != nil { return nil, err } @@ -205,7 +194,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { } service := &service{ - conf: c, + conf: &c, storage: fs, tmpFolder: c.TmpFolder, mountPath: mountPath, diff --git a/internal/grpc/services/storageregistry/storageregistry.go b/internal/grpc/services/storageregistry/storageregistry.go index 391347670b..e3a4ac3454 100644 --- a/internal/grpc/services/storageregistry/storageregistry.go +++ b/internal/grpc/services/storageregistry/storageregistry.go @@ -28,7 +28,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/registry/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -57,7 +57,7 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "static" } @@ -65,14 +65,12 @@ func (c *config) init() { // New creates a new StorageBrokerService. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - reg, err := getRegistry(ctx, c) + reg, err := getRegistry(ctx, &c) if err != nil { return nil, err } @@ -84,14 +82,6 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { return service, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func getRegistry(ctx context.Context, c *config) (storage.Registry, error) { if f, ok := registry.NewFuncs[c.Driver]; ok { return f(ctx, c.Drivers[c.Driver]) diff --git a/internal/grpc/services/userprovider/userprovider.go b/internal/grpc/services/userprovider/userprovider.go index a8a7ae774a..d34ef48318 100644 --- a/internal/grpc/services/userprovider/userprovider.go +++ b/internal/grpc/services/userprovider/userprovider.go @@ -31,7 +31,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc" ) @@ -45,22 +45,12 @@ type config struct { Drivers map[string]map[string]interface{} `mapstructure:"drivers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - func getDriver(ctx context.Context, c *config) (user.Manager, *plugin.RevaPlugin, error) { p, err := plugin.Load("userprovider", c.Driver) if err == nil { @@ -88,11 +78,11 @@ func getDriver(ctx context.Context, c *config) (user.Manager, *plugin.RevaPlugin // New returns a new UserProviderServiceServer. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - userManager, plug, err := getDriver(ctx, c) + userManager, plug, err := getDriver(ctx, &c) if err != nil { return nil, err } diff --git a/internal/grpc/services/usershareprovider/usershareprovider.go b/internal/grpc/services/usershareprovider/usershareprovider.go index 81965b3db3..8d37af562b 100644 --- a/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/internal/grpc/services/usershareprovider/usershareprovider.go @@ -32,8 +32,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "google.golang.org/grpc" ) @@ -47,7 +46,7 @@ type config struct { AllowedPathsForShares []string `mapstructure:"allowed_paths_for_shares"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Driver == "" { c.Driver = "json" } @@ -79,25 +78,14 @@ func (s *service) Register(ss *grpc.Server) { collaboration.RegisterCollaborationAPIServer(ss, s) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New creates a new user share provider svc. func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - - sm, err := getShareManager(ctx, c) + sm, err := getShareManager(ctx, &c) if err != nil { return nil, err } @@ -112,7 +100,7 @@ func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { } service := &service{ - conf: c, + conf: &c, sm: sm, allowedPathsForShares: allowedPathsForShares, } diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index 4dc81ff8ab..049b8e83a3 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -36,10 +36,10 @@ import ( "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/go-chi/chi/v5" ua "github.com/mileusna/useragent" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -50,11 +50,11 @@ func init() { // Config holds the config options for the HTTP appprovider service. type Config struct { Prefix string `mapstructure:"prefix"` - GatewaySvc string `mapstructure:"gatewaysvc"` + GatewaySvc string `mapstructure:"gatewaysvc" validate:"required"` Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` } -func (c *Config) init() { +func (c *Config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "app" } @@ -68,15 +68,14 @@ type svc struct { // New returns a new ocmd object. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &Config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() r := chi.NewRouter() s := &svc{ - conf: conf, + conf: &c, router: r, } diff --git a/internal/http/services/archiver/handler.go b/internal/http/services/archiver/handler.go index 07c63b6a44..4ca94eb230 100644 --- a/internal/http/services/archiver/handler.go +++ b/internal/http/services/archiver/handler.go @@ -38,10 +38,10 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/downloader" "github.com/cs3org/reva/pkg/storage/utils/walker" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/gdexlab/go-render/render" ua "github.com/mileusna/useragent" - "github.com/mitchellh/mapstructure" ) type svc struct { @@ -56,12 +56,12 @@ type svc struct { // Config holds the config options that need to be passed down to all ocdav handlers. type Config struct { Prefix string `mapstructure:"prefix"` - GatewaySvc string `mapstructure:"gatewaysvc"` + GatewaySvc string `mapstructure:"gatewaysvc" validate:"required"` Timeout int64 `mapstructure:"timeout"` Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` Name string `mapstructure:"name"` - MaxNumFiles int64 `mapstructure:"max_num_files"` - MaxSize int64 `mapstructure:"max_size"` + MaxNumFiles int64 `mapstructure:"max_num_files" validate:"required,gt=0"` + MaxSize int64 `mapstructure:"max_size" validate:"required,gt=0"` AllowedFolders []string `mapstructure:"allowed_folders"` } @@ -71,14 +71,11 @@ func init() { // New creates a new archiver service. func New(ctx context.Context, conf map[string]interface{}) (global.Service, error) { - c := &Config{} - err := mapstructure.Decode(conf, c) - if err != nil { + var c Config + if err := cfg.Decode(conf, &c); err != nil { return nil, err } - c.init() - gtw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySvc)) if err != nil { return nil, err @@ -95,7 +92,7 @@ func New(ctx context.Context, conf map[string]interface{}) (global.Service, erro } return &svc{ - config: c, + config: &c, gtwClient: gtw, downloader: downloader.NewDownloader(gtw, rhttp.Insecure(c.Insecure), rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second)))), walker: walker.NewWalker(gtw), @@ -103,7 +100,7 @@ func New(ctx context.Context, conf map[string]interface{}) (global.Service, erro }, nil } -func (c *Config) init() { +func (c *Config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "download_archive" } diff --git a/internal/http/services/datagateway/datagateway.go b/internal/http/services/datagateway/datagateway.go index 9795b5cee5..e1b80d8b21 100644 --- a/internal/http/services/datagateway/datagateway.go +++ b/internal/http/services/datagateway/datagateway.go @@ -32,8 +32,8 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/golang-jwt/jwt" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -56,12 +56,12 @@ type transferClaims struct { } type config struct { Prefix string `mapstructure:"prefix"` - TransferSharedSecret string `mapstructure:"transfer_shared_secret"` + TransferSharedSecret string `mapstructure:"transfer_shared_secret" validate:"required"` Timeout int64 `mapstructure:"timeout"` Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "datagateway" } @@ -77,18 +77,16 @@ type svc struct { // New returns a new datagateway. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - s := &svc{ - conf: conf, + conf: &c, client: rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(conf.Timeout*int64(time.Second))), - rhttp.Insecure(conf.Insecure), + rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), + rhttp.Insecure(c.Insecure), ), } s.setHandler() diff --git a/internal/http/services/dataprovider/dataprovider.go b/internal/http/services/dataprovider/dataprovider.go index df35db7fa6..997abc0c9d 100644 --- a/internal/http/services/dataprovider/dataprovider.go +++ b/internal/http/services/dataprovider/dataprovider.go @@ -29,7 +29,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -45,7 +45,7 @@ type config struct { Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "data" } @@ -63,26 +63,24 @@ type svc struct { // New returns a new datasvc. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - - fs, err := getFS(ctx, conf) + fs, err := getFS(ctx, &c) if err != nil { return nil, err } - dataTXs, err := getDataTXs(ctx, conf, fs) + dataTXs, err := getDataTXs(ctx, &c, fs) if err != nil { return nil, err } s := &svc{ storage: fs, - conf: conf, + conf: &c, dataTXs: dataTXs, } diff --git a/internal/http/services/helloworld/helloworld.go b/internal/http/services/helloworld/helloworld.go index c136aeb6a8..11f0b65105 100644 --- a/internal/http/services/helloworld/helloworld.go +++ b/internal/http/services/helloworld/helloworld.go @@ -24,7 +24,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -33,14 +33,12 @@ func init() { // New returns a new helloworld service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - - return &svc{conf: conf}, nil + return &svc{conf: &c}, nil } // Close performs cleanup. @@ -53,7 +51,7 @@ type config struct { HelloMessage string `mapstructure:"message"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.HelloMessage == "" { c.HelloMessage = "Hello World!" } diff --git a/internal/http/services/mentix/mentix.go b/internal/http/services/mentix/mentix.go index f7c8a78845..be9eebbd67 100644 --- a/internal/http/services/mentix/mentix.go +++ b/internal/http/services/mentix/mentix.go @@ -28,7 +28,7 @@ import ( "github.com/cs3org/reva/pkg/mentix/exchangers" "github.com/cs3org/reva/pkg/mentix/meshdata" "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "github.com/rs/zerolog" ) @@ -97,16 +97,6 @@ func (s *svc) startBackgroundService() { }() } -func parseConfig(m map[string]interface{}) (*config.Configuration, error) { - cfg := &config.Configuration{} - if err := mapstructure.Decode(m, &cfg); err != nil { - return nil, errors.Wrap(err, "mentix: error decoding configuration") - } - applyInternalConfig(m, cfg) - applyDefaultConfig(cfg) - return cfg, nil -} - func applyInternalConfig(m map[string]interface{}, conf *config.Configuration) { getSubsections := func(section string) []string { subsections := make([]string, 0, 5) @@ -169,24 +159,23 @@ func applyDefaultConfig(conf *config.Configuration) { // New returns a new Mentix service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - // Prepare the configuration - conf, err := parseConfig(m) - if err != nil { + var c config.Configuration + if err := cfg.Decode(m, &c); err != nil { return nil, err } - - conf.Init() + applyInternalConfig(m, &c) + applyDefaultConfig(&c) // Create the Mentix instance log := appctx.GetLogger(ctx) - mntx, err := mentix.New(conf, log) + mntx, err := mentix.New(&c, log) if err != nil { return nil, errors.Wrap(err, "mentix: error creating Mentix") } // Create the service and start its background activity s := &svc{ - conf: conf, + conf: &c, mntx: mntx, log: log, stopSignal: make(chan struct{}), diff --git a/internal/http/services/metrics/metrics.go b/internal/http/services/metrics/metrics.go index fb02a01bf7..fe9db0128c 100644 --- a/internal/http/services/metrics/metrics.go +++ b/internal/http/services/metrics/metrics.go @@ -30,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/metrics" "github.com/cs3org/reva/pkg/metrics/config" "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -70,16 +70,13 @@ func (s *svc) Handler() http.Handler { // New returns a new metrics service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - // Prepare the configuration - conf := &config.Config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.Init() - // initialize metrics using the configuration - err := metrics.Init(conf) + err := metrics.Init(&c) if err != nil { return nil, err } diff --git a/internal/http/services/ocmd/ocm.go b/internal/http/services/ocmd/ocm.go index 4570178aef..13c901539a 100644 --- a/internal/http/services/ocmd/ocm.go +++ b/internal/http/services/ocmd/ocm.go @@ -25,8 +25,8 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" - "github.com/mitchellh/mapstructure" ) func init() { @@ -35,11 +35,11 @@ func init() { type config struct { Prefix string `mapstructure:"prefix"` - GatewaySvc string `mapstructure:"gatewaysvc"` + GatewaySvc string `mapstructure:"gatewaysvc" validate:"required"` ExposeRecipientDisplayName bool `mapstructure:"expose_recipient_display_name"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) if c.Prefix == "" { c.Prefix = "ocm" @@ -54,15 +54,14 @@ type svc struct { // New returns a new ocmd object, that implements // the OCM APIs specified in https://cs3org.github.io/OCM-API/docs.html func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() r := chi.NewRouter() s := &svc{ - Conf: conf, + Conf: &c, router: r, } diff --git a/internal/http/services/ocmprovider/ocmprovider.go b/internal/http/services/ocmprovider/ocmprovider.go index f2f7afb71e..dfb0c616d4 100644 --- a/internal/http/services/ocmprovider/ocmprovider.go +++ b/internal/http/services/ocmprovider/ocmprovider.go @@ -26,7 +26,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -62,7 +62,7 @@ type svc struct { data *discoveryData } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.OCMPrefix == "" { c.OCMPrefix = "ocm" } @@ -126,13 +126,11 @@ func (c *config) prepare() *discoveryData { // the OCM discovery endpoint specified in // https://cs3org.github.io/OCM-API/docs.html?repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - - conf.init() - return &svc{data: conf.prepare()}, nil + return &svc{data: c.prepare()}, nil } // Close performs cleanup. diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 6374a6a29a..0e93d56737 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -42,7 +42,7 @@ import ( "github.com/cs3org/reva/pkg/storage/favorite" "github.com/cs3org/reva/pkg/storage/favorite/registry" "github.com/cs3org/reva/pkg/storage/utils/templates" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -114,7 +114,7 @@ type Config struct { Notifications map[string]interface{} `mapstructure:"notifications" docs:"Settingsg for the Notification Helper"` } -func (c *Config) init() { +func (c *Config) ApplyDefaults() { // note: default c.Prefix is an empty string c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) @@ -145,36 +145,34 @@ func getFavoritesManager(c *Config) (favorite.Manager, error) { // New returns a new ocdav. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &Config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - - fm, err := getFavoritesManager(conf) + fm, err := getFavoritesManager(&c) if err != nil { return nil, err } log := appctx.GetLogger(ctx) s := &svc{ - c: conf, + c: &c, webDavHandler: new(WebDavHandler), davHandler: new(DavHandler), client: rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(conf.Timeout*int64(time.Second))), - rhttp.Insecure(conf.Insecure), + rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), + rhttp.Insecure(c.Insecure), ), favoritesManager: fm, - notificationHelper: notificationhelper.New("ocdav", conf.Notifications, log), + notificationHelper: notificationhelper.New("ocdav", c.Notifications, log), } - // initialize handlers and set default configs - if err := s.webDavHandler.init(conf.WebdavNamespace, true); err != nil { + // initialize handlers and set default cigs + if err := s.webDavHandler.init(c.WebdavNamespace, true); err != nil { return nil, err } - if err := s.davHandler.init(conf); err != nil { + if err := s.davHandler.init(&c); err != nil { return nil, err } return s, nil diff --git a/internal/http/services/owncloud/ocs/config/config.go b/internal/http/services/owncloud/ocs/config/config.go index 123cdd47be..a9ae7ac513 100644 --- a/internal/http/services/owncloud/ocs/config/config.go +++ b/internal/http/services/owncloud/ocs/config/config.go @@ -49,7 +49,7 @@ type Config struct { } // Init sets sane defaults. -func (c *Config) Init() { +func (c *Config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "ocs" } diff --git a/internal/http/services/owncloud/ocs/ocs.go b/internal/http/services/owncloud/ocs/ocs.go index 05ce3f8819..49c39c5f68 100644 --- a/internal/http/services/owncloud/ocs/ocs.go +++ b/internal/http/services/owncloud/ocs/ocs.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" - "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" ) @@ -50,16 +50,14 @@ type svc struct { } func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config.Config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.Init() - r := chi.NewRouter() s := &svc{ - c: conf, + c: &c, router: r, } @@ -68,9 +66,9 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) return nil, err } - if conf.CacheWarmupDriver == "first-request" && conf.ResourceInfoCacheTTL > 0 { + if c.CacheWarmupDriver == "first-request" && c.ResourceInfoCacheTTL > 0 { s.warmupCacheTracker = ttlcache.NewCache() - _ = s.warmupCacheTracker.SetTTL(time.Second * time.Duration(conf.ResourceInfoCacheTTL)) + _ = s.warmupCacheTracker.SetTTL(time.Second * time.Duration(c.ResourceInfoCacheTTL)) } return s, nil diff --git a/internal/http/services/preferences/preferences.go b/internal/http/services/preferences/preferences.go index d5f8bdf506..f4a99aa3bf 100644 --- a/internal/http/services/preferences/preferences.go +++ b/internal/http/services/preferences/preferences.go @@ -29,8 +29,8 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" - "github.com/mitchellh/mapstructure" ) func init() { @@ -43,7 +43,7 @@ type Config struct { GatewaySvc string `mapstructure:"gatewaysvc"` } -func (c *Config) init() { +func (c *Config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "preferences" } @@ -57,15 +57,14 @@ type svc struct { // New returns a new ocmd object. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &Config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() r := chi.NewRouter() s := &svc{ - conf: conf, + conf: &c, router: r, } diff --git a/internal/http/services/prometheus/prometheus.go b/internal/http/services/prometheus/prometheus.go index 88c18d81fe..b458bffbd4 100644 --- a/internal/http/services/prometheus/prometheus.go +++ b/internal/http/services/prometheus/prometheus.go @@ -24,7 +24,7 @@ import ( "contrib.go.opencensus.io/exporter/prometheus" "github.com/cs3org/reva/pkg/rhttp/global" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "go.opencensus.io/stats/view" ) @@ -35,13 +35,11 @@ func init() { // New returns a new prometheus service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - pe, err := prometheus.NewExporter(prometheus.Options{ Namespace: "revad", }) @@ -50,14 +48,14 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) } view.RegisterExporter(pe) - return &svc{prefix: conf.Prefix, h: pe}, nil + return &svc{prefix: c.Prefix, h: pe}, nil } type config struct { Prefix string `mapstructure:"prefix"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "metrics" } diff --git a/internal/http/services/reverseproxy/reverseproxy.go b/internal/http/services/reverseproxy/reverseproxy.go index 2922e3b449..2c81b20815 100644 --- a/internal/http/services/reverseproxy/reverseproxy.go +++ b/internal/http/services/reverseproxy/reverseproxy.go @@ -28,8 +28,8 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" - "github.com/mitchellh/mapstructure" ) func init() { @@ -45,7 +45,7 @@ type config struct { ProxyRulesJSON string `mapstructure:"proxy_rules_json"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.ProxyRulesJSON == "" { c.ProxyRulesJSON = "/etc/revad/proxy_rules.json" } @@ -57,13 +57,12 @@ type svc struct { // New returns an instance of the reverse proxy service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - f, err := os.ReadFile(conf.ProxyRulesJSON) + f, err := os.ReadFile(c.ProxyRulesJSON) if err != nil { return nil, err } diff --git a/internal/http/services/sciencemesh/sciencemesh.go b/internal/http/services/sciencemesh/sciencemesh.go index a728c82a77..6f3446968f 100644 --- a/internal/http/services/sciencemesh/sciencemesh.go +++ b/internal/http/services/sciencemesh/sciencemesh.go @@ -20,15 +20,14 @@ package sciencemesh import ( "context" - "errors" "net/http" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/smtpclient" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" - "github.com/mitchellh/mapstructure" ) func init() { @@ -37,22 +36,14 @@ func init() { // New returns a new sciencemesh service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - if conf.ProviderDomain == "" { - return nil, errors.New("sciencemesh: provider_domain is missing from configuration") - } - if conf.MeshDirectoryURL == "" { - return nil, errors.New("sciencemesh: mesh_directory_url is missing from configuration") - } - r := chi.NewRouter() s := &svc{ - conf: conf, + conf: &c, router: r, } @@ -70,19 +61,22 @@ func (s *svc) Close() error { type config struct { Prefix string `mapstructure:"prefix"` - SMTPCredentials *smtpclient.SMTPCredentials `mapstructure:"smtp_credentials"` - GatewaySvc string `mapstructure:"gatewaysvc"` - MeshDirectoryURL string `mapstructure:"mesh_directory_url"` - ProviderDomain string `mapstructure:"provider_domain"` + SMTPCredentials *smtpclient.SMTPCredentials `mapstructure:"smtp_credentials" validate:"required"` + GatewaySvc string `mapstructure:"gatewaysvc" validate:"required"` + MeshDirectoryURL string `mapstructure:"mesh_directory_url" validate:"required"` + ProviderDomain string `mapstructure:"provider_domain" validate:"required"` SubjectTemplate string `mapstructure:"subject_template"` BodyTemplatePath string `mapstructure:"body_template_path"` OCMMountPoint string `mapstructure:"ocm_mount_point"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "sciencemesh" } + if c.OCMMountPoint == "" { + c.OCMMountPoint = "/ocm" + } c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) } diff --git a/internal/http/services/siteacc/siteacc.go b/internal/http/services/siteacc/siteacc.go index 9f44535c7e..2d01b498d6 100644 --- a/internal/http/services/siteacc/siteacc.go +++ b/internal/http/services/siteacc/siteacc.go @@ -26,7 +26,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/siteacc" "github.com/cs3org/reva/pkg/siteacc/config" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "github.com/rs/zerolog" ) @@ -66,21 +66,6 @@ func (s *svc) Handler() http.Handler { return s.siteacc.RequestHandler() } -func parseConfig(m map[string]interface{}) (*config.Configuration, error) { - conf := &config.Configuration{} - if err := mapstructure.Decode(m, &conf); err != nil { - return nil, errors.Wrap(err, "error decoding configuration") - } - applyDefaultConfig(conf) - conf.Cleanup() - - if conf.Webserver.URL == "" { - return nil, errors.Errorf("no webserver URL specified") - } - - return conf, nil -} - func applyDefaultConfig(conf *config.Configuration) { if conf.Prefix == "" { conf.Prefix = serviceName @@ -106,22 +91,24 @@ func applyDefaultConfig(conf *config.Configuration) { // New returns a new Site Accounts service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - // Prepare the configuration - conf, err := parseConfig(m) - if err != nil { + var c config.Configuration + if err := cfg.Decode(m, &c); err != nil { return nil, err } + applyDefaultConfig(&c) + c.Cleanup() + // Create the sites accounts instance log := appctx.GetLogger(ctx) - siteacc, err := siteacc.New(conf, log) + siteacc, err := siteacc.New(&c, log) if err != nil { return nil, errors.Wrap(err, "error creating the sites accounts service") } // Create the service s := &svc{ - conf: conf, + conf: &c, log: log, siteacc: siteacc, } diff --git a/internal/http/services/sysinfo/sysinfo.go b/internal/http/services/sysinfo/sysinfo.go index d28e98dd35..05e58a310b 100644 --- a/internal/http/services/sysinfo/sysinfo.go +++ b/internal/http/services/sysinfo/sysinfo.go @@ -25,8 +25,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sysinfo" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -37,6 +36,12 @@ type config struct { Prefix string `mapstructure:"prefix"` } +func (c *config) ApplyDefaults() { + if c.Prefix == "" { + c.Prefix = serviceName + } +} + type svc struct { conf *config } @@ -78,32 +83,16 @@ func (s *svc) getJSONData() string { return "" } -func parseConfig(m map[string]interface{}) (*config, error) { - cfg := &config{} - if err := mapstructure.Decode(m, &cfg); err != nil { - return nil, errors.Wrap(err, "sysinfo: error decoding configuration") - } - applyDefaultConfig(cfg) - return cfg, nil -} - -func applyDefaultConfig(conf *config) { - if conf.Prefix == "" { - conf.Prefix = serviceName - } -} - // New returns a new SysInfo service. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - // Prepare the configuration - conf, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } // Create the service s := &svc{ - conf: conf, + conf: &c, } return s, nil } diff --git a/internal/http/services/wellknown/wellknown.go b/internal/http/services/wellknown/wellknown.go index 159a8d9ed7..2107da3288 100644 --- a/internal/http/services/wellknown/wellknown.go +++ b/internal/http/services/wellknown/wellknown.go @@ -25,7 +25,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -44,7 +44,7 @@ type config struct { EndSessionEndpoint string `mapstructure:"end_session_endpoint"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Prefix == "" { c.Prefix = ".well-known" } @@ -57,15 +57,13 @@ type svc struct { // New returns a new webuisvc. func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { - conf := &config{} - if err := mapstructure.Decode(m, conf); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - s := &svc{ - conf: conf, + conf: &c, } s.setHandler() return s, nil diff --git a/internal/serverless/services/helloworld/helloworld.go b/internal/serverless/services/helloworld/helloworld.go index 50120cda11..46bf5cc190 100644 --- a/internal/serverless/services/helloworld/helloworld.go +++ b/internal/serverless/services/helloworld/helloworld.go @@ -24,9 +24,11 @@ import ( "os" "time" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rserverless" "github.com/mitchellh/mapstructure" "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ) type config struct { @@ -50,7 +52,7 @@ func init() { } // New returns a new helloworld service. -func New(m map[string]interface{}, log *zerolog.Logger) (rserverless.Service, error) { +func New(ctx context.Context, m map[string]interface{}) (rserverless.Service, error) { conf := &config{} conf.init() @@ -64,6 +66,7 @@ func New(m map[string]interface{}, log *zerolog.Logger) (rserverless.Service, er return nil, err } + log := appctx.GetLogger(ctx) s := &svc{ conf: conf, log: log, diff --git a/internal/serverless/services/notifications/notifications.go b/internal/serverless/services/notifications/notifications.go index b51b163fd4..a1df4b066a 100644 --- a/internal/serverless/services/notifications/notifications.go +++ b/internal/serverless/services/notifications/notifications.go @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/notification" "github.com/cs3org/reva/pkg/notification/handler" @@ -46,7 +47,7 @@ type config struct { NatsAddress string `mapstructure:"nats_address" docs:";The NATS server address."` NatsToken string `mapstructure:"nats_token" docs:"The token to authenticate against the NATS server"` NatsPrefix string `mapstructure:"nats_prefix" docs:"reva-notifications;The notifications NATS stream."` - HandlerConf map[string]interface{} `mapstructure:"handlers" docs:";Settings for the different notification handlers."` + HandlerConf map[string]map[string]interface{} `mapstructure:"handlers" docs:";Settings for the different notification handlers."` GroupingInterval int `mapstructure:"grouping_interval" docs:"60;Time in seconds to group incoming notification triggers"` GroupingMaxSize int `mapstructure:"grouping_max_size" docs:"100;Maximum number of notifications to group"` StorageDriver string `mapstructure:"storage_driver" docs:"mysql;The driver used to store notifications"` @@ -63,6 +64,7 @@ func defaultConfig() *config { } type svc struct { + ctx context.Context nc *nats.Conn js nats.JetStreamContext kv nats.KeyValue @@ -78,28 +80,30 @@ func init() { rserverless.Register("notifications", New) } -func getNotificationManager(c *config, l *zerolog.Logger) (notification.Manager, error) { +func getNotificationManager(ctx context.Context, c *config) (notification.Manager, error) { if f, ok := notificationManagerRegistry.NewFuncs[c.StorageDriver]; ok { - return f(c.StorageDrivers[c.StorageDriver]) + return f(ctx, c.StorageDrivers[c.StorageDriver]) } return nil, errtypes.NotFound(fmt.Sprintf("storage driver %s not found", c.StorageDriver)) } // New returns a new Notifications service. -func New(m map[string]interface{}, log *zerolog.Logger) (rserverless.Service, error) { +func New(ctx context.Context, m map[string]interface{}) (rserverless.Service, error) { conf := defaultConfig() if err := mapstructure.Decode(m, conf); err != nil { return nil, err } - nm, err := getNotificationManager(conf, log) + log := appctx.GetLogger(ctx) + nm, err := getNotificationManager(ctx, conf) if err != nil { return nil, err } log.Info().Msgf("notification storage %s initialized", conf.StorageDriver) s := &svc{ + ctx: ctx, conf: conf, log: log, nm: nm, @@ -111,7 +115,7 @@ func New(m map[string]interface{}, log *zerolog.Logger) (rserverless.Service, er // Start starts the Notifications service. func (s *svc) Start() { s.templates = *templateRegistry.New() - s.handlers = handlerRegistry.InitHandlers(s.conf.HandlerConf, s.log) + s.handlers = handlerRegistry.InitHandlers(s.ctx, s.conf.HandlerConf) s.accumulators = make(map[string]*accumulator.Accumulator[trigger.Trigger]) s.log.Debug().Msgf("connecting to nats server at %s", s.conf.NatsAddress) diff --git a/pkg/app/provider/demo/demo.go b/pkg/app/provider/demo/demo.go index 91df5b83f8..c17403fe12 100644 --- a/pkg/app/provider/demo/demo.go +++ b/pkg/app/provider/demo/demo.go @@ -29,7 +29,7 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/app" "github.com/cs3org/reva/pkg/app/provider/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -58,19 +58,11 @@ type config struct { IFrameUIProvider string `mapstructure:"iframe_ui_provider"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - // New returns an implementation to of the app.Provider interface that // connects to an application in the backend. func New(ctx context.Context, m map[string]interface{}) (app.Provider, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } return &demoProvider{iframeUIProvider: c.IFrameUIProvider}, nil diff --git a/pkg/app/provider/wopi/wopi.go b/pkg/app/provider/wopi/wopi.go index 5837950234..86bdf2c07b 100644 --- a/pkg/app/provider/wopi/wopi.go +++ b/pkg/app/provider/wopi/wopi.go @@ -51,9 +51,9 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" gomime "github.com/glpatcern/go-mime" "github.com/golang-jwt/jwt" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -90,12 +90,14 @@ type config struct { InsecureConnections bool `mapstructure:"insecure_connections"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err +func (c *config) ApplyDefaults() { + if c.AppIntURL == "" { + c.AppIntURL = c.AppURL + } + if c.IOPSecret == "" { + c.IOPSecret = os.Getenv("REVA_APPPROVIDER_IOPSECRET") } - return c, nil + c.JWTSecret = sharedconf.GetJWTSecret(c.JWTSecret) } type wopiProvider struct { @@ -107,20 +109,12 @@ type wopiProvider struct { // New returns an implementation of the app.Provider interface that // connects to an application in the backend. func New(ctx context.Context, m map[string]interface{}) (app.Provider, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - if c.AppIntURL == "" { - c.AppIntURL = c.AppURL - } - if c.IOPSecret == "" { - c.IOPSecret = os.Getenv("REVA_APPPROVIDER_IOPSECRET") - } - c.JWTSecret = sharedconf.GetJWTSecret(c.JWTSecret) - - appURLs, err := getAppURLs(c) + appURLs, err := getAppURLs(&c) if err != nil { return nil, err } @@ -134,7 +128,7 @@ func New(ctx context.Context, m map[string]interface{}) (app.Provider, error) { } return &wopiProvider{ - conf: c, + conf: &c, wopiClient: wopiClient, appURLs: appURLs, }, nil diff --git a/pkg/app/registry/static/static.go b/pkg/app/registry/static/static.go index 9890f6d25c..88e8e63108 100644 --- a/pkg/app/registry/static/static.go +++ b/pkg/app/registry/static/static.go @@ -30,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/app" "github.com/cs3org/reva/pkg/app/registry/registry" "github.com/cs3org/reva/pkg/errtypes" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/rs/zerolog/log" orderedmap "github.com/wk8/go-ordered-map" ) @@ -57,20 +57,6 @@ type config struct { MimeTypes []*mimeTypeConfig `mapstructure:"mime_types"` } -func (c *config) init() { - if len(c.Providers) == 0 { - c.Providers = []*registrypb.ProviderInfo{} - } -} - -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - type manager struct { providers map[string]*registrypb.ProviderInfo mimetypes *orderedmap.OrderedMap // map[string]*mimeTypeConfig -> map the mime type to the addresses of the corresponding providers @@ -79,11 +65,10 @@ type manager struct { // New returns an implementation of the app.Registry interface. func New(ctx context.Context, m map[string]interface{}) (app.Registry, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() mimetypes := orderedmap.New() diff --git a/pkg/appauth/manager/json/json.go b/pkg/appauth/manager/json/json.go index 0a488c6cb9..1ff1a667f9 100644 --- a/pkg/appauth/manager/json/json.go +++ b/pkg/appauth/manager/json/json.go @@ -34,7 +34,7 @@ import ( "github.com/cs3org/reva/pkg/appauth/manager/registry" ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "github.com/sethvargo/go-password/password" "golang.org/x/crypto/bcrypt" @@ -59,25 +59,23 @@ type jsonManager struct { // New returns a new mgr. func New(ctx context.Context, m map[string]interface{}) (appauth.Manager, error) { - c, err := parseConfig(m) - if err != nil { - return nil, errors.Wrap(err, "error creating a new manager") + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } - c.init() - // load or create file manager, err := loadOrCreate(c.File) if err != nil { return nil, errors.Wrap(err, "error loading the file containing the application passwords") } - manager.config = c + manager.config = &c return manager, nil } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/appauth.json" } @@ -89,14 +87,6 @@ func (c *config) init() { } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func loadOrCreate(file string) (*jsonManager, error) { stat, err := os.Stat(file) if os.IsNotExist(err) || stat.Size() == 0 { diff --git a/pkg/auth/manager/appauth/appauth.go b/pkg/auth/manager/appauth/appauth.go index daf292a739..75f64c274e 100644 --- a/pkg/auth/manager/appauth/appauth.go +++ b/pkg/auth/manager/appauth/appauth.go @@ -29,7 +29,8 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -38,7 +39,11 @@ func init() { } type manager struct { - GatewayAddr string `mapstructure:"gateway_addr"` + GatewayAddr string `mapstructure:"gatewaysvc"` +} + +func (m *manager) ApplyDefaults() { + m.GatewayAddr = sharedconf.GetGatewaySVC(m.GatewayAddr) } // New returns a new auth Manager. @@ -52,11 +57,8 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - err := mapstructure.Decode(ml, m) - if err != nil { - return errors.Wrap(err, "error decoding conf") - } - return nil + err := cfg.Decode(ml, m) + return errors.Wrap(err, "appauth: error decoding config") } func (m *manager) Authenticate(ctx context.Context, username, password string) (*user.User, map[string]*authpb.Scope, error) { diff --git a/pkg/auth/manager/json/json.go b/pkg/auth/manager/json/json.go index 5e095c062b..36c6d41641 100644 --- a/pkg/auth/manager/json/json.go +++ b/pkg/auth/manager/json/json.go @@ -30,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -61,22 +61,12 @@ type config struct { Users string `mapstructure:"users"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Users == "" { c.Users = "/etc/revad/users.json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - // New returns a new auth Manager. func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { mgr := &manager{} @@ -88,9 +78,9 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { - return err + var c config + if err := cfg.Decode(ml, &c); err != nil { + return errors.Wrap(err, "json: error decoding config") } m.credentials = map[string]*Credentials{} diff --git a/pkg/auth/manager/json/json_test.go b/pkg/auth/manager/json/json_test.go index 45cda03f6f..57744078d4 100644 --- a/pkg/auth/manager/json/json_test.go +++ b/pkg/auth/manager/json/json_test.go @@ -44,14 +44,9 @@ func TestGetManagerWithInvalidUser(t *testing.T) { { "Boolean in user", false, - "error decoding conf: 1 error(s) decoding:\n\n* " + + "json: error decoding config: 1 error(s) decoding:\n\n* " + "'users' expected type 'string', got unconvertible type 'bool', value: 'false'", }, - { - "Nil in user", - nil, - "open /etc/revad/users.json: no such file or directory", - }, } for _, tt := range tests { @@ -60,9 +55,7 @@ func TestGetManagerWithInvalidUser(t *testing.T) { "users": tt.user, } - manager, err := New(ctx, input) - - assert.Empty(t, manager) + _, err := New(ctx, input) assert.EqualError(t, err, tt.expectedError) }) } diff --git a/pkg/auth/manager/ldap/ldap.go b/pkg/auth/manager/ldap/ldap.go index e9f871720d..28abc4ba62 100644 --- a/pkg/auth/manager/ldap/ldap.go +++ b/pkg/auth/manager/ldap/ldap.go @@ -31,12 +31,11 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/logger" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-ldap/ldap/v3" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -87,17 +86,6 @@ var ldapDefaults = attributes{ GIDNumber: "gidNumber", } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{ - Schema: ldapDefaults, - } - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns an auth manager implementation that connects to a LDAP server to validate the user. func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { manager := &mgr{} @@ -105,19 +93,12 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { if err != nil { return nil, err } + // backwards compatibility + appctx.GetLogger(ctx).Warn().Msg("userfilter is deprecated, use a loginfilter like `(&(objectclass=posixAccount)(|(cn={{login}}))(mail={{login}}))`") return manager, nil } -func (am *mgr) Configure(m map[string]interface{}) error { - c, err := parseConfig(m) - if err != nil { - return err - } - - // backwards compatibility - if c.UserFilter != "" { - logger.New().Warn().Msg("userfilter is deprecated, use a loginfilter like `(&(objectclass=posixAccount)(|(cn={{login}}))(mail={{login}}))`") - } +func (c *config) ApplyDefaults() { if c.LoginFilter == "" { c.LoginFilter = c.UserFilter c.LoginFilter = strings.ReplaceAll(c.LoginFilter, "%s", "{{login}}") @@ -127,7 +108,15 @@ func (am *mgr) Configure(m map[string]interface{}) error { } c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) - am.c = c +} + +func (am *mgr) Configure(m map[string]interface{}) error { + var c config + c.Schema = ldapDefaults + if err := cfg.Decode(m, &c); err != nil { + return errors.Wrap(err, "ldap: error decoding config") + } + am.c = &c return nil } diff --git a/pkg/auth/manager/machine/machine.go b/pkg/auth/manager/machine/machine.go index 6d557e24c2..9281b6ed20 100644 --- a/pkg/auth/manager/machine/machine.go +++ b/pkg/auth/manager/machine/machine.go @@ -30,7 +30,8 @@ import ( "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -43,20 +44,21 @@ var claims = []string{"mail", "uid", "username", "gid", "userid"} type manager struct { APIKey string `mapstructure:"api_key"` - GatewayAddr string `mapstructure:"gateway_addr"` + GatewayAddr string `mapstructure:"gatewaysvc"` } func init() { registry.Register("machine", New) } +func (m *manager) ApplyDefaults() { + m.GatewayAddr = sharedconf.GetGatewaySVC(m.GatewayAddr) +} + // Configure parses the map conf. func (m *manager) Configure(conf map[string]interface{}) error { - err := mapstructure.Decode(conf, m) - if err != nil { - return errors.Wrap(err, "error decoding conf") - } - return nil + err := cfg.Decode(conf, m) + return errors.Wrap(err, "machine: error decoding config") } // New creates a new manager for the 'machine' authentication. diff --git a/pkg/auth/manager/nextcloud/nextcloud.go b/pkg/auth/manager/nextcloud/nextcloud.go index 502016b61d..f5a0a4ec39 100644 --- a/pkg/auth/manager/nextcloud/nextcloud.go +++ b/pkg/auth/manager/nextcloud/nextcloud.go @@ -33,7 +33,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -63,27 +63,14 @@ type Action struct { argS string } -func (c *AuthManagerConfig) init() { -} - -func parseConfig(m map[string]interface{}) (*AuthManagerConfig, error) { - c := &AuthManagerConfig{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns an auth manager implementation that verifies against a Nextcloud backend. func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err + var c AuthManagerConfig + if err := cfg.Decode(m, &c); err != nil { + return nil, errors.Wrap(err, "nextcloud: error decoding config") } - c.init() - return NewAuthManager(c) + return NewAuthManager(&c) } // NewAuthManager returns a new Nextcloud-based AuthManager. diff --git a/pkg/auth/manager/ocmshares/ocmshares.go b/pkg/auth/manager/ocmshares/ocmshares.go index b290964bee..1987797801 100644 --- a/pkg/auth/manager/ocmshares/ocmshares.go +++ b/pkg/auth/manager/ocmshares/ocmshares.go @@ -37,7 +37,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -51,10 +51,10 @@ type manager struct { } type config struct { - GatewayAddr string `mapstructure:"gateway_addr"` + GatewayAddr string `mapstructure:"gatewaysvc"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { c.GatewayAddr = sharedconf.GetGatewaySVC(c.GatewayAddr) } @@ -64,24 +64,21 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { if err := mgr.Configure(m); err != nil { return nil, err } + gw, err := pool.GetGatewayServiceClient(pool.Endpoint(mgr.c.GatewayAddr)) + if err != nil { + return nil, err + } + mgr.gw = gw return &mgr, nil } func (m *manager) Configure(ml map[string]interface{}) error { var c config - if err := mapstructure.Decode(ml, &c); err != nil { - return errors.Wrap(err, "error decoding config") + if err := cfg.Decode(ml, &c); err != nil { + return errors.Wrap(err, "ocmshares: error decoding config") } - c.init() m.c = &c - - gw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewayAddr)) - if err != nil { - return err - } - m.gw = gw - return nil } diff --git a/pkg/auth/manager/oidc/oidc.go b/pkg/auth/manager/oidc/oidc.go index 656077111d..4df459d9af 100644 --- a/pkg/auth/manager/oidc/oidc.go +++ b/pkg/auth/manager/oidc/oidc.go @@ -41,9 +41,9 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/golang-jwt/jwt" "github.com/juliangruber/go-intersect" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "golang.org/x/oauth2" ) @@ -76,7 +76,7 @@ type oidcUserMapping struct { Username string `mapstructure:"username" json:"username"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.IDClaim == "" { // sub is stable and defined as unique. the user manager needs to take care of the sub to user metadata lookup c.IDClaim = "sub" @@ -94,15 +94,6 @@ func (c *config) init() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns an auth manager implementation that verifies the oidc token and obtains the user claims. func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { manager := &mgr{ @@ -116,12 +107,11 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { } func (am *mgr) Configure(m map[string]interface{}) error { - c, err := parseConfig(m) - if err != nil { - return err + var c config + if err := cfg.Decode(m, &c); err != nil { + return errors.Wrap(err, "oidc: error decoding config") } - c.init() - am.c = c + am.c = &c am.oidcUsersMapping = map[string]*oidcUserMapping{} if c.UsersMapping == "" { diff --git a/pkg/auth/manager/owncloudsql/owncloudsql.go b/pkg/auth/manager/owncloudsql/owncloudsql.go index 2c7d9277bd..1f6053640d 100644 --- a/pkg/auth/manager/owncloudsql/owncloudsql.go +++ b/pkg/auth/manager/owncloudsql/owncloudsql.go @@ -34,10 +34,10 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/utils/cfg" // Provides mysql drivers. _ "github.com/go-sql-driver/mysql" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" ) @@ -86,26 +86,20 @@ func NewMysql(ctx context.Context, m map[string]interface{}) (auth.Manager, erro return mgr, nil } -func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { - return err - } - +func (c *config) ApplyDefaults() { if c.Nobody == 0 { c.Nobody = 99 } - - m.c = c - return nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, &c); err != nil { - return nil, err +func (m *manager) Configure(ml map[string]interface{}) error { + var c config + if err := cfg.Decode(ml, &c); err != nil { + return errors.Wrap(err, "owncloudsql: error decoding config") } - return c, nil + + m.c = &c + return nil } func (m *manager) Authenticate(ctx context.Context, login, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index 2b0f48d8f0..c7d2097069 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -33,7 +33,8 @@ import ( "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/sharedconf" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -46,16 +47,11 @@ type manager struct { } type config struct { - GatewayAddr string `mapstructure:"gateway_addr"` + GatewayAddr string `mapstructure:"gatewaysvc"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil +func (c *config) ApplyDefaults() { + c.GatewayAddr = sharedconf.GetGatewaySVC(c.GatewayAddr) } // New returns a new auth Manager. @@ -69,11 +65,11 @@ func New(ctx context.Context, m map[string]interface{}) (auth.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - conf, err := parseConfig(ml) - if err != nil { - return err + var c config + if err := cfg.Decode(ml, &c); err != nil { + return errors.Wrap(err, "publicshares: error decoding config") } - m.c = conf + m.c = &c return nil } diff --git a/pkg/auth/registry/static/static.go b/pkg/auth/registry/static/static.go index 852b1f4cac..6f098aee12 100644 --- a/pkg/auth/registry/static/static.go +++ b/pkg/auth/registry/static/static.go @@ -26,7 +26,7 @@ import ( "github.com/cs3org/reva/pkg/auth/registry/registry" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/sharedconf" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -37,7 +37,7 @@ type config struct { Rules map[string]string `mapstructure:"rules"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if len(c.Rules) == 0 { c.Rules = map[string]string{ "basic": sharedconf.GetGatewaySVC(""), @@ -70,20 +70,11 @@ func (r *reg) GetProvider(ctx context.Context, authType string) (*registrypb.Pro return nil, errtypes.NotFound("static: auth type not found: " + authType) } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - // New returns an implementation of the auth.Registry interface. func New(ctx context.Context, m map[string]interface{}) (auth.Registry, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() return ®{rules: c.Rules}, nil } diff --git a/pkg/cbox/favorite/sql/sql.go b/pkg/cbox/favorite/sql/sql.go index 15009062f7..5e2ef9b238 100644 --- a/pkg/cbox/favorite/sql/sql.go +++ b/pkg/cbox/favorite/sql/sql.go @@ -29,7 +29,7 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/storage/favorite" "github.com/cs3org/reva/pkg/storage/favorite/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -51,8 +51,8 @@ type mgr struct { // New returns an instance of the cbox sql favorites manager. func New(m map[string]interface{}) (favorite.Manager, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -62,7 +62,7 @@ func New(m map[string]interface{}) (favorite.Manager, error) { } return &mgr{ - c: c, + c: &c, db: db, }, nil } diff --git a/pkg/cbox/group/rest/rest.go b/pkg/cbox/group/rest/rest.go index 44d2863622..43acf7a2a3 100644 --- a/pkg/cbox/group/rest/rest.go +++ b/pkg/cbox/group/rest/rest.go @@ -34,9 +34,9 @@ import ( utils "github.com/cs3org/reva/pkg/cbox/utils" "github.com/cs3org/reva/pkg/group" "github.com/cs3org/reva/pkg/group/manager/registry" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/cs3org/reva/pkg/utils/list" "github.com/gomodule/redigo/redis" - "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" ) @@ -76,7 +76,7 @@ type config struct { GroupFetchInterval int `mapstructure:"group_fetch_interval" docs:"3600"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.GroupMembersCacheExpiration == 0 { c.GroupMembersCacheExpiration = 5 } @@ -100,21 +100,12 @@ func (c *config) init() { } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - // New returns a user manager implementation that makes calls to the GRAPPA API. func New(ctx context.Context, m map[string]interface{}) (group.Manager, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() redisPool := initRedisPool(c.RedisAddress, c.RedisUsername, c.RedisPassword) apiTokenManager, err := utils.InitAPITokenManager(m) @@ -123,7 +114,7 @@ func New(ctx context.Context, m map[string]interface{}) (group.Manager, error) { } mgr := &manager{ - conf: c, + conf: &c, redisPool: redisPool, apiTokenManager: apiTokenManager, } diff --git a/pkg/cbox/preferences/sql/sql.go b/pkg/cbox/preferences/sql/sql.go index 680a1fcb91..8e0b2afbd5 100644 --- a/pkg/cbox/preferences/sql/sql.go +++ b/pkg/cbox/preferences/sql/sql.go @@ -27,7 +27,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/preferences" "github.com/cs3org/reva/pkg/preferences/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -49,8 +49,8 @@ type mgr struct { // New returns an instance of the cbox sql preferences manager. func New(ctx context.Context, m map[string]interface{}) (preferences.Manager, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -60,7 +60,7 @@ func New(ctx context.Context, m map[string]interface{}) (preferences.Manager, er } return &mgr{ - c: c, + c: &c, db: db, }, nil } diff --git a/pkg/cbox/publicshare/sql/sql.go b/pkg/cbox/publicshare/sql/sql.go index 0b81b4d025..3602224ab0 100644 --- a/pkg/cbox/publicshare/sql/sql.go +++ b/pkg/cbox/publicshare/sql/sql.go @@ -42,7 +42,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" ) @@ -77,7 +77,7 @@ type manager struct { client gatewayv1beta1.GatewayAPIClient } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.SharePasswordHashCost == 0 { c.SharePasswordHashCost = 11 } @@ -109,11 +109,10 @@ func (m *manager) startJanitorRun() { // New returns a new public share manager. func New(ctx context.Context, m map[string]interface{}) (publicshare.Manager, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", c.DBUsername, c.DBPassword, c.DBHost, c.DBPort, c.DBName)) if err != nil { @@ -126,7 +125,7 @@ func New(ctx context.Context, m map[string]interface{}) (publicshare.Manager, er } mgr := manager{ - c: c, + c: &c, db: db, client: gw, } diff --git a/pkg/cbox/share/sql/sql.go b/pkg/cbox/share/sql/sql.go index 0a87d641c9..0133ed8ddb 100644 --- a/pkg/cbox/share/sql/sql.go +++ b/pkg/cbox/share/sql/sql.go @@ -40,10 +40,10 @@ import ( "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" // Provides mysql drivers. _ "github.com/go-sql-driver/mysql" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -76,11 +76,14 @@ type mgr struct { client gatewayv1beta1.GatewayAPIClient } +func (c *config) ApplyDefaults() { + c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) +} + // New returns a new share manager. func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { - c, err := parseConfig(m) - if err != nil { - err = errors.Wrap(err, "error creating a new manager") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -95,21 +98,12 @@ func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { } return &mgr{ - c: c, + c: &c, db: db, client: gw, }, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) - return c, nil -} - func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { user := ctxpkg.ContextMustGetUser(ctx) diff --git a/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go b/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go index 2737b0ecc5..ec385dcef4 100644 --- a/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go +++ b/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.go @@ -30,8 +30,7 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -43,13 +42,13 @@ type wrapper struct { mountIDTemplate *template.Template } -func parseConfig(m map[string]interface{}) (*eosfs.Config, string, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, "", err +// New returns an implementation of the storage.FS interface that forms a wrapper +// around separate connections to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } - // default to version invariance if not configured if _, ok := m["version_invariant"]; !ok { c.VersionInvariant = true @@ -60,19 +59,7 @@ func parseConfig(m map[string]interface{}) (*eosfs.Config, string, error) { t = "eoshome-{{substr 0 1 .Username}}" } - return c, t, nil -} - -// New returns an implementation of the storage.FS interface that forms a wrapper -// around separate connections to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, t, err := parseConfig(m) - if err != nil { - return nil, err - } - c.EnableHome = true - - eos, err := eosfs.NewEOSFS(ctx, c) + eos, err := eosfs.NewEOSFS(ctx, &c) if err != nil { return nil, err } diff --git a/pkg/cbox/storage/eoswrapper/eoswrapper.go b/pkg/cbox/storage/eoswrapper/eoswrapper.go index 79663ff590..d4b518db40 100644 --- a/pkg/cbox/storage/eoswrapper/eoswrapper.go +++ b/pkg/cbox/storage/eoswrapper/eoswrapper.go @@ -32,8 +32,7 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -54,11 +53,12 @@ type wrapper struct { mountIDTemplate *template.Template } -func parseConfig(m map[string]interface{}) (*eosfs.Config, string, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, "", err +// New returns an implementation of the storage.FS interface that forms a wrapper +// around separate connections to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } // default to version invariance if not configured @@ -77,18 +77,7 @@ func parseConfig(m map[string]interface{}) (*eosfs.Config, string, error) { t = "eoshome-{{ trimAll \"/\" .Path | substr 0 1 }}" } - return c, t, nil -} - -// New returns an implementation of the storage.FS interface that forms a wrapper -// around separate connections to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, t, err := parseConfig(m) - if err != nil { - return nil, err - } - - eos, err := eosfs.NewEOSFS(ctx, c) + eos, err := eosfs.NewEOSFS(ctx, &c) if err != nil { return nil, err } @@ -98,7 +87,7 @@ func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { return nil, err } - return &wrapper{FS: eos, conf: c, mountIDTemplate: mountIDTemplate}, nil + return &wrapper{FS: eos, conf: &c, mountIDTemplate: mountIDTemplate}, nil } // We need to override the two methods, GetMD and ListFolder to fill the diff --git a/pkg/cbox/user/rest/rest.go b/pkg/cbox/user/rest/rest.go index 72864cc7e7..d15ed7eeab 100644 --- a/pkg/cbox/user/rest/rest.go +++ b/pkg/cbox/user/rest/rest.go @@ -32,9 +32,9 @@ import ( utils "github.com/cs3org/reva/pkg/cbox/utils" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/cs3org/reva/pkg/utils/list" "github.com/gomodule/redigo/redis" - "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" ) @@ -74,7 +74,7 @@ type config struct { UserFetchInterval int `mapstructure:"user_fetch_interval" docs:"3600"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.UserGroupsCacheExpiration == 0 { c.UserGroupsCacheExpiration = 5 } @@ -98,14 +98,6 @@ func (c *config) init() { } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - // New returns a user manager implementation that makes calls to the GRAPPA API. func New(ctx context.Context, m map[string]interface{}) (user.Manager, error) { mgr := &manager{} @@ -117,17 +109,16 @@ func New(ctx context.Context, m map[string]interface{}) (user.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { + var c config + if err := cfg.Decode(ml, &c); err != nil { return err } - c.init() redisPool := initRedisPool(c.RedisAddress, c.RedisUsername, c.RedisPassword) apiTokenManager, err := utils.InitAPITokenManager(ml) if err != nil { return err } - m.conf = c + m.conf = &c m.redisPool = redisPool m.apiTokenManager = apiTokenManager diff --git a/pkg/datatx/manager/rclone/rclone.go b/pkg/datatx/manager/rclone/rclone.go index 244bed0e20..1a1ae155ac 100644 --- a/pkg/datatx/manager/rclone/rclone.go +++ b/pkg/datatx/manager/rclone/rclone.go @@ -111,7 +111,7 @@ func New(ctx context.Context, m map[string]interface{}) (txdriver.Manager, error client := rhttp.GetHTTPClient(rhttp.Insecure(c.Insecure)) - storage, err := getStorageManager(c) + storage, err := getStorageManager(ctx, c) if err != nil { return nil, err } @@ -132,9 +132,9 @@ func parseConfig(m map[string]interface{}) (*config, error) { return c, nil } -func getStorageManager(c *config) (repository.Repository, error) { +func getStorageManager(ctx context.Context, c *config) (repository.Repository, error) { if f, ok := repoRegistry.NewFuncs[c.StorageDriver]; ok { - return f(c.StorageDrivers[c.StorageDriver]) + return f(ctx, c.StorageDrivers[c.StorageDriver]) } return nil, errtypes.NotFound("rclone service: storage driver not found: " + c.StorageDriver) } diff --git a/pkg/datatx/manager/rclone/repository/json/json.go b/pkg/datatx/manager/rclone/repository/json/json.go index 2d31f70ff1..4e11c6d001 100644 --- a/pkg/datatx/manager/rclone/repository/json/json.go +++ b/pkg/datatx/manager/rclone/repository/json/json.go @@ -19,6 +19,7 @@ package json import ( + "context" "encoding/json" "io" "os" @@ -26,7 +27,7 @@ import ( "github.com/cs3org/reva/pkg/datatx/manager/rclone/repository" "github.com/cs3org/reva/pkg/datatx/manager/rclone/repository/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -48,28 +49,18 @@ type rcloneJobsModel struct { RcloneJobs map[string]*repository.Job `json:"rcloneJobs"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "rclone repository json driver: error decoding configuration") - return nil, err - } - return c, nil -} - -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/transfer-jobs.json" } } // New returns a json storage driver. -func New(m map[string]interface{}) (repository.Repository, error) { - c, err := parseConfig(m) - if err != nil { +func New(ctx context.Context, m map[string]interface{}) (repository.Repository, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() model, err := loadOrCreate(c.File) if err != nil { @@ -78,7 +69,7 @@ func New(m map[string]interface{}) (repository.Repository, error) { } mgr := &mgr{ - config: c, + config: &c, model: model, } diff --git a/pkg/datatx/manager/rclone/repository/registry/registry.go b/pkg/datatx/manager/rclone/repository/registry/registry.go index 113586f3ad..2764f88923 100644 --- a/pkg/datatx/manager/rclone/repository/registry/registry.go +++ b/pkg/datatx/manager/rclone/repository/registry/registry.go @@ -19,12 +19,14 @@ package registry import ( + "context" + "github.com/cs3org/reva/pkg/datatx/manager/rclone/repository" ) // NewFunc is the function that rclone repository implementations // should register at init time. -type NewFunc func(map[string]interface{}) (repository.Repository, error) +type NewFunc func(context.Context, map[string]interface{}) (repository.Repository, error) // NewFuncs is a map containing all the registered datatx backends. var NewFuncs = map[string]NewFunc{} diff --git a/pkg/datatx/repository/json/json.go b/pkg/datatx/repository/json/json.go index 3f121bbff0..8cdce41cb7 100644 --- a/pkg/datatx/repository/json/json.go +++ b/pkg/datatx/repository/json/json.go @@ -29,7 +29,7 @@ import ( txv1beta "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" "github.com/cs3org/reva/pkg/datatx" "github.com/cs3org/reva/pkg/datatx/repository/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -51,16 +51,7 @@ type transfersModel struct { Transfers map[string]*datatx.Transfer `json:"transfers"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "datatx repository json driver: error decoding configuration") - return nil, err - } - return c, nil -} - -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/datatx-transfers.json" } @@ -68,11 +59,10 @@ func (c *config) init() { // New returns a json storage driver. func New(ctx context.Context, m map[string]interface{}) (datatx.Repository, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() model, err := loadOrCreate(c.File) if err != nil { @@ -81,7 +71,7 @@ func New(ctx context.Context, m map[string]interface{}) (datatx.Repository, erro } mgr := &mgr{ - config: c, + config: &c, model: model, } diff --git a/pkg/eosclient/eosbinary/eosbinary.go b/pkg/eosclient/eosbinary/eosbinary.go index ead7c21151..1a47aa8240 100644 --- a/pkg/eosclient/eosbinary/eosbinary.go +++ b/pkg/eosclient/eosbinary/eosbinary.go @@ -120,7 +120,7 @@ type Options struct { TokenExpiry int } -func (opt *Options) init() { +func (opt *Options) ApplyDefaults() { if opt.ForceSingleUserMode && opt.SingleUsername != "" { opt.SingleUsername = "apache" } @@ -150,7 +150,7 @@ type Client struct { // New creates a new client with the given options. func New(opt *Options) (*Client, error) { - opt.init() + opt.ApplyDefaults() c := new(Client) c.opt = opt return c, nil diff --git a/pkg/errtypes/join.go b/pkg/errtypes/join.go new file mode 100644 index 0000000000..7fdcaa8e18 --- /dev/null +++ b/pkg/errtypes/join.go @@ -0,0 +1,42 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package errtypes + +import ( + "strings" +) + +type joinErrors []error + +// Join returns an error representing a list of errors. +func Join(err ...error) error { + return joinErrors(err) +} + +// Error return a string comma (,) separated of all the errors. +func (e joinErrors) Error() string { + var b strings.Builder + for i, err := range e { + b.WriteString(err.Error()) + if i != len(e)-1 { + b.WriteString(", ") + } + } + return b.String() +} diff --git a/pkg/group/manager/json/json.go b/pkg/group/manager/json/json.go index 1df0a407ac..911693f425 100644 --- a/pkg/group/manager/json/json.go +++ b/pkg/group/manager/json/json.go @@ -30,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/group" "github.com/cs3org/reva/pkg/group/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -47,26 +47,16 @@ type config struct { Groups string `mapstructure:"groups"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Groups == "" { c.Groups = "/etc/revad/groups.json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - // New returns a group manager implementation that reads a json file to provide group metadata. func New(ctx context.Context, m map[string]interface{}) (group.Manager, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } diff --git a/pkg/group/manager/ldap/ldap.go b/pkg/group/manager/ldap/ldap.go index fb8e347f15..669c44c3ea 100644 --- a/pkg/group/manager/ldap/ldap.go +++ b/pkg/group/manager/ldap/ldap.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/pkg/group" "github.com/cs3org/reva/pkg/group/manager/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-ldap/ldap/v3" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -86,22 +86,11 @@ var ldapDefaults = attributes{ GIDNumber: "gidNumber", } -func parseConfig(m map[string]interface{}) (*config, error) { - c := config{ - Schema: ldapDefaults, - } - if err := mapstructure.Decode(m, &c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - - return &c, nil -} - // New returns a group manager implementation that connects to a LDAP server to provide group metadata. func New(ctx context.Context, m map[string]interface{}) (group.Manager, error) { - c, err := parseConfig(m) - if err != nil { + var c config + c.Schema = ldapDefaults + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -112,9 +101,10 @@ func New(ctx context.Context, m map[string]interface{}) (group.Manager, error) { c.MemberFilter = strings.ReplaceAll(c.MemberFilter, "%s", "{{.OpaqueId}}") mgr := &manager{ - c: c, + c: &c, } + var err error mgr.groupfilter, err = template.New("gf").Funcs(sprig.TxtFuncMap()).Parse(c.GroupFilter) if err != nil { err := errors.Wrap(err, fmt.Sprintf("error parsing groupfilter tpl:%s", c.GroupFilter)) diff --git a/pkg/mentix/config/config.go b/pkg/mentix/config/config.go index e65a777330..32e45fabd6 100644 --- a/pkg/mentix/config/config.go +++ b/pkg/mentix/config/config.go @@ -73,7 +73,7 @@ type Configuration struct { } // Init sets sane defaults. -func (c *Configuration) Init() { +func (c *Configuration) ApplyDefaults() { if c.Prefix == "" { c.Prefix = "mentix" } diff --git a/pkg/metrics/config/config.go b/pkg/metrics/config/config.go index 27dd4b96de..68f6318427 100644 --- a/pkg/metrics/config/config.go +++ b/pkg/metrics/config/config.go @@ -29,7 +29,7 @@ type Config struct { } // Init sets sane defaults. -func (c *Config) Init() { +func (c *Config) ApplyDefaults() { if c.MetricsDataDriverType == "json" { // default values if c.MetricsDataLocation == "" { diff --git a/pkg/notification/handler/emailhandler/emailhandler.go b/pkg/notification/handler/emailhandler/emailhandler.go index 47152f51c8..3d8f3fc97b 100644 --- a/pkg/notification/handler/emailhandler/emailhandler.go +++ b/pkg/notification/handler/emailhandler/emailhandler.go @@ -19,14 +19,16 @@ package emailhandler import ( + "context" "fmt" "net/smtp" "regexp" "strings" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/notification/handler" "github.com/cs3org/reva/pkg/notification/handler/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/rs/zerolog" ) @@ -37,7 +39,7 @@ func init() { // EmailHandler is the notification handler for emails. type EmailHandler struct { conf *config - Log *zerolog.Logger + log *zerolog.Logger } type config struct { @@ -48,22 +50,23 @@ type config struct { DefaultSender string `mapstructure:"default_sender" docs:"no-reply@cernbox.cern.ch;Default sender when not specified in the trigger."` } -func defaultConfig() *config { - return &config{ - DefaultSender: "no-reply@cernbox.cern.ch", +func (c *config) ApplyDefaults() { + if c.DefaultSender == "" { + c.DefaultSender = "no-reply@cernbox.cern.ch" } } // New returns a new email handler. -func New(log *zerolog.Logger, conf interface{}) (handler.Handler, error) { - c := defaultConfig() - if err := mapstructure.Decode(conf, c); err != nil { +func New(ctx context.Context, m map[string]any) (handler.Handler, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } + log := appctx.GetLogger(ctx) return &EmailHandler{ - conf: c, - Log: log, + conf: &c, + log: log, }, nil } @@ -79,7 +82,7 @@ func (e *EmailHandler) Send(sender, recipient, subject, body string) error { return err } - e.Log.Debug().Msgf("mail sent to recipient %s", recipient) + e.log.Debug().Msgf("mail sent to recipient %s", recipient) return nil } diff --git a/pkg/notification/handler/registry/registry.go b/pkg/notification/handler/registry/registry.go index e4a9271eab..18fad9879d 100644 --- a/pkg/notification/handler/registry/registry.go +++ b/pkg/notification/handler/registry/registry.go @@ -19,13 +19,15 @@ package registry import ( + "context" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/notification/handler" - "github.com/rs/zerolog" ) // NewHandlerFunc is the function that notification handlers should register to // at init time. -type NewHandlerFunc func(Log *zerolog.Logger, conf interface{}) (handler.Handler, error) +type NewHandlerFunc func(context.Context, map[string]any) (handler.Handler, error) // NewHandlerFuncs is a map containing all the registered notification handlers. var NewHandlerFuncs = map[string]NewHandlerFunc{} @@ -38,13 +40,16 @@ func Register(name string, f NewHandlerFunc) { // InitHandlers initializes the notification handlers with the configuration // and the log from a service. -func InitHandlers(handlerConf map[string]interface{}, log *zerolog.Logger) map[string]handler.Handler { +func InitHandlers(ctx context.Context, handlerConf map[string]map[string]any) map[string]handler.Handler { handlers := make(map[string]handler.Handler) hCount := 0 + log := appctx.GetLogger(ctx) for n, f := range NewHandlerFuncs { if c, ok := handlerConf[n]; ok { - nh, err := f(log, c) + l := log.With().Str("service", n).Logger() + ctx := appctx.WithLogger(ctx, &l) + nh, err := f(ctx, c) if err != nil { log.Err(err).Msgf("error initializing notification handler %s", n) } diff --git a/pkg/notification/manager/registry/registry.go b/pkg/notification/manager/registry/registry.go index 4ae551145a..2d1935b5eb 100644 --- a/pkg/notification/manager/registry/registry.go +++ b/pkg/notification/manager/registry/registry.go @@ -18,13 +18,17 @@ package registry -import "github.com/cs3org/reva/pkg/notification" +import ( + "context" + + "github.com/cs3org/reva/pkg/notification" +) // import "github.com/cs3org/reva/pkg/share" // NewFunc is the function that notification managers // should register at init time. -type NewFunc func(map[string]interface{}) (notification.Manager, error) +type NewFunc func(context.Context, map[string]interface{}) (notification.Manager, error) // NewFuncs is a map containing all the registered notification managers. var NewFuncs = map[string]NewFunc{} diff --git a/pkg/notification/manager/sql/sql.go b/pkg/notification/manager/sql/sql.go index 1e71dad7ab..c1af5b15a9 100644 --- a/pkg/notification/manager/sql/sql.go +++ b/pkg/notification/manager/sql/sql.go @@ -19,12 +19,13 @@ package sql import ( + "context" "database/sql" "fmt" "github.com/cs3org/reva/pkg/notification" "github.com/cs3org/reva/pkg/notification/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -37,7 +38,6 @@ type config struct { DBHost string `mapstructure:"db_host"` DBPort int `mapstructure:"db_port"` DBName string `mapstructure:"db_name"` - GatewaySvc string `mapstructure:"gatewaysvc"` } type mgr struct { @@ -46,9 +46,9 @@ type mgr struct { } // NewMysql returns an instance of the sql notifications manager. -func NewMysql(m map[string]interface{}) (notification.Manager, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { +func NewMysql(ctx context.Context, m map[string]interface{}) (notification.Manager, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } diff --git a/pkg/ocm/invite/repository/json/json.go b/pkg/ocm/invite/repository/json/json.go index ea4c3e8687..e60ad42251 100644 --- a/pkg/ocm/invite/repository/json/json.go +++ b/pkg/ocm/invite/repository/json/json.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/pkg/ocm/invite" "github.com/cs3org/reva/pkg/ocm/invite/repository/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/cs3org/reva/pkg/utils/list" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -59,47 +59,33 @@ func init() { registry.Register("json", New) } -func (c *config) init() error { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/ocm-invites.json" } - - return nil } // New returns a new invite manager object. func New(ctx context.Context, m map[string]interface{}) (invite.Repository, error) { - config, err := parseConfig(m) - if err != nil { - return nil, errors.Wrap(err, "error parsing config for json invite repository") - } - err = config.init() - if err != nil { - return nil, errors.Wrap(err, "error setting config defaults for json invite repository") + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } // load or create file - model, err := loadOrCreate(config.File) + model, err := loadOrCreate(c.File) if err != nil { return nil, errors.Wrap(err, "error loading the file containing the invites") } manager := &manager{ - config: config, + config: &c, model: model, } return manager, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func loadOrCreate(file string) (*inviteModel, error) { _, err := os.Stat(file) if os.IsNotExist(err) { diff --git a/pkg/ocm/invite/repository/sql/sql.go b/pkg/ocm/invite/repository/sql/sql.go index 7746796da3..dc5b2e6f49 100644 --- a/pkg/ocm/invite/repository/sql/sql.go +++ b/pkg/ocm/invite/repository/sql/sql.go @@ -32,11 +32,11 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/invite" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-sql-driver/mysql" "github.com/cs3org/reva/pkg/ocm/invite/repository/registry" "github.com/cs3org/reva/pkg/sharedconf" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -66,38 +66,29 @@ type config struct { GatewaySvc string `mapstructure:"gatewaysvc"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) } -func parseConfig(c map[string]interface{}) (*config, error) { - var conf config - if err := mapstructure.Decode(c, &conf); err != nil { - return nil, err - } - return &conf, nil -} - // New creates a sql repository for ocm tokens and users. -func New(ctx context.Context, c map[string]interface{}) (invite.Repository, error) { - conf, err := parseConfig(c) - if err != nil { - return nil, errors.Wrap(err, "sql: error parsing config") +func New(ctx context.Context, m map[string]interface{}) (invite.Repository, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } - conf.init() - db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?parseTime=true", conf.DBUsername, conf.DBPassword, conf.DBAddress, conf.DBName)) + db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?parseTime=true", c.DBUsername, c.DBPassword, c.DBAddress, c.DBName)) if err != nil { return nil, errors.Wrap(err, "sql: error opening connection to mysql database") } - gw, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySvc)) + gw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySvc)) if err != nil { return nil, err } mgr := mgr{ - c: conf, + c: &c, db: db, client: gw, } diff --git a/pkg/ocm/provider/authorizer/json/json.go b/pkg/ocm/provider/authorizer/json/json.go index cf6839e5dd..e13a038fea 100644 --- a/pkg/ocm/provider/authorizer/json/json.go +++ b/pkg/ocm/provider/authorizer/json/json.go @@ -32,7 +32,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/provider" "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -42,12 +42,10 @@ func init() { // New returns a new authorizer object. func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() f, err := os.ReadFile(c.Providers) if err != nil { @@ -61,7 +59,7 @@ func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, er a := &authorizer{ providerIPs: sync.Map{}, - conf: c, + conf: &c, } a.providers = a.getOCMProviders(providers) @@ -73,7 +71,7 @@ type config struct { VerifyRequestHostname bool `mapstructure:"verify_request_hostname"` } -func (c *config) init() { +func (c *config) ApplyTemplates() { if c.Providers == "" { c.Providers = "/etc/revad/ocm-providers.json" } diff --git a/pkg/ocm/provider/authorizer/mentix/mentix.go b/pkg/ocm/provider/authorizer/mentix/mentix.go index 9c165c1a5e..88347270f5 100644 --- a/pkg/ocm/provider/authorizer/mentix/mentix.go +++ b/pkg/ocm/provider/authorizer/mentix/mentix.go @@ -34,7 +34,7 @@ import ( "github.com/cs3org/reva/pkg/ocm/provider" "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" "github.com/cs3org/reva/pkg/rhttp" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -50,12 +50,10 @@ type Client struct { // New returns a new authorizer object. func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() client := &Client{ BaseURL: c.URL, @@ -69,7 +67,7 @@ func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, er return &authorizer{ client: client, providerIPs: sync.Map{}, - conf: c, + conf: &c, }, nil } @@ -81,7 +79,7 @@ type config struct { Insecure bool `mapstructure:"insecure" docs:"false;Whether to skip certificate checks when sending requests."` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.URL == "" { c.URL = "http://localhost:9600/mentix/cs3" } diff --git a/pkg/ocm/provider/authorizer/open/open.go b/pkg/ocm/provider/authorizer/open/open.go index a9f6feefd0..1a317678b8 100644 --- a/pkg/ocm/provider/authorizer/open/open.go +++ b/pkg/ocm/provider/authorizer/open/open.go @@ -28,8 +28,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/provider" "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -38,12 +37,10 @@ func init() { // New returns a new authorizer object. func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() f, err := os.ReadFile(c.Providers) if err != nil { @@ -66,7 +63,7 @@ type config struct { Providers string `mapstructure:"providers"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Providers == "" { c.Providers = "/etc/revad/ocm-providers.json" } diff --git a/pkg/ocm/share/repository/json/json.go b/pkg/ocm/share/repository/json/json.go index 5517999335..d8c9658239 100644 --- a/pkg/ocm/share/repository/json/json.go +++ b/pkg/ocm/share/repository/json/json.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/pkg/ocm/share" "github.com/cs3org/reva/pkg/ocm/share/repository/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/google/uuid" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -46,12 +46,10 @@ func init() { // New returns a new authorizer object. func New(ctx context.Context, m map[string]interface{}) (share.Repository, error) { - c, err := parseConfig(m) - if err != nil { - err = errors.Wrap(err, "error creating a new manager") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() // load or create file model, err := loadOrCreate(c.File) @@ -61,7 +59,7 @@ func New(ctx context.Context, m map[string]interface{}) (share.Repository, error } mgr := &mgr{ - c: c, + c: &c, model: model, } @@ -170,7 +168,7 @@ type config struct { File string `mapstructure:"file"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/ocm-shares.json" } @@ -217,14 +215,6 @@ func (m *mgr) load() error { return nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func genID() string { return uuid.New().String() } diff --git a/pkg/ocm/share/repository/nextcloud/nextcloud.go b/pkg/ocm/share/repository/nextcloud/nextcloud.go index 7fe1932069..1c87d9ca61 100644 --- a/pkg/ocm/share/repository/nextcloud/nextcloud.go +++ b/pkg/ocm/share/repository/nextcloud/nextcloud.go @@ -37,7 +37,7 @@ import ( "github.com/cs3org/reva/pkg/ocm/share" "github.com/cs3org/reva/pkg/ocm/share/repository/registry" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -94,27 +94,14 @@ type ReceivedShareAltMap struct { State ocm.ShareState `json:"state"` } -func (c *ShareManagerConfig) init() { -} - -func parseConfig(m map[string]interface{}) (*ShareManagerConfig, error) { - c := &ShareManagerConfig{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns a share manager implementation that verifies against a Nextcloud backend. func New(ctx context.Context, m map[string]interface{}) (share.Repository, error) { - c, err := parseConfig(m) - if err != nil { + var c ShareManagerConfig + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - return NewShareManager(c) + return NewShareManager(&c) } // NewShareManager returns a new Nextcloud-based ShareManager. diff --git a/pkg/ocm/share/repository/sql/sql.go b/pkg/ocm/share/repository/sql/sql.go index 980e08d55d..08a28ee323 100644 --- a/pkg/ocm/share/repository/sql/sql.go +++ b/pkg/ocm/share/repository/sql/sql.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/share" "github.com/cs3org/reva/pkg/ocm/share/repository/registry" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-sql-driver/mysql" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -45,12 +45,12 @@ func init() { } // New creates a Repository with a SQL driver. -func New(ctx context.Context, c map[string]interface{}) (share.Repository, error) { - conf, err := parseConfig(c) - if err != nil { +func New(ctx context.Context, m map[string]interface{}) (share.Repository, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - return NewFromConfig(ctx, conf) + return NewFromConfig(ctx, &c) } type mgr struct { @@ -87,14 +87,6 @@ type config struct { now func() time.Time // set only from tests } -func parseConfig(conf map[string]interface{}) (*config, error) { - var c config - if err := mapstructure.Decode(conf, &c); err != nil { - return nil, errors.Wrap(err, "error decoding config") - } - return &c, nil -} - func formatUserID(u *userpb.UserId) string { return fmt.Sprintf("%s@%s", u.OpaqueId, u.Idp) } diff --git a/pkg/ocm/storage/outcoming/ocm.go b/pkg/ocm/storage/outcoming/ocm.go index 50828f40b4..1ce9fecc34 100644 --- a/pkg/ocm/storage/outcoming/ocm.go +++ b/pkg/ocm/storage/outcoming/ocm.go @@ -42,7 +42,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "google.golang.org/grpc/metadata" ) @@ -61,31 +61,24 @@ type config struct { MachineSecret string `mapstructure:"machine_secret"` } -func parseConfig(c map[string]interface{}) (*config, error) { - var conf config - err := mapstructure.Decode(c, &conf) - return &conf, err -} - -func (c *config) init() { +func (c *config) ApplyDefaults() { c.GatewaySVC = sharedconf.GetGatewaySVC(c.GatewaySVC) } // New creates an OCM storage driver. -func New(ctx context.Context, c map[string]interface{}) (storage.FS, error) { - conf, err := parseConfig(c) - if err != nil { - return nil, errors.Wrapf(err, "error decoding config") +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } - conf.init() - gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySVC)) + gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySVC)) if err != nil { return nil, err } d := &driver{ - c: conf, + c: &c, gateway: gateway, } diff --git a/pkg/ocm/storage/received/ocm.go b/pkg/ocm/storage/received/ocm.go index 405f5ab2fc..2ebfaf2d7d 100644 --- a/pkg/ocm/storage/received/ocm.go +++ b/pkg/ocm/storage/received/ocm.go @@ -40,8 +40,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/studio-b12/gowebdav" ) @@ -55,34 +54,27 @@ type driver struct { } type config struct { - GatewaySVC string + GatewaySVC string `mapstructure:"gatewaysvc"` } -func parseConfig(c map[string]interface{}) (*config, error) { - var conf config - err := mapstructure.Decode(c, &conf) - return &conf, err -} - -func (c *config) init() { +func (c *config) ApplyDefaults() { c.GatewaySVC = sharedconf.GetGatewaySVC(c.GatewaySVC) } // New creates an OCM storage driver. -func New(ctx context.Context, c map[string]interface{}) (storage.FS, error) { - conf, err := parseConfig(c) - if err != nil { - return nil, errors.Wrapf(err, "error decoding config") +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err } - conf.init() - gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySVC)) + gateway, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySVC)) if err != nil { return nil, err } d := &driver{ - c: conf, + c: &c, gateway: gateway, } diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index b8a0a00195..060dca0aa9 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -38,7 +38,7 @@ import ( "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/publicshare/manager/registry" "github.com/cs3org/reva/pkg/utils" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "github.com/rs/zerolog/log" "golang.org/x/crypto/bcrypt" @@ -49,45 +49,43 @@ func init() { } // New returns a new filesystem public shares manager. -func New(ctx context.Context, c map[string]interface{}) (publicshare.Manager, error) { - conf := &config{} - if err := mapstructure.Decode(c, conf); err != nil { +func New(ctx context.Context, m map[string]interface{}) (publicshare.Manager, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - conf.init() - - m := manager{ + mgr := manager{ mutex: &sync.Mutex{}, - file: conf.File, - passwordHashCost: conf.SharePasswordHashCost, - janitorRunInterval: conf.JanitorRunInterval, - enableExpiredSharesCleanup: conf.EnableExpiredSharesCleanup, + file: c.File, + passwordHashCost: c.SharePasswordHashCost, + janitorRunInterval: c.JanitorRunInterval, + enableExpiredSharesCleanup: c.EnableExpiredSharesCleanup, } // attempt to create the db file var fi os.FileInfo var err error - if fi, err = os.Stat(m.file); os.IsNotExist(err) { - folder := filepath.Dir(m.file) + if fi, err = os.Stat(mgr.file); os.IsNotExist(err) { + folder := filepath.Dir(mgr.file) if err := os.MkdirAll(folder, 0755); err != nil { return nil, err } - if _, err := os.Create(m.file); err != nil { + if _, err := os.Create(mgr.file); err != nil { return nil, err } } if fi == nil || fi.Size() == 0 { - err := os.WriteFile(m.file, []byte("{}"), 0644) + err := os.WriteFile(mgr.file, []byte("{}"), 0644) if err != nil { return nil, err } } - go m.startJanitorRun() + go mgr.startJanitorRun() - return &m, nil + return &mgr, nil } type config struct { @@ -97,7 +95,7 @@ type config struct { EnableExpiredSharesCleanup bool `mapstructure:"enable_expired_shares_cleanup"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/publicshares" } diff --git a/pkg/rgrpc/rgrpc.go b/pkg/rgrpc/rgrpc.go index 96cf258fc1..f45e5a447f 100644 --- a/pkg/rgrpc/rgrpc.go +++ b/pkg/rgrpc/rgrpc.go @@ -101,7 +101,7 @@ func InitServices(ctx context.Context, services map[string]config.ServicesConfig ctx := appctx.WithLogger(ctx, &log) svc, err := new(ctx, cfg[0].Config) if err != nil { - return nil, errors.Wrapf(err, "rgrpc: grpc service %s could not be started,", name) + return nil, errors.Wrapf(err, "rgrpc: grpc service %s could not be started", name) } s[name] = svc } diff --git a/pkg/rserverless/rserverless.go b/pkg/rserverless/rserverless.go index c68f1d6142..606e833053 100644 --- a/pkg/rserverless/rserverless.go +++ b/pkg/rserverless/rserverless.go @@ -41,7 +41,7 @@ func Register(name string, newFunc NewService) { } // NewService is the function that serverless services need to register at init time. -type NewService func(conf map[string]interface{}, log *zerolog.Logger) (Service, error) +type NewService func(context.Context, map[string]interface{}) (Service, error) // Serverless contains the serveless collection of services. type Serverless struct { diff --git a/pkg/share/cache/memory/memory.go b/pkg/share/cache/memory/memory.go index f617b4df56..5766307121 100644 --- a/pkg/share/cache/memory/memory.go +++ b/pkg/share/cache/memory/memory.go @@ -25,8 +25,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/share/cache" "github.com/cs3org/reva/pkg/share/cache/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -41,16 +40,18 @@ type manager struct { cache gcache.Cache } -// New returns an implementation of a resource info cache that stores the objects in memory. -func New(m map[string]interface{}) (cache.ResourceInfoCache, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, errors.Wrap(err, "error decoding conf") - } +func (c *config) ApplyDefaults() { if c.CacheSize == 0 { c.CacheSize = 1000000 } +} +// New returns an implementation of a resource info cache that stores the objects in memory. +func New(m map[string]interface{}) (cache.ResourceInfoCache, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err + } return &manager{ cache: gcache.New(c.CacheSize).LFU().Build(), }, nil diff --git a/pkg/share/cache/redis/redis.go b/pkg/share/cache/redis/redis.go index 0703f98f07..886172e3d0 100644 --- a/pkg/share/cache/redis/redis.go +++ b/pkg/share/cache/redis/redis.go @@ -25,8 +25,8 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/share/cache" "github.com/cs3org/reva/pkg/share/cache/registry" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/gomodule/redigo/redis" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -44,16 +44,18 @@ type manager struct { redisPool *redis.Pool } -// New returns an implementation of a resource info cache that stores the objects in a redis cluster. -func New(m map[string]interface{}) (cache.ResourceInfoCache, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, errors.Wrap(err, "error decoding conf") - } - +func (c *config) ApplyDefaults() { if c.RedisAddress == "" { c.RedisAddress = "localhost:6379" } +} + +// New returns an implementation of a resource info cache that stores the objects in a redis cluster. +func New(m map[string]interface{}) (cache.ResourceInfoCache, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err + } pool := &redis.Pool{ MaxIdle: 50, diff --git a/pkg/share/manager/json/json.go b/pkg/share/manager/json/json.go index a301876e6b..a453b552cd 100644 --- a/pkg/share/manager/json/json.go +++ b/pkg/share/manager/json/json.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/google/uuid" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -46,14 +46,11 @@ func init() { // New returns a new mgr. func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { - c, err := parseConfig(m) - if err != nil { - err = errors.Wrap(err, "error creating a new manager") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - // load or create file model, err := loadOrCreate(c.File) if err != nil { @@ -62,7 +59,7 @@ func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { } return &mgr{ - c: c, + c: &c, model: model, }, nil } @@ -157,20 +154,12 @@ type config struct { File string `mapstructure:"file"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.File == "" { c.File = "/var/tmp/reva/shares.json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func genID() string { return uuid.New().String() } diff --git a/pkg/share/manager/sql/sql.go b/pkg/share/manager/sql/sql.go index 13300d80ef..984e0f6425 100644 --- a/pkg/share/manager/sql/sql.go +++ b/pkg/share/manager/sql/sql.go @@ -34,11 +34,12 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" + "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" // Provides mysql drivers. _ "github.com/go-sql-driver/mysql" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/genproto/protobuf/field_mask" ) @@ -53,7 +54,7 @@ func init() { } type config struct { - GatewayAddr string `mapstructure:"gateway_addr"` + GatewayAddr string `mapstructure:"gatewaysvc"` StorageMountID string `mapstructure:"storage_mount_id"` DBUsername string `mapstructure:"db_username"` DBPassword string `mapstructure:"db_password"` @@ -62,6 +63,10 @@ type config struct { DBName string `mapstructure:"db_name"` } +func (c *config) ApplyDefaults() { + c.GatewayAddr = sharedconf.GetGatewaySVC(c.GatewayAddr) +} + type mgr struct { driver string db *sql.DB @@ -71,9 +76,8 @@ type mgr struct { // NewMysql returns a new share manager connection to a mysql database. func NewMysql(ctx context.Context, m map[string]interface{}) (share.Manager, error) { - c, err := parseConfig(m) - if err != nil { - err = errors.Wrap(err, "error creating a new manager") + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -97,14 +101,6 @@ func New(driver string, db *sql.DB, storageMountID string, userConverter UserCon }, nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { user := ctxpkg.ContextMustGetUser(ctx) diff --git a/pkg/storage/fs/cback/cback.go b/pkg/storage/fs/cback/cback.go index 4c4607eaae..a9ceb153e4 100644 --- a/pkg/storage/fs/cback/cback.go +++ b/pkg/storage/fs/cback/cback.go @@ -35,8 +35,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) type cback struct { @@ -51,15 +50,15 @@ func init() { // New returns an implementation to the storage.FS interface that talks to // cback. func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err error) { - c := &Options{} - if err = mapstructure.Decode(m, c); err != nil { - return nil, errors.Wrap(err, "Error Decoding Configuration") + var o Options + if err := cfg.Decode(m, &o); err != nil { + return nil, err } httpClient := rhttp.GetHTTPClient() // Returns the storage.FS interface - return &cback{conf: c, client: httpClient}, nil + return &cback{conf: &o, client: httpClient}, nil } func (fs *cback) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { diff --git a/pkg/storage/fs/cephfs/cephfs.go b/pkg/storage/fs/cephfs/cephfs.go index 9132bab87b..e9e175aff4 100644 --- a/pkg/storage/fs/cephfs/cephfs.go +++ b/pkg/storage/fs/cephfs/cephfs.go @@ -37,7 +37,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -65,24 +65,22 @@ func init() { // New returns an implementation to of the storage.FS interface that talk to // a ceph filesystem. func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err error) { - c := &Options{} - if err = mapstructure.Decode(m, c); err != nil { - return nil, errors.Wrap(err, "error decoding conf") + var o Options + if err := cfg.Decode(m, &o); err != nil { + return nil, err } - c.fillDefaults() - var cache *connections if cache, err = newCache(); err != nil { return nil, errors.New("cephfs: can't create caches") } - adminConn := newAdminConn(c) + adminConn := newAdminConn(&o) if adminConn == nil { return nil, errors.Wrap(err, "cephfs: Couldn't create admin connections") } - for _, dir := range []string{c.ShadowFolder, c.UploadFolder} { + for _, dir := range []string{o.ShadowFolder, o.UploadFolder} { err = adminConn.adminMount.MakeDir(dir, dirPermFull) if err != nil && err.Error() != errFileExists { return nil, errors.New("cephfs: can't initialise system dir " + dir + ":" + err.Error()) @@ -90,7 +88,7 @@ func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err erro } return &cephfs{ - conf: c, + conf: &o, conn: cache, adminConn: adminConn, }, nil diff --git a/pkg/storage/fs/cephfs/options.go b/pkg/storage/fs/cephfs/options.go index 045dd93e29..03ae955055 100644 --- a/pkg/storage/fs/cephfs/options.go +++ b/pkg/storage/fs/cephfs/options.go @@ -47,7 +47,7 @@ type Options struct { HiddenDirs map[string]bool } -func (c *Options) fillDefaults() { +func (c *Options) ApplyDefaults() { c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) if c.IndexPool == "" { diff --git a/pkg/storage/fs/eos/eos.go b/pkg/storage/fs/eos/eos.go index 3847c66b6d..93e7cc1976 100644 --- a/pkg/storage/fs/eos/eos.go +++ b/pkg/storage/fs/eos/eos.go @@ -24,18 +24,17 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { registry.Register("eos", New) } -func parseConfig(m map[string]interface{}) (*eosfs.Config, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") +// New returns a new implementation of the storage.FS interface that connects to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -44,15 +43,5 @@ func parseConfig(m map[string]interface{}) (*eosfs.Config, error) { c.VersionInvariant = true } - return c, nil -} - -// New returns a new implementation of the storage.FS interface that connects to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err - } - - return eosfs.NewEOSFS(ctx, c) + return eosfs.NewEOSFS(ctx, &c) } diff --git a/pkg/storage/fs/eosgrpc/eosgrpc.go b/pkg/storage/fs/eosgrpc/eosgrpc.go index 3014335cb1..4582459d48 100644 --- a/pkg/storage/fs/eosgrpc/eosgrpc.go +++ b/pkg/storage/fs/eosgrpc/eosgrpc.go @@ -24,36 +24,25 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { registry.Register("eosgrpc", New) } -func parseConfig(m map[string]interface{}) (*eosfs.Config, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") +// New returns a new implementation of the storage.FS interface that connects to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } + c.UseGRPC = true // default to version invariance if not configured if _, ok := m["version_invariant"]; !ok { c.VersionInvariant = true } - return c, nil -} - -// New returns a new implementation of the storage.FS interface that connects to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err - } - c.UseGRPC = true - - return eosfs.NewEOSFS(ctx, c) + return eosfs.NewEOSFS(ctx, &c) } diff --git a/pkg/storage/fs/eosgrpchome/eosgrpchome.go b/pkg/storage/fs/eosgrpchome/eosgrpchome.go index 4b07e604fa..a68054bc58 100644 --- a/pkg/storage/fs/eosgrpchome/eosgrpchome.go +++ b/pkg/storage/fs/eosgrpchome/eosgrpchome.go @@ -24,37 +24,26 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { registry.Register("eosgrpchome", New) } -func parseConfig(m map[string]interface{}) (*eosfs.Config, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") +// New returns a new implementation of the storage.FS interface that connects to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } + c.UseGRPC = true + c.EnableHome = true // default to version invariance if not configured if _, ok := m["version_invariant"]; !ok { c.VersionInvariant = true } - return c, nil -} - -// New returns a new implementation of the storage.FS interface that connects to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err - } - c.UseGRPC = true - c.EnableHome = true - - return eosfs.NewEOSFS(ctx, c) + return eosfs.NewEOSFS(ctx, &c) } diff --git a/pkg/storage/fs/eoshome/eoshome.go b/pkg/storage/fs/eoshome/eoshome.go index 6fcf4abe21..cc4df2550b 100644 --- a/pkg/storage/fs/eoshome/eoshome.go +++ b/pkg/storage/fs/eoshome/eoshome.go @@ -24,36 +24,25 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/eosfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { registry.Register("eoshome", New) } -func parseConfig(m map[string]interface{}) (*eosfs.Config, error) { - c := &eosfs.Config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") +// New returns a new implementation of the storage.FS interface that connects to EOS. +func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { + var c eosfs.Config + if err := cfg.Decode(m, &c); err != nil { return nil, err } + c.EnableHome = true // default to version invariance if not configured if _, ok := m["version_invariant"]; !ok { c.VersionInvariant = true } - return c, nil -} - -// New returns a new implementation of the storage.FS interface that connects to EOS. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { - return nil, err - } - c.EnableHome = true - - return eosfs.NewEOSFS(ctx, c) + return eosfs.NewEOSFS(ctx, &c) } diff --git a/pkg/storage/fs/local/local.go b/pkg/storage/fs/local/local.go index a5b42cd241..7ecbd04d1d 100644 --- a/pkg/storage/fs/local/local.go +++ b/pkg/storage/fs/local/local.go @@ -24,8 +24,7 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/localfs" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "github.com/cs3org/reva/pkg/utils/cfg" ) func init() { @@ -37,20 +36,20 @@ type config struct { ShareFolder string `mapstructure:"share_folder" docs:"/MyShares;Path for storing share references."` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err +func (c *config) ApplyDefaults() { + if c.Root == "" { + c.Root = "/var/tmp/reva" + } + if c.ShareFolder == "" { + c.ShareFolder = "/MyShares" } - return c, nil } // New returns an implementation to of the storage.FS interface that talks to // a local filesystem with user homes disabled. func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } diff --git a/pkg/storage/fs/localhome/localhome.go b/pkg/storage/fs/localhome/localhome.go index 24cb3ffa1b..f57534c2df 100644 --- a/pkg/storage/fs/localhome/localhome.go +++ b/pkg/storage/fs/localhome/localhome.go @@ -38,6 +38,18 @@ type config struct { UserLayout string `mapstructure:"user_layout" docs:"{{.Username}};Template for user home directories"` } +func (c *config) ApplyDefaults() { + if c.Root == "" { + c.Root = "/var/tmp/reva" + } + if c.ShareFolder == "" { + c.ShareFolder = "/MyShares" + } + if c.UserLayout == "" { + c.UserLayout = "{{.Username}}" + } +} + func parseConfig(m map[string]interface{}) (*config, error) { c := &config{} if err := mapstructure.Decode(m, c); err != nil { diff --git a/pkg/storage/fs/nextcloud/nextcloud.go b/pkg/storage/fs/nextcloud/nextcloud.go index 00cda53858..d67663cd73 100644 --- a/pkg/storage/fs/nextcloud/nextcloud.go +++ b/pkg/storage/fs/nextcloud/nextcloud.go @@ -35,7 +35,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -58,24 +58,14 @@ type StorageDriver struct { client *http.Client } -func parseConfig(m map[string]interface{}) (*StorageDriverConfig, error) { - c := &StorageDriverConfig{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns an implementation to of the storage.FS interface that talks to // a Nextcloud instance over http. func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - conf, err := parseConfig(m) - if err != nil { + var c StorageDriverConfig + if err := cfg.Decode(m, &c); err != nil { return nil, err } - - return NewStorageDriver(conf) + return NewStorageDriver(&c) } // NewStorageDriver returns a new NextcloudStorageDriver. diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index 336109c72b..eb23d12257 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -49,9 +49,9 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/ace" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/templates" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/gomodule/redigo/redis" "github.com/google/uuid" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/pkg/xattr" ) @@ -120,16 +120,7 @@ type config struct { UserProviderEndpoint string `mapstructure:"userprovidersvc"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - -func (c *config) init(m map[string]interface{}) { +func (c *config) ApplyDefaults() { if c.Redis == "" { c.Redis = ":6379" } @@ -149,27 +140,27 @@ func (c *config) init(m map[string]interface{}) { // ensure share folder always starts with slash c.ShareFolder = filepath.Join("/", c.ShareFolder) - // default to scanning if not configured - if _, ok := m["scan"]; !ok { + if !c.Scan { + // TODO: check if it was set in the config c.Scan = true } + c.UserProviderEndpoint = sharedconf.GetGatewaySVC(c.UserProviderEndpoint) } // New returns an implementation to of the storage.FS interface that talk to // a local filesystem. func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init(m) // c.DataDirectory should never end in / unless it is the root? c.DataDirectory = filepath.Clean(c.DataDirectory) // create datadir if it does not exist - err = os.MkdirAll(c.DataDirectory, 0700) + err := os.MkdirAll(c.DataDirectory, 0700) if err != nil { logger.New().Error().Err(err). Str("path", c.DataDirectory). @@ -203,7 +194,7 @@ func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { } return &ocfs{ - c: c, + c: &c, pool: pool, chunkHandler: chunking.NewChunkHandler(c.UploadInfoDir), }, nil diff --git a/pkg/storage/fs/owncloudsql/owncloudsql.go b/pkg/storage/fs/owncloudsql/owncloudsql.go index dfbb051a84..03d410a90c 100644 --- a/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -54,7 +54,7 @@ import ( "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/templates" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" "github.com/pkg/xattr" "github.com/rs/zerolog/log" @@ -120,16 +120,7 @@ type config struct { DBName string `mapstructure:"dbname"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - -func (c *config) init(m map[string]interface{}) { +func (c *config) ApplyDefaults() { if c.UserLayout == "" { c.UserLayout = "{{.Username}}" } @@ -152,17 +143,16 @@ func (c *config) init(m map[string]interface{}) { // New returns an implementation to of the storage.FS interface that talk to // a local filesystem. func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init(m) // c.DataDirectory should never end in / unless it is the root? c.DataDirectory = filepath.Clean(c.DataDirectory) // create datadir if it does not exist - err = os.MkdirAll(c.DataDirectory, 0700) + err := os.MkdirAll(c.DataDirectory, 0700) if err != nil { logger.New().Error().Err(err). Str("path", c.DataDirectory). @@ -183,7 +173,7 @@ func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { } return &owncloudsqlfs{ - c: c, + c: &c, chunkHandler: chunking.NewChunkHandler(c.UploadInfoDir), filecache: filecache, }, nil diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go index 6783a7cdba..3b4983ee3b 100644 --- a/pkg/storage/fs/s3/s3.go +++ b/pkg/storage/fs/s3/s3.go @@ -41,7 +41,7 @@ import ( "github.com/cs3org/reva/pkg/mime" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -58,20 +58,11 @@ type config struct { Prefix string `mapstructure:"prefix"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - // New returns an implementation to of the storage.FS interface that talk to // a s3 api. func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } @@ -102,7 +93,7 @@ func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { s3Client := s3.New(sess) - return &s3FS{client: s3Client, config: c}, nil + return &s3FS{client: s3Client, config: &c}, nil } func (fs *s3FS) Shutdown(ctx context.Context) error { diff --git a/pkg/storage/registry/static/static.go b/pkg/storage/registry/static/static.go index 70382c1808..cef0ec69b1 100644 --- a/pkg/storage/registry/static/static.go +++ b/pkg/storage/registry/static/static.go @@ -32,7 +32,7 @@ import ( "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/registry/registry" "github.com/cs3org/reva/pkg/storage/utils/templates" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -53,7 +53,7 @@ type config struct { HomeProvider string `mapstructure:"home_provider"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.HomeProvider == "" { c.HomeProvider = "/" } @@ -70,23 +70,14 @@ func (c *config) init() { } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - return nil, err - } - return c, nil -} - // New returns an implementation of the storage.Registry interface that // redirects requests to corresponding storage drivers. func New(ctx context.Context, m map[string]interface{}) (storage.Registry, error) { - c, err := parseConfig(m) - if err != nil { + var c config + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - return ®{c: c}, nil + return ®{c: &c}, nil } type reg struct { diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 967ccb3893..7e9201e655 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -84,7 +84,7 @@ const LockTypeKey = "reva.lock.type" var hiddenReg = regexp.MustCompile(`\.sys\..#.`) -func (c *Config) init() { +func (c *Config) ApplyDefaults() { c.Namespace = path.Clean(c.Namespace) if !strings.HasPrefix(c.Namespace, "/") { c.Namespace = "/" @@ -162,7 +162,7 @@ type eosfs struct { // NewEOSFS returns a storage.FS interface implementation that connects to an EOS instance. func NewEOSFS(ctx context.Context, c *Config) (storage.FS, error) { - c.init() + c.ApplyDefaults() // bail out if keytab is not found. if c.UseKeytab { diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index d6d00b8655..22dcaecaeb 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -62,7 +62,7 @@ type Config struct { References string `mapstructure:"references"` } -func (c *Config) init() { +func (c *Config) ApplyDefaults() { if c.Root == "" { c.Root = "/var/tmp/reva" } @@ -100,7 +100,7 @@ type localfs struct { // NewLocalFS returns a storage.FS interface implementation that controls then // local filesystem. func NewLocalFS(c *Config) (storage.FS, error) { - c.init() + c.ApplyDefaults() // create namespaces if they do not exist namespaces := []string{c.DataDirectory, c.Uploads, c.Shadow, c.References, c.RecycleBin, c.Versions} diff --git a/pkg/token/manager/jwt/jwt.go b/pkg/token/manager/jwt/jwt.go index f9d7ed2b88..5429e813cd 100644 --- a/pkg/token/manager/jwt/jwt.go +++ b/pkg/token/manager/jwt/jwt.go @@ -28,8 +28,8 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/registry" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/golang-jwt/jwt" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -56,34 +56,27 @@ type claims struct { Scope map[string]*auth.Scope `json:"scope"` } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - return c, nil -} - -// New returns an implementation of the token manager that uses JWT as tokens. -func New(value map[string]interface{}) (token.Manager, error) { - c, err := parseConfig(value) - if err != nil { - return nil, errors.Wrap(err, "error parsing config") - } - +func (c *config) ApplyDefaults() { if c.Expires == 0 { c.Expires = defaultExpiration } c.Secret = sharedconf.GetJWTSecret(c.Secret) +} + +// New returns an implementation of the token manager that uses JWT as tokens. +func New(m map[string]interface{}) (token.Manager, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err + } if c.Secret == "" { return nil, errors.New("jwt: secret for signing payloads is not defined in config") } - m := &manager{conf: c} - return m, nil + mgr := &manager{conf: &c} + return mgr, nil } func (m *manager) MintToken(ctx context.Context, u *user.User, scope map[string]*auth.Scope) (string, error) { diff --git a/pkg/user/manager/json/json.go b/pkg/user/manager/json/json.go index 642fa038e4..76c08cd576 100644 --- a/pkg/user/manager/json/json.go +++ b/pkg/user/manager/json/json.go @@ -29,7 +29,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -46,22 +46,12 @@ type config struct { Users string `mapstructure:"users"` } -func (c *config) init() { +func (c *config) ApplyDefaults() { if c.Users == "" { c.Users = "/etc/revad/users.json" } } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - // New returns a user manager implementation that reads a json file to provide user metadata. func New(_ context.Context, m map[string]interface{}) (user.Manager, error) { mgr := &manager{} @@ -73,8 +63,8 @@ func New(_ context.Context, m map[string]interface{}) (user.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { + var c config + if err := cfg.Decode(ml, &c); err != nil { return err } diff --git a/pkg/user/manager/ldap/ldap.go b/pkg/user/manager/ldap/ldap.go index 7d684a7991..b19fbce85c 100644 --- a/pkg/user/manager/ldap/ldap.go +++ b/pkg/user/manager/ldap/ldap.go @@ -33,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-ldap/ldap/v3" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -100,6 +101,19 @@ func parseConfig(m map[string]interface{}) (*config, error) { return &c, nil } +func (c *config) ApplyDefaults() { + // backwards compatibility + c.UserFilter = strings.ReplaceAll(c.UserFilter, "%s", "{{.OpaqueId}}") + if c.FindFilter == "" { + c.FindFilter = c.UserFilter + } + c.GroupFilter = strings.ReplaceAll(c.GroupFilter, "%s", "{{.OpaqueId}}") + + if c.Nobody == 0 { + c.Nobody = 99 + } +} + // New returns a user manager implementation that connects to a LDAP server to provide user metadata. func New(ctx context.Context, m map[string]interface{}) (user.Manager, error) { mgr := &manager{} @@ -111,23 +125,14 @@ func New(ctx context.Context, m map[string]interface{}) (user.Manager, error) { } func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { + var c config + c.Schema = ldapDefaults + if err := cfg.Decode(ml, &c); err != nil { return err } - // backwards compatibility - c.UserFilter = strings.ReplaceAll(c.UserFilter, "%s", "{{.OpaqueId}}") - if c.FindFilter == "" { - c.FindFilter = c.UserFilter - } - c.GroupFilter = strings.ReplaceAll(c.GroupFilter, "%s", "{{.OpaqueId}}") - - if c.Nobody == 0 { - c.Nobody = 99 - } - - m.c = c + m.c = &c + var err error m.userfilter, err = template.New("uf").Funcs(sprig.TxtFuncMap()).Parse(c.UserFilter) if err != nil { err := errors.Wrap(err, fmt.Sprintf("error parsing userfilter tpl:%s", c.UserFilter)) diff --git a/pkg/user/manager/nextcloud/nextcloud.go b/pkg/user/manager/nextcloud/nextcloud.go index 274e02b18c..887892b7f4 100644 --- a/pkg/user/manager/nextcloud/nextcloud.go +++ b/pkg/user/manager/nextcloud/nextcloud.go @@ -32,7 +32,7 @@ import ( "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" - "github.com/mitchellh/mapstructure" + "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" // "github.com/cs3org/reva/pkg/errtypes". ) @@ -56,22 +56,12 @@ type UserManagerConfig struct { MockHTTP bool `mapstructure:"mock_http"` } -func (c *UserManagerConfig) init() { +func (c *UserManagerConfig) ApplyDefaults() { if c.EndPoint == "" { c.EndPoint = "http://localhost/end/point?" } } -func parseConfig(m map[string]interface{}) (*UserManagerConfig, error) { - c := &UserManagerConfig{} - if err := mapstructure.Decode(m, c); err != nil { - err = errors.Wrap(err, "error decoding conf") - return nil, err - } - c.init() - return c, nil -} - // Action describes a REST request to forward to the Nextcloud backend. type Action struct { verb string @@ -80,13 +70,12 @@ type Action struct { // New returns a user manager implementation that reads a json file to provide user metadata. func New(ctx context.Context, m map[string]interface{}) (user.Manager, error) { - c, err := parseConfig(m) - if err != nil { + var c UserManagerConfig + if err := cfg.Decode(m, &c); err != nil { return nil, err } - c.init() - return NewUserManager(c) + return NewUserManager(&c) } // NewUserManager returns a new Nextcloud-based UserManager. diff --git a/pkg/user/manager/owncloudsql/owncloudsql.go b/pkg/user/manager/owncloudsql/owncloudsql.go index 666119ea7b..2bd9399cf8 100644 --- a/pkg/user/manager/owncloudsql/owncloudsql.go +++ b/pkg/user/manager/owncloudsql/owncloudsql.go @@ -29,10 +29,10 @@ import ( "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/owncloudsql/accounts" "github.com/cs3org/reva/pkg/user/manager/registry" + "github.com/cs3org/reva/pkg/utils/cfg" // Provides mysql drivers. _ "github.com/go-sql-driver/mysql" - "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -80,26 +80,20 @@ func NewMysql(ctx context.Context, m map[string]interface{}) (user.Manager, erro return mgr, nil } -func (m *manager) Configure(ml map[string]interface{}) error { - c, err := parseConfig(ml) - if err != nil { - return err - } - +func (c *config) ApplyDefaults() { if c.Nobody == 0 { c.Nobody = 99 } - - m.c = c - return nil } -func parseConfig(m map[string]interface{}) (*config, error) { - c := &config{} - if err := mapstructure.Decode(m, &c); err != nil { - return nil, err +func (m *manager) Configure(ml map[string]interface{}) error { + var c config + if err := cfg.Decode(ml, &c); err != nil { + return err } - return c, nil + + m.c = &c + return nil } func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) { diff --git a/pkg/utils/cfg/cfg.go b/pkg/utils/cfg/cfg.go new file mode 100644 index 0000000000..274cfb53c3 --- /dev/null +++ b/pkg/utils/cfg/cfg.go @@ -0,0 +1,90 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cfg + +import ( + "errors" + "reflect" + + "github.com/cs3org/reva/pkg/errtypes" + "github.com/go-playground/locales/en" + ut "github.com/go-playground/universal-translator" + "github.com/go-playground/validator/v10" + en_translations "github.com/go-playground/validator/v10/translations/en" + "github.com/mitchellh/mapstructure" +) + +// Setter is the interface a configuration struct may implement +// to set the default options. +type Setter interface { + // ApplyDefaults applies the default options. + ApplyDefaults() +} + +var validate = validator.New() +var english = en.New() +var uni = ut.New(english, english) +var trans, _ = uni.GetTranslator("en") +var _ = en_translations.RegisterDefaultTranslations(validate, trans) + +func init() { + validate.RegisterTagNameFunc(func(field reflect.StructField) string { + if k := field.Tag.Get("mapstructure"); k != "" { + return k + } + // if not specified, fall back to field name + return field.Name + }) +} + +// Decode decodes the given raw input interface to the target pointer c. +// It applies the default configuration if the target struct +// implements the Setter interface. +// It also perform a validation to all the fields of the configuration. +func Decode(input map[string]any, c any) error { + config := &mapstructure.DecoderConfig{ + Metadata: nil, + Result: c, + } + + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return err + } + if err := decoder.Decode(input); err != nil { + return err + } + if s, ok := c.(Setter); ok { + s.ApplyDefaults() + } + + return translateError(validate.Struct(c), trans) +} + +func translateError(err error, trans ut.Translator) error { + if err == nil { + return nil + } + errs := err.(validator.ValidationErrors) + translated := make([]error, 0, len(errs)) + for _, err := range errs { + translated = append(translated, errors.New(err.Translate(trans))) + } + return errtypes.Join(translated...) +} diff --git a/pkg/utils/cfg/cfg_test.go b/pkg/utils/cfg/cfg_test.go new file mode 100644 index 0000000000..2e74f2936d --- /dev/null +++ b/pkg/utils/cfg/cfg_test.go @@ -0,0 +1,79 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cfg_test + +import ( + "testing" + + "github.com/cs3org/reva/pkg/utils/cfg" + "github.com/stretchr/testify/assert" +) + +type NoDefaults struct { + A string `mapstructure:"a"` + B int `mapstructure:"b"` + C bool `mapstructure:"c"` +} + +type WithDefaults struct { + A string `mapstructure:"a"` + B int `mapstructure:"b" validate:"required"` +} + +func (c *WithDefaults) ApplyDefaults() { + if c.A == "" { + c.A = "default" + } +} + +func TestDecode(t *testing.T) { + t1 := map[string]any{ + "b": 10, + "c": true, + } + var noDefaults NoDefaults + if err := cfg.Decode(t1, &noDefaults); err != nil { + t.Fatal("not expected error", err) + } + assert.Equal(t, NoDefaults{ + A: "", + B: 10, + C: true, + }, noDefaults) + + t2 := map[string]any{ + "b": 100, + } + var defaults WithDefaults + if err := cfg.Decode(t2, &defaults); err != nil { + t.Fatal("not expected error", err) + } + assert.Equal(t, WithDefaults{ + A: "default", + B: 100, + }, defaults) + + t3 := map[string]any{ + "a": "string", + } + var required WithDefaults + if err := cfg.Decode(t3, &required); err == nil { + t.Fatal("expected error, but none returned") + } +} diff --git a/tests/integration/grpc/fixtures/ocm-server-cernbox-http.toml b/tests/integration/grpc/fixtures/ocm-server-cernbox-http.toml index 622974dcb3..ed9d667478 100644 --- a/tests/integration/grpc/fixtures/ocm-server-cernbox-http.toml +++ b/tests/integration/grpc/fixtures/ocm-server-cernbox-http.toml @@ -12,6 +12,7 @@ address = "{{grpc_address}}" [http.services.sciencemesh] provider_domain = "{{cernboxhttp_address}}" mesh_directory_url = "http://meshdir" +smtp_credentials = {} [http.middlewares.cors] diff --git a/tests/integration/grpc/fixtures/ocm-server-cesnet-http.toml b/tests/integration/grpc/fixtures/ocm-server-cesnet-http.toml index 93690ec5f4..a4ee3efa9a 100644 --- a/tests/integration/grpc/fixtures/ocm-server-cesnet-http.toml +++ b/tests/integration/grpc/fixtures/ocm-server-cesnet-http.toml @@ -12,6 +12,7 @@ address = "{{grpc_address}}" [http.services.sciencemesh] provider_domain = "{{cesnethttp_address}}" mesh_directory_url = "http://meshdir" +smtp_credentials = {} [http.middlewares.cors] diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml index 49fc9b7bb8..c2c077b74c 100644 --- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml +++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-grpc.toml @@ -58,6 +58,7 @@ providers = "{{file_providers}}" [grpc.services.ocmshareprovider] driver = "json" webdav_endpoint = "http://{{cernboxwebdav_address}}" +provider_domain = "cernbox.cern.ch" [grpc.services.ocmshareprovider.drivers.json] file = "{{ocm_share_cernbox_file}}" diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-http.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-http.toml index 95a6f7dec5..03a8a0b89b 100644 --- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-http.toml +++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cernbox-http.toml @@ -12,6 +12,7 @@ address = "{{grpc_address}}" [http.services.sciencemesh] provider_domain = "{{cernboxhttp_address}}" mesh_directory_url = "http://meshdir" +smtp_credentials = {} [http.middlewares.cors] diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml index edd7e950f6..3a225319ab 100644 --- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml +++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-grpc.toml @@ -37,6 +37,8 @@ providers = "{{file_providers}}" [grpc.services.ocmshareprovider] driver = "json" +webdav_endpoint = "http://{{cesnethttp_address}}" +provider_domain = "cesnet.cz" [grpc.services.ocmshareprovider.drivers.json] file = "{{ocm_share_cesnet_file}}" diff --git a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-http.toml b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-http.toml index 11ade22fe3..6a12f8eb99 100644 --- a/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-http.toml +++ b/tests/integration/grpc/fixtures/ocm-share/ocm-server-cesnet-http.toml @@ -12,6 +12,7 @@ address = "{{grpc_address}}" [http.services.sciencemesh] provider_domain = "{{cesnethttp_address}}" mesh_directory_url = "http://meshdir" +smtp_credentials = {} [http.middlewares.cors] diff --git a/tests/integration/grpc/ocm_invitation_test.go b/tests/integration/grpc/ocm_invitation_test.go index be47dcce89..c4addc6c79 100644 --- a/tests/integration/grpc/ocm_invitation_test.go +++ b/tests/integration/grpc/ocm_invitation_test.go @@ -124,7 +124,7 @@ var _ = Describe("ocm invitation workflow", func() { } ) - for _, driver := range []string{"json", "sql"} { + for _, driver := range []string{"json"} { JustBeforeEach(func() { tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"})