diff --git a/changelog/unreleased/app-registry-refactor.md b/changelog/unreleased/app-registry-refactor.md new file mode 100644 index 00000000000..bc3eaa842f3 --- /dev/null +++ b/changelog/unreleased/app-registry-refactor.md @@ -0,0 +1,5 @@ +Enhancement: Extend app registry with AddProvider method and mimetype filters + +https://github.com/cs3org/reva/pull/1785 +https://github.com/cs3org/cs3apis/pull/131 +https://github.com/cs3org/reva/issues/1779 diff --git a/cmd/revad/runtime/loader.go b/cmd/revad/runtime/loader.go index 0b90f93a6a0..ba169a1d923 100644 --- a/cmd/revad/runtime/loader.go +++ b/cmd/revad/runtime/loader.go @@ -27,6 +27,7 @@ import ( _ "github.com/cs3org/reva/internal/http/interceptors/auth/tokenwriter/loader" _ "github.com/cs3org/reva/internal/http/interceptors/loader" _ "github.com/cs3org/reva/internal/http/services/loader" + _ "github.com/cs3org/reva/pkg/app/provider/loader" _ "github.com/cs3org/reva/pkg/appauth/manager/loader" _ "github.com/cs3org/reva/pkg/auth/manager/loader" _ "github.com/cs3org/reva/pkg/auth/registry/loader" diff --git a/go.mod b/go.mod index ec3e3ac1ae7..e41875fb617 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,8 @@ require ( go 1.16 replace ( + //github.com/cs3org/go-cs3apis => ../cs3apis/build/go-cs3apis + github.com/cs3org/go-cs3apis => github.com/ishank011/go-cs3apis v0.0.0-20210611101519-1497ab8e8312 github.com/eventials/go-tus => github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1 google.golang.org/grpc => google.golang.org/grpc v1.26.0 // temporary downgrade diff --git a/go.sum b/go.sum index bd5c4f2a03a..a9a90abb409 100644 --- a/go.sum +++ b/go.sum @@ -150,8 +150,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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-20210527092509-2b828e94ed4c h1:EaKDtDswzfWUr70xoN63sPLZyvdinkmXrjqc5AFhVZE= -github.com/cs3org/go-cs3apis v0.0.0-20210527092509-2b828e94ed4c/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cucumber/godog v0.8.1/go.mod h1:vSh3r/lM+psC1BPXvdkSEuNjmXfpVqrMGYAElF6hxnA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -667,6 +665,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/inhies/go-bytesize v0.0.0-20201103132853-d0aed0d254f8/go.mod h1:KrtyD5PFj++GKkFS/7/RRrfnRhAMGQwy75GLCHWrCNs= +github.com/ishank011/go-cs3apis v0.0.0-20210611101519-1497ab8e8312 h1:7RPGG8ZaTLQhY9cSj8+OkmSK3ZyZCAHp9Naao3zrXBg= +github.com/ishank011/go-cs3apis v0.0.0-20210611101519-1497ab8e8312/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= diff --git a/internal/grpc/services/appprovider/appprovider.go b/internal/grpc/services/appprovider/appprovider.go index b7545f7927e..06e41bb7cfd 100644 --- a/internal/grpc/services/appprovider/appprovider.go +++ b/internal/grpc/services/appprovider/appprovider.go @@ -33,7 +33,7 @@ import ( providerpb "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1" "github.com/cs3org/reva/pkg/app" - "github.com/cs3org/reva/pkg/app/provider/demo" + "github.com/cs3org/reva/pkg/app/provider/registry" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc" @@ -55,11 +55,26 @@ type service struct { } type config struct { - Driver string `mapstructure:"driver"` - Demo map[string]interface{} `mapstructure:"demo"` - IopSecret string `mapstructure:"iopsecret" docs:";The iopsecret used to connect to the wopiserver."` - WopiURL string `mapstructure:"wopiurl" docs:";The wopiserver's URL."` - WopiBrURL string `mapstructure:"wopibridgeurl" docs:";The wopibridge's URL."` + Driver string `mapstructure:"driver"` + Drivers map[string]map[string]interface{} `mapstructure:"drivers"` + IopSecret string `mapstructure:"iopsecret" docs:";The iopsecret used to connect to the wopiserver."` + WopiURL string `mapstructure:"wopiurl" docs:";The wopiserver's URL."` + WopiBrURL string `mapstructure:"wopibridgeurl" docs:";The wopibridge's URL."` +} + +func (c *config) init() { + if c.Driver == "" { + c.Driver = "demo" + } +} + +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 @@ -85,14 +100,6 @@ func New(m map[string]interface{}, ss *grpc.Server) (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 (s *service) Close() error { return nil } @@ -106,12 +113,10 @@ func (s *service) Register(ss *grpc.Server) { } func getProvider(c *config) (app.Provider, error) { - switch c.Driver { - case "demo": - return demo.New(c.Demo) - default: - return nil, errtypes.NotFound("driver not found: " + c.Driver) + if f, ok := registry.NewFuncs[c.Driver]; ok { + return f(c.Drivers[c.Driver]) } + return nil, errtypes.NotFound("driver not found: " + c.Driver) } func (s *service) getWopiAppEndpoints(ctx context.Context) (map[string]interface{}, error) { diff --git a/internal/grpc/services/appprovider/appprovider_test.go b/internal/grpc/services/appprovider/appprovider_test.go index 14b83d0d7c0..8950a20a1ba 100644 --- a/internal/grpc/services/appprovider/appprovider_test.go +++ b/internal/grpc/services/appprovider/appprovider_test.go @@ -37,13 +37,13 @@ func Test_parseConfig(t *testing.T) { name: "all configurations set", m: map[string]interface{}{ "Driver": "demo", - "Demo": map[string]interface{}{"a": "b", "c": "d"}, + "Drivers": map[string]map[string]interface{}{"demo": map[string]interface{}{"a": "b", "c": "d"}}, "IopSecret": "very-secret", "WopiURL": "https://my.wopi:9871", }, want: &config{ Driver: "demo", - Demo: map[string]interface{}{"a": "b", "c": "d"}, + Drivers: map[string]map[string]interface{}{"demo": map[string]interface{}{"a": "b", "c": "d"}}, IopSecret: "very-secret", WopiURL: "https://my.wopi:9871", }, @@ -64,8 +64,8 @@ func Test_parseConfig(t *testing.T) { name: "undefined settings type", m: map[string]interface{}{"Not-Defined": 123}, want: &config{ - Driver: "", - Demo: map[string]interface{}(nil), + Driver: "demo", + Drivers: map[string]map[string]interface{}(nil), IopSecret: "", WopiURL: "", }, diff --git a/internal/grpc/services/appregistry/appregistry.go b/internal/grpc/services/appregistry/appregistry.go index 3f2f99db6cd..93ba74382c5 100644 --- a/internal/grpc/services/appregistry/appregistry.go +++ b/internal/grpc/services/appregistry/appregistry.go @@ -102,25 +102,26 @@ func (s *svc) GetAppProviders(ctx context.Context, req *registrypb.GetAppProvide }, nil } - provider := format(p) res := ®istrypb.GetAppProvidersResponse{ Status: status.NewOK(ctx), - Providers: []*registrypb.ProviderInfo{provider}, + Providers: []*registrypb.ProviderInfo{p}, } return res, nil } +func (s *svc) AddAppProvider(ctx context.Context, req *registrypb.AddAppProviderRequest) (*registrypb.AddAppProviderResponse, error) { + return ®istrypb.AddAppProviderResponse{ + Status: status.NewUnimplemented(ctx, errtypes.NotSupported("AddAppProvider not implemented"), "AddAppProvider not implemented"), + }, nil +} + func (s *svc) ListAppProviders(ctx context.Context, req *registrypb.ListAppProvidersRequest) (*registrypb.ListAppProvidersResponse, error) { - pvds, err := s.registry.ListProviders(ctx) + providers, err := s.registry.ListProviders(ctx) if err != nil { return ®istrypb.ListAppProvidersResponse{ Status: status.NewInternal(ctx, err, "error listing the app providers"), }, nil } - providers := make([]*registrypb.ProviderInfo, 0, len(pvds)) - for _, pvd := range pvds { - providers = append(providers, format(pvd)) - } res := ®istrypb.ListAppProvidersResponse{ Status: status.NewOK(ctx), @@ -129,8 +130,14 @@ func (s *svc) ListAppProviders(ctx context.Context, req *registrypb.ListAppProvi return res, nil } -func format(p *app.ProviderInfo) *registrypb.ProviderInfo { - return ®istrypb.ProviderInfo{ - Address: p.Location, - } +func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registrypb.GetDefaultAppProviderForMimeTypeRequest) (*registrypb.GetDefaultAppProviderForMimeTypeResponse, error) { + return ®istrypb.GetDefaultAppProviderForMimeTypeResponse{ + Status: status.NewUnimplemented(ctx, errtypes.NotSupported("GetDefaultAppProviderForMimeType not implemented"), "GetDefaultAppProviderForMimeType not implemented"), + }, nil +} + +func (s *svc) SetDefaultAppProviderForMimeType(ctx context.Context, req *registrypb.SetDefaultAppProviderForMimeTypeRequest) (*registrypb.SetDefaultAppProviderForMimeTypeResponse, error) { + return ®istrypb.SetDefaultAppProviderForMimeTypeResponse{ + Status: status.NewUnimplemented(ctx, errtypes.NotSupported("SetDefaultAppProviderForMimeType not implemented"), "SetDefaultAppProviderForMimeType not implemented"), + }, nil } diff --git a/internal/grpc/services/gateway/appregistry.go b/internal/grpc/services/gateway/appregistry.go index a02f18f9de7..d08dcd2dc7d 100644 --- a/internal/grpc/services/gateway/appregistry.go +++ b/internal/grpc/services/gateway/appregistry.go @@ -38,7 +38,24 @@ func (s *svc) GetAppProviders(ctx context.Context, req *registry.GetAppProviders res, err := c.GetAppProviders(ctx, req) if err != nil { - return nil, errors.Wrap(err, "gateway: error calling ListShares") + return nil, errors.Wrap(err, "gateway: error calling GetAppProviders") + } + + return res, nil +} + +func (s *svc) AddAppProvider(ctx context.Context, req *registry.AddAppProviderRequest) (*registry.AddAppProviderResponse, error) { + c, err := pool.GetAppRegistryClient(s.c.AppRegistryEndpoint) + if err != nil { + err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") + return ®istry.AddAppProviderResponse{ + Status: status.NewInternal(ctx, err, "error getting user share provider client"), + }, nil + } + + res, err := c.AddAppProvider(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "gateway: error calling AddAppProvider") } return res, nil @@ -55,7 +72,41 @@ func (s *svc) ListAppProviders(ctx context.Context, req *registry.ListAppProvide res, err := c.ListAppProviders(ctx, req) if err != nil { - return nil, errors.Wrap(err, "gateway: error calling ListShares") + return nil, errors.Wrap(err, "gateway: error calling ListAppProviders") + } + + return res, nil +} + +func (s *svc) GetDefaultAppProviderForMimeType(ctx context.Context, req *registry.GetDefaultAppProviderForMimeTypeRequest) (*registry.GetDefaultAppProviderForMimeTypeResponse, error) { + c, err := pool.GetAppRegistryClient(s.c.AppRegistryEndpoint) + if err != nil { + err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") + return ®istry.GetDefaultAppProviderForMimeTypeResponse{ + Status: status.NewInternal(ctx, err, "error getting user share provider client"), + }, nil + } + + res, err := c.GetDefaultAppProviderForMimeType(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "gateway: error calling GetDefaultAppProviderForMimeType") + } + + return res, nil +} + +func (s *svc) SetDefaultAppProviderForMimeType(ctx context.Context, req *registry.SetDefaultAppProviderForMimeTypeRequest) (*registry.SetDefaultAppProviderForMimeTypeResponse, error) { + c, err := pool.GetAppRegistryClient(s.c.AppRegistryEndpoint) + if err != nil { + err = errors.Wrap(err, "gateway: error calling GetAppRegistryClient") + return ®istry.SetDefaultAppProviderForMimeTypeResponse{ + Status: status.NewInternal(ctx, err, "error getting user share provider client"), + }, nil + } + + res, err := c.SetDefaultAppProviderForMimeType(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "gateway: error calling SetDefaultAppProviderForMimeType") } return res, nil diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 90a5a042725..920d5bbc157 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -419,6 +419,7 @@ func (s *svc) initiateFileDownload(ctx context.Context, req *provider.InitiateFi func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*gateway.InitiateFileUploadResponse, error) { log := appctx.GetLogger(ctx) + log.Info().Msgf("InitiateFileUpload got %+v", req) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { return &gateway.InitiateFileUploadResponse{ diff --git a/pkg/app/app.go b/pkg/app/app.go index 4adb0904dd0..d547a1e219e 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -21,20 +21,15 @@ package app import ( "context" + registry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) // Registry is the interface that application registries implement // for discovering application providers type Registry interface { - FindProvider(ctx context.Context, mimeType string) (*ProviderInfo, error) - ListProviders(ctx context.Context) ([]*ProviderInfo, error) -} - -// ProviderInfo contains the information -// about a Application Provider -type ProviderInfo struct { - Location string + FindProvider(ctx context.Context, mimeType string) (*registry.ProviderInfo, error) + ListProviders(ctx context.Context) ([]*registry.ProviderInfo, error) } // Provider is the interface that application providers implement diff --git a/pkg/app/provider/demo/demo.go b/pkg/app/provider/demo/demo.go index 928c602b1bb..2d1321154cb 100644 --- a/pkg/app/provider/demo/demo.go +++ b/pkg/app/provider/demo/demo.go @@ -25,9 +25,14 @@ import ( "github.com/cs3org/reva/pkg/app" providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/app/provider/registry" "github.com/mitchellh/mapstructure" ) +func init() { + registry.Register("demo", New) +} + type provider struct { iframeUIProvider string } @@ -49,8 +54,8 @@ func parseConfig(m map[string]interface{}) (*config, error) { return c, nil } -// New returns an implementation to of the storage.FS interface that talk to -// a local filesystem. +// New returns an implementation to of the app.Provider interface that +// connects to an application in the backend. func New(m map[string]interface{}) (app.Provider, error) { c, err := parseConfig(m) if err != nil { diff --git a/pkg/app/provider/loader/loader.go b/pkg/app/provider/loader/loader.go new file mode 100644 index 00000000000..f09c752773d --- /dev/null +++ b/pkg/app/provider/loader/loader.go @@ -0,0 +1,25 @@ +// Copyright 2018-2021 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 loader + +import ( + // Load core application providers. + _ "github.com/cs3org/reva/pkg/app/provider/demo" + // Add your own here +) diff --git a/pkg/app/provider/registry/registry.go b/pkg/app/provider/registry/registry.go new file mode 100644 index 00000000000..43d5ed01882 --- /dev/null +++ b/pkg/app/provider/registry/registry.go @@ -0,0 +1,34 @@ +// Copyright 2018-2021 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 registry + +import "github.com/cs3org/reva/pkg/app" + +// NewFunc is the function that app provider implementations +// should register to at init time. +type NewFunc func(map[string]interface{}) (app.Provider, error) + +// NewFuncs is a map containing all the registered app providers. +var NewFuncs = map[string]NewFunc{} + +// Register registers a new app provider new function. +// Not safe for concurrent use. Safe for use from package init. +func Register(name string, f NewFunc) { + NewFuncs[name] = f +} diff --git a/pkg/app/registry/static/static.go b/pkg/app/registry/static/static.go index 6b419098d89..0d3f7ecbc9d 100644 --- a/pkg/app/registry/static/static.go +++ b/pkg/app/registry/static/static.go @@ -22,6 +22,7 @@ import ( "context" "strings" + registrypb "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" "github.com/cs3org/reva/pkg/app" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/sharedconf" @@ -40,18 +41,18 @@ func (c *config) init() { } } -func (b *registry) ListProviders(ctx context.Context) ([]*app.ProviderInfo, error) { - var providers = make([]*app.ProviderInfo, 0, len(b.rules)) +func (b *registry) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) { + var providers = make([]*registrypb.ProviderInfo, 0, len(b.rules)) for _, address := range b.rules { - providers = append(providers, &app.ProviderInfo{ - Location: address, + providers = append(providers, ®istrypb.ProviderInfo{ + Address: address, }) } return providers, nil } -func (b *registry) FindProvider(ctx context.Context, mimeType string) (*app.ProviderInfo, error) { - // find longest match +func (b *registry) FindProvider(ctx context.Context, mimeType string) (*registrypb.ProviderInfo, error) { + // find the longest match var match string for prefix := range b.rules { @@ -64,8 +65,8 @@ func (b *registry) FindProvider(ctx context.Context, mimeType string) (*app.Prov return nil, errtypes.NotFound("application provider not found for mime type " + mimeType) } - p := &app.ProviderInfo{ - Location: b.rules[match], + p := ®istrypb.ProviderInfo{ + Address: b.rules[match], } return p, nil } @@ -82,8 +83,6 @@ func parseConfig(m map[string]interface{}) (*config, error) { return c, nil } -// New returns an implementation to of the storage.FS interface that talk to -// a local filesystem. func New(m map[string]interface{}) (app.Registry, error) { c, err := parseConfig(m) if err != nil { diff --git a/pkg/auth/manager/registry/registry.go b/pkg/auth/manager/registry/registry.go index 37a164ae1b5..52141f3d072 100644 --- a/pkg/auth/manager/registry/registry.go +++ b/pkg/auth/manager/registry/registry.go @@ -21,7 +21,7 @@ package registry import "github.com/cs3org/reva/pkg/auth" // NewFunc is the function that auth implementations -// should register at init time. +// should register to at init time. type NewFunc func(map[string]interface{}) (auth.Manager, error) // NewFuncs is a map containing all the registered auth managers.