[full-ci] enhancement: use reva client pool selectors (#6452)

* enhancement: use reva client pool selectors

register mock service to registry and pass tests

* enhancement: bump reva

* Fix a couple of linter issues

---------

Co-authored-by: Ralf Haferkamp <rhaferkamp@owncloud.com>
This commit is contained in:
Florian Schade
2023-06-08 12:41:04 +02:00
committed by GitHub
parent 021c9fcdd9
commit 4f26424db6
157 changed files with 2845 additions and 1901 deletions

View File

@@ -2144,7 +2144,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"IDM_ADMIN_PASSWORD": "admin", # override the random admin password from `ocis init`
"FRONTEND_SEARCH_MIN_LENGTH": "2",
"GATEWAY_GRPC_ADDR": "0.0.0.0:9142", # make gateway available to wopi server
"APP_PROVIDER_EXTERNAL_ADDR": "127.0.0.1:9164",
"APP_PROVIDER_EXTERNAL_ADDR": "com.owncloud.api.app-provider",
"APP_PROVIDER_DRIVER": "wopi",
"APP_PROVIDER_WOPI_APP_NAME": "FakeOffice",
"APP_PROVIDER_WOPI_APP_URL": "http://fakeoffice:8080",

View File

@@ -0,0 +1,8 @@
Enhancement: Use reva client selectors
Use reva client selectors instead of the static clients, this introduces the ocis service registry in reva.
The service discovery now resolves reva services by name and the client selectors pick a random registered service node.
https://github.com/owncloud/ocis/pull/6452
https://github.com/cs3org/reva/pull/3939
https://github.com/cs3org/reva/pull/3953

2
go.mod
View File

@@ -13,7 +13,7 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.6.0
github.com/cs3org/go-cs3apis v0.0.0-20230516150832-730ac860c71d
github.com/cs3org/reva/v2 v2.14.0
github.com/cs3org/reva/v2 v2.14.1-0.20230607220921-238a03c2f795
github.com/disintegration/imaging v1.6.2
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/egirna/icap-client v0.1.1

4
go.sum
View File

@@ -629,8 +629,8 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo
github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc=
github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
github.com/cs3org/reva/v2 v2.14.0 h1:X5da4chnEPzqUb76y/DDDawFloRAG7Gy/BMpeYh7vu8=
github.com/cs3org/reva/v2 v2.14.0/go.mod h1:vMQqSn30fEPHO/GKC2WmGimlOPqvfSy4gdhRSpbvrWc=
github.com/cs3org/reva/v2 v2.14.1-0.20230607220921-238a03c2f795 h1:uyzA03PcmG7mjd+3KJrkws0IXuXQCvHEn25xXBmO2QI=
github.com/cs3org/reva/v2 v2.14.1-0.20230607220921-238a03c2f795/go.mod h1:E32krZG159YflDSjDWfx/QGIC2529PS5LiPnGNHu3d0=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=

View File

@@ -0,0 +1,47 @@
package registry
import (
"context"
"time"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
mRegistry "go-micro.dev/v4/registry"
)
// RegisterService publishes an arbitrary endpoint to the service-registry. This allows querying nodes of
// non-micro services like reva. No health-checks are done, thus the caller is responsible for canceling.
func RegisterService(ctx context.Context, service *mRegistry.Service, logger log.Logger) error {
registry := GetRegistry()
node := service.Nodes[0]
logger.Info().Msgf("registering external service %v@%v", node.Id, node.Address)
rOpts := []mRegistry.RegisterOption{mRegistry.RegisterTTL(time.Minute)}
if err := registry.Register(service, rOpts...); err != nil {
logger.Fatal().Err(err).Msgf("Registration error for external service %v", service.Name)
}
t := time.NewTicker(time.Second * 30)
go func() {
for {
select {
case <-t.C:
logger.Debug().Interface("service", service).Msg("refreshing external service-registration")
err := registry.Register(service, rOpts...)
if err != nil {
logger.Error().Err(err).Msgf("registration error for external service %v", service.Name)
}
case <-ctx.Done():
logger.Debug().Interface("service", service).Msg("unregistering")
t.Stop()
err := registry.Deregister(service)
if err != nil {
logger.Err(err).Msgf("Error unregistering external service %v", service.Name)
}
}
}
}()
return nil
}

View File

@@ -1,4 +1,4 @@
package external
package registry
//
//import (

View File

@@ -6,14 +6,14 @@ import (
"sync"
"time"
rRegistry "github.com/cs3org/reva/v2/pkg/registry"
consulr "github.com/go-micro/plugins/v4/registry/consul"
etcdr "github.com/go-micro/plugins/v4/registry/etcd"
kubernetesr "github.com/go-micro/plugins/v4/registry/kubernetes"
mdnsr "github.com/go-micro/plugins/v4/registry/mdns"
memr "github.com/go-micro/plugins/v4/registry/memory"
natsr "github.com/go-micro/plugins/v4/registry/nats"
"go-micro.dev/v4/registry"
mRegistry "go-micro.dev/v4/registry"
"go-micro.dev/v4/registry/cache"
)
@@ -25,7 +25,7 @@ const (
var (
once sync.Once
regPlugin string
reg registry.Registry
reg mRegistry.Registry
)
func Configure(plugin string) {
@@ -37,7 +37,7 @@ func Configure(plugin string) {
// GetRegistry returns a configured micro registry based on Micro env vars.
// It defaults to mDNS, so mind that systems with mDNS disabled by default (i.e SUSE) will have a hard time
// and it needs to explicitly use etcd. Os awareness for providing a working registry out of the box should be done.
func GetRegistry() registry.Registry {
func GetRegistry() mRegistry.Registry {
once.Do(func() {
addresses := strings.Split(os.Getenv(registryAddressEnv), ",")
// prefer env of setting from Configure()
@@ -49,29 +49,33 @@ func GetRegistry() registry.Registry {
switch plugin {
case "nats":
reg = natsr.NewRegistry(
registry.Addrs(addresses...),
mRegistry.Addrs(addresses...),
)
case "kubernetes":
reg = kubernetesr.NewRegistry(
registry.Addrs(addresses...),
mRegistry.Addrs(addresses...),
)
case "etcd":
reg = etcdr.NewRegistry(
registry.Addrs(addresses...),
mRegistry.Addrs(addresses...),
)
case "consul":
reg = consulr.NewRegistry(
registry.Addrs(addresses...),
mRegistry.Addrs(addresses...),
)
case "memory":
reg = memr.NewRegistry()
default:
reg = mdnsr.NewRegistry()
}
// No cache needed for in-memory registry
if plugin != "memory" {
reg = cache.New(reg, cache.WithTTL(20*time.Second))
reg = cache.New(reg, cache.WithTTL(30*time.Second))
}
// fixme: lazy initialization of reva registry, needs refactor to a explicit call per service
_ = rRegistry.Init(reg)
})
// always use cached registry to prevent registry
// lookup for every request

View File

@@ -0,0 +1,83 @@
package registry
import (
"fmt"
"net"
"strconv"
"strings"
mRegistry "go-micro.dev/v4/registry"
"go-micro.dev/v4/util/addr"
)
func BuildGRPCService(serviceID, uuid, address string, version string) *mRegistry.Service {
var host string
var port int
parts := strings.Split(address, ":")
if len(parts) > 1 {
host = strings.Join(parts[:len(parts)-1], ":")
port, _ = strconv.Atoi(parts[len(parts)-1])
} else {
host = parts[0]
}
addr, err := addr.Extract(host)
if err != nil {
addr = host
}
node := &mRegistry.Node{
Id: serviceID + "-" + uuid,
Address: net.JoinHostPort(addr, fmt.Sprint(port)),
Metadata: make(map[string]string),
}
node.Metadata["registry"] = GetRegistry().String()
node.Metadata["server"] = "grpc"
node.Metadata["transport"] = "grpc"
node.Metadata["protocol"] = "grpc"
return &mRegistry.Service{
Name: serviceID,
Version: version,
Nodes: []*mRegistry.Node{node},
Endpoints: make([]*mRegistry.Endpoint, 0),
}
}
func BuildHTTPService(serviceID, uuid, address string, version string) *mRegistry.Service {
var host string
var port int
parts := strings.Split(address, ":")
if len(parts) > 1 {
host = strings.Join(parts[:len(parts)-1], ":")
port, _ = strconv.Atoi(parts[len(parts)-1])
} else {
host = parts[0]
}
addr, err := addr.Extract(host)
if err != nil {
addr = host
}
node := &mRegistry.Node{
Id: serviceID + "-" + uuid,
Address: net.JoinHostPort(addr, fmt.Sprint(port)),
Metadata: make(map[string]string),
}
node.Metadata["registry"] = GetRegistry().String()
node.Metadata["server"] = "http"
node.Metadata["transport"] = "http"
node.Metadata["protocol"] = "http"
return &mRegistry.Service{
Name: serviceID,
Version: version,
Nodes: []*mRegistry.Node{node},
Endpoints: make([]*mRegistry.Endpoint, 0),
}
}

View File

@@ -1,120 +0,0 @@
package external
import (
"context"
"time"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
oregistry "github.com/owncloud/ocis/v2/ocis-pkg/registry"
"go-micro.dev/v4/registry"
)
// RegisterGRPCEndpoint publishes an arbitrary endpoint to the service-registry. This allows querying nodes of
// non-micro GRPC-services like reva. No health-checks are done, thus the caller is responsible for canceling.
func RegisterGRPCEndpoint(ctx context.Context, serviceID, uuid, addr string, version string, logger log.Logger) error {
node := &registry.Node{
Id: serviceID + "-" + uuid,
Address: addr,
Metadata: make(map[string]string),
}
ocisRegistry := oregistry.GetRegistry()
node.Metadata["registry"] = ocisRegistry.String()
node.Metadata["server"] = "grpc"
node.Metadata["transport"] = "grpc"
node.Metadata["protocol"] = "grpc"
service := &registry.Service{
Name: serviceID,
Version: version,
Nodes: []*registry.Node{node},
Endpoints: make([]*registry.Endpoint, 0),
}
logger.Info().Msgf("registering external service %v@%v", node.Id, node.Address)
rOpts := []registry.RegisterOption{registry.RegisterTTL(time.Minute)}
if err := ocisRegistry.Register(service, rOpts...); err != nil {
logger.Fatal().Err(err).Msgf("Registration error for external service %v", serviceID)
}
t := time.NewTicker(time.Second * 30)
go func() {
for {
select {
case <-t.C:
logger.Debug().Interface("service", service).Msg("refreshing external service-registration")
err := ocisRegistry.Register(service, rOpts...)
if err != nil {
logger.Error().Err(err).Msgf("registration error for external service %v", serviceID)
}
case <-ctx.Done():
logger.Debug().Interface("service", service).Msg("unregistering")
t.Stop()
err := ocisRegistry.Deregister(service)
if err != nil {
logger.Err(err).Msgf("Error unregistering external service %v", serviceID)
}
}
}
}()
return nil
}
// RegisterHTTPEndpoint publishes an arbitrary endpoint to the service-registry. This allows querying nodes of
// non-micro HTTP-services like reva. No health-checks are done, thus the caller is responsible for canceling.
func RegisterHTTPEndpoint(ctx context.Context, serviceID, uuid, addr string, version string, logger log.Logger) error {
node := &registry.Node{
Id: serviceID + "-" + uuid,
Address: addr,
Metadata: make(map[string]string),
}
ocisRegistry := oregistry.GetRegistry()
node.Metadata["registry"] = ocisRegistry.String()
node.Metadata["server"] = "http"
node.Metadata["transport"] = "http"
node.Metadata["protocol"] = "http"
service := &registry.Service{
Name: serviceID,
Version: version,
Nodes: []*registry.Node{node},
Endpoints: make([]*registry.Endpoint, 0),
}
logger.Info().Msgf("registering external service %v@%v", node.Id, node.Address)
rOpts := []registry.RegisterOption{registry.RegisterTTL(time.Minute)}
if err := ocisRegistry.Register(service, rOpts...); err != nil {
logger.Fatal().Err(err).Msgf("Registration error for external service %v", serviceID)
}
t := time.NewTicker(time.Second * 30)
go func() {
for {
select {
case <-t.C:
logger.Debug().Interface("service", service).Msg("refreshing external service-registration")
err := ocisRegistry.Register(service, rOpts...)
if err != nil {
logger.Error().Err(err).Msgf("registration error for external service %v", serviceID)
}
case <-ctx.Done():
logger.Debug().Interface("service", service).Msg("unregistering")
t.Stop()
err := ocisRegistry.Deregister(service)
if err != nil {
logger.Err(err).Msgf("Error unregistering external service %v", serviceID)
}
}
}
}()
return nil
}

View File

@@ -1,9 +1,11 @@
package shared
import "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
import (
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
)
var defaultRevaConfig = Reva{
Address: "127.0.0.1:9142",
Address: "com.owncloud.api.gateway",
}
func DefaultRevaConfig() *Reva {

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/app-provider/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.AppProviderConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.AppProviderConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,15 +81,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/app-registry/pkg/config"
"github.com/owncloud/ocis/v2/services/app-registry/pkg/config/parser"
@@ -41,12 +41,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.AppRegistryConfigFromStruct(cfg, logger)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.AppRegistryConfigFromStruct(cfg, logger)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -72,15 +76,9 @@ func Server(cfg *config.Config) *cli.Command {
cancel()
})
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -1,9 +1,8 @@
package revaconfig
import (
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/mitchellh/mapstructure"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/app-registry/pkg/config"
)

View File

@@ -11,7 +11,7 @@ import (
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
@@ -43,10 +43,6 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.AuthBasicConfigFromStruct(cfg)
// the reva runtime calls os.Exit in the case of a failure and there is no way for the oCIS
// runtime to catch it and restart a reva service. Therefore we need to ensure the service has
// everything it needs, before starting the service.
@@ -60,7 +56,15 @@ func Server(cfg *config.Config) *cli.Command {
}
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.AuthBasicConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -90,15 +94,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -1,6 +1,8 @@
package revaconfig
import "github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
import (
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
)
// AuthBasicConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service.
func AuthBasicConfigFromStruct(cfg *config.Config) map[string]interface{} {

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.AuthBearerConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.AuthBearerConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,15 +81,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -1,6 +1,9 @@
// Package revaconfig transfers the config struct to reva config map
package revaconfig
import "github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config"
import (
"github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config"
)
// AuthBearerConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service.
func AuthBearerConfigFromStruct(cfg *config.Config) map[string]interface{} {

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/auth-machine/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.AuthMachineConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.AuthMachineConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,15 +81,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/frontend/pkg/config"
@@ -42,15 +42,20 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg, err := revaconfig.FrontendConfigFromStruct(cfg)
rCfg, err := revaconfig.FrontendConfigFromStruct(cfg)
if err != nil {
return err
}
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -80,15 +85,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterHTTPEndpoint(
ctx,
cfg.HTTP.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.HTTP.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the http endpoint")
httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.HTTP.Addr, version.GetString())
if err := registry.RegisterService(ctx, httpSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the http service")
}
return gr.Run()

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/gateway/pkg/config"
"github.com/owncloud/ocis/v2/services/gateway/pkg/config/parser"
@@ -41,12 +41,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.GatewayConfigFromStruct(cfg, logger)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.GatewayConfigFromStruct(cfg, logger)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -72,15 +76,9 @@ func Server(cfg *config.Config) *cli.Command {
cancel()
})
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -52,16 +52,16 @@ func DefaultConfig() *config.Config {
FrontendPublicURL: "https://localhost:9200",
AppRegistryEndpoint: "localhost:9242",
AuthBasicEndpoint: "localhost:9146",
AuthMachineEndpoint: "localhost:9166",
GroupsEndpoint: "localhost:9160",
PermissionsEndpoint: "localhost:9191",
SharingEndpoint: "localhost:9150",
StoragePublicLinkEndpoint: "localhost:9178",
StorageSharesEndpoint: "localhost:9154",
StorageUsersEndpoint: "localhost:9157",
UsersEndpoint: "localhost:9144",
AppRegistryEndpoint: "com.owncloud.api.app-registry",
AuthBasicEndpoint: "com.owncloud.api.auth-basic",
AuthMachineEndpoint: "com.owncloud.api.auth-machine",
GroupsEndpoint: "com.owncloud.api.groups",
PermissionsEndpoint: "com.owncloud.api.settings",
SharingEndpoint: "com.owncloud.api.sharing",
StoragePublicLinkEndpoint: "com.owncloud.api.storage-publiclink",
StorageSharesEndpoint: "com.owncloud.api.storage-shares",
StorageUsersEndpoint: "com.owncloud.api.storage-users",
UsersEndpoint: "com.owncloud.api.users",
StorageRegistry: config.StorageRegistry{
Driver: "spaces",

View File

@@ -6,9 +6,8 @@ import (
"strings"
"time"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/gateway/pkg/config"
)

View File

@@ -5,12 +5,12 @@ import (
"net/url"
"github.com/CiscoM31/godata"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
cs3group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
cs3user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
@@ -21,8 +21,9 @@ var (
)
type CS3 struct {
Config *shared.Reva
Logger *log.Logger
Config *shared.Reva
Logger *log.Logger
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
}
// CreateUser implements the Backend Interface. It's currently not supported for the CS3 backend
@@ -44,13 +45,13 @@ func (i *CS3) UpdateUser(ctx context.Context, nameOrID string, user libregraph.U
func (i *CS3) GetUser(ctx context.Context, userID string, _ *godata.GoDataRequest) (*libregraph.User, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetUser")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
gatewayClient, err := i.GatewaySelector.Next()
if err != nil {
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get client")
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get gatewayClient")
return nil, errorcode.New(errorcode.ServiceNotAvailable, err.Error())
}
res, err := client.GetUserByClaim(ctx, &cs3user.GetUserByClaimRequest{
res, err := gatewayClient.GetUserByClaim(ctx, &cs3user.GetUserByClaimRequest{
Claim: "userid", // FIXME add consts to reva
Value: userID,
})
@@ -73,9 +74,9 @@ func (i *CS3) GetUser(ctx context.Context, userID string, _ *godata.GoDataReques
func (i *CS3) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libregraph.User, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetUsers")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
gatewayClient, err := i.GatewaySelector.Next()
if err != nil {
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get client")
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get gatewayClient")
return nil, errorcode.New(errorcode.ServiceNotAvailable, err.Error())
}
@@ -84,7 +85,7 @@ func (i *CS3) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libr
return nil, err
}
res, err := client.FindUsers(ctx, &cs3user.FindUsersRequest{
res, err := gatewayClient.FindUsers(ctx, &cs3user.FindUsersRequest{
// FIXME presence match is currently not implemented, an empty search currently leads to
// Unwilling To Perform": Search Error: error parsing filter: (&(objectclass=posixAccount)(|(cn=*)(displayname=*)(mail=*))), error: Present filter match for cn not implemented
Filter: search,
@@ -114,9 +115,9 @@ func (i *CS3) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libr
func (i *CS3) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregraph.Group, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetGroups")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
gatewayClient, err := i.GatewaySelector.Next()
if err != nil {
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get client")
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get gatewayClient")
return nil, errorcode.New(errorcode.ServiceNotAvailable, err.Error())
}
@@ -125,7 +126,7 @@ func (i *CS3) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregra
search = queryParam.Get("$search")
}
res, err := client.FindGroups(ctx, &cs3group.FindGroupsRequest{
res, err := gatewayClient.FindGroups(ctx, &cs3group.FindGroupsRequest{
// FIXME presence match is currently not implemented, an empty search currently leads to
// Unwilling To Perform": Search Error: error parsing filter: (&(objectclass=posixAccount)(|(cn=*)(displayname=*)(mail=*))), error: Present filter match for cn not implemented
Filter: search,
@@ -161,13 +162,13 @@ func (i *CS3) CreateGroup(ctx context.Context, group libregraph.Group) (*libregr
func (i *CS3) GetGroup(ctx context.Context, groupID string, queryParam url.Values) (*libregraph.Group, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetGroup")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
gatewayClient, err := i.GatewaySelector.Next()
if err != nil {
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get client")
logger.Error().Str("backend", "cs3").Err(err).Msg("could not get gatewayClient")
return nil, errorcode.New(errorcode.ServiceNotAvailable, err.Error())
}
res, err := client.GetGroupByClaim(ctx, &cs3group.GetGroupByClaimRequest{
res, err := gatewayClient.GetGroupByClaim(ctx, &cs3group.GetGroupByClaimRequest{
Claim: "groupid", // FIXME add consts to reva
Value: groupID,
})

View File

@@ -17,6 +17,7 @@ import (
ociscrypto "github.com/owncloud/ocis/v2/ocis-pkg/crypto"
"github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
@@ -114,7 +115,7 @@ func Server(opts ...Option) (http.Service, error) {
// how do we secure the api?
var requireAdminMiddleware func(stdhttp.Handler) stdhttp.Handler
var roleService svc.RoleService
var gatewayClient gateway.GatewayAPIClient
var gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
grpcClient, err := grpc.NewClient(append(grpc.GetClientOptions(options.Config.GRPCClientTLS), grpc.WithTraceProvider(tracing.TraceProvider))...)
if err != nil {
return http.Service{}, err
@@ -126,9 +127,9 @@ func Server(opts ...Option) (http.Service, error) {
account.JWTSecret(options.Config.TokenManager.JWTSecret),
))
roleService = settingssvc.NewRoleService("com.owncloud.api.settings", grpcClient)
gatewayClient, err = pool.GetGatewayServiceClient(options.Config.Reva.Address, options.Config.Reva.GetRevaOptions()...)
gatewaySelector, err = pool.GatewaySelector(options.Config.Reva.Address, append(options.Config.Reva.GetRevaOptions(), pool.WithRegistry(registry.GetRegistry()))...)
if err != nil {
return http.Service{}, errors.Wrap(err, "could not initialize gateway client")
return http.Service{}, errors.Wrap(err, "could not initialize gateway selector")
}
} else {
middlewares = append(middlewares, graphMiddleware.Token(options.Config.HTTP.APIToken))
@@ -159,7 +160,7 @@ func Server(opts ...Option) (http.Service, error) {
svc.EventsPublisher(publisher),
svc.WithRoleService(roleService),
svc.WithRequireAdminMiddleware(requireAdminMiddleware),
svc.WithGatewayClient(gatewayClient),
svc.WithGatewaySelector(gatewaySelector),
svc.WithSearchService(searchsvc.NewSearchProviderService("com.owncloud.api.search", grpcClient)),
svc.KeycloakClient(keyCloakClient),
svc.EventHistoryClient(hClient),

View File

@@ -7,13 +7,13 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/stretchr/testify/mock"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
@@ -23,6 +23,8 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
type applicationList struct {
@@ -35,6 +37,7 @@ var _ = Describe("Applications", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
roleService *mocks.RoleService
identityBackend *identitymocks.Backend
@@ -47,7 +50,16 @@ var _ = Describe("Applications", func() {
identityBackend = &identitymocks.Backend{}
roleService = &mocks.RoleService{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
rr = httptest.NewRecorder()
ctx = context.Background()
@@ -62,7 +74,7 @@ var _ = Describe("Applications", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithRoleService(roleService),

View File

@@ -8,15 +8,15 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
"github.com/golang/protobuf/ptypes/empty"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -27,6 +27,8 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
type assignmentList struct {
@@ -39,6 +41,7 @@ var _ = Describe("AppRoleAssignments", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
roleService *mocks.RoleService
identityBackend *identitymocks.Backend
@@ -57,7 +60,16 @@ var _ = Describe("AppRoleAssignments", func() {
identityBackend = &identitymocks.Backend{}
roleService = &mocks.RoleService{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
rr = httptest.NewRecorder()
ctx = context.Background()
@@ -72,7 +84,7 @@ var _ = Describe("AppRoleAssignments", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithRoleService(roleService),

View File

@@ -25,9 +25,14 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) {
g.logger.Info().Msg("Calling GetRootDriveChildren")
ctx := r.Context()
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
res, err := client.GetHome(ctx, &storageprovider.GetHomeRequest{})
res, err := gatewayClient.GetHome(ctx, &storageprovider.GetHomeRequest{})
switch {
case err != nil:
g.logger.Error().Err(err).Msg("error sending get home grpc request")
@@ -43,7 +48,7 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) {
return
}
lRes, err := client.ListContainer(ctx, &storageprovider.ListContainerRequest{
lRes, err := gatewayClient.ListContainer(ctx, &storageprovider.ListContainerRequest{
Ref: &storageprovider.Reference{
Path: res.Path,
},
@@ -80,9 +85,12 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) {
}
func (g Graph) getDriveItem(ctx context.Context, ref storageprovider.Reference) (*libregraph.DriveItem, error) {
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return nil, err
}
res, err := client.Stat(ctx, &storageprovider.StatRequest{Ref: &ref})
res, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &ref})
if err != nil {
return nil, err
}
@@ -94,12 +102,15 @@ func (g Graph) getDriveItem(ctx context.Context, ref storageprovider.Reference)
}
func (g Graph) getRemoteItem(ctx context.Context, root *storageprovider.ResourceId, baseURL *url.URL) (*libregraph.RemoteItem, error) {
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return nil, err
}
ref := &storageprovider.Reference{
ResourceId: root,
}
res, err := client.Stat(ctx, &storageprovider.StatRequest{Ref: ref})
res, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: ref})
if err != nil {
return nil, err
}
@@ -204,8 +215,12 @@ func cs3ResourceToRemoteItem(res *storageprovider.ResourceInfo) (*libregraph.Rem
}
func (g Graph) getPathForResource(ctx context.Context, id storageprovider.ResourceId) (string, error) {
client := g.GetGatewayClient()
res, err := client.GetPath(ctx, &storageprovider.GetPathRequest{ResourceId: &id})
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return "", err
}
res, err := gatewayClient.GetPath(ctx, &storageprovider.GetPathRequest{ResourceId: &id})
if err != nil {
return "", err
}

View File

@@ -8,14 +8,14 @@ import (
"net/http/httptest"
"time"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -24,6 +24,8 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
type itemsList struct {
@@ -36,6 +38,7 @@ var _ = Describe("Driveitems", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
identityBackend *identitymocks.Backend
@@ -49,8 +52,17 @@ var _ = Describe("Driveitems", func() {
rr = httptest.NewRecorder()
identityBackend = &identitymocks.Backend{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityBackend = &identitymocks.Backend{}
newGroup = libregraph.NewGroup()
newGroup.SetMembersodataBind([]string{"/users/user1"})
newGroup.SetId("group1")
@@ -67,7 +79,7 @@ var _ = Describe("Driveitems", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
)

View File

@@ -261,7 +261,13 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) {
return
}
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
drive := libregraph.Drive{}
if err := StrictJSONUnmarshal(r.Body, &drive); err != nil {
logger.Debug().Err(err).Interface("body", r.Body).Msg("could not create drive: invalid body schema definition")
@@ -306,7 +312,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) {
csr.Owner = us
}
resp, err := client.CreateStorageSpace(r.Context(), &csr)
resp, err := gatewayClient.CreateStorageSpace(r.Context(), &csr)
if err != nil {
logger.Error().Err(err).Msg("could not create drive: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
@@ -374,7 +380,12 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
}
root := &rid
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
updateSpaceRequest := &storageprovider.UpdateStorageSpaceRequest{
// Prepare the object to apply the diff from. The properties on StorageSpace will overwrite
@@ -459,7 +470,7 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
}
logger.Debug().Interface("payload", updateSpaceRequest).Msg("calling update space on backend")
resp, err := client.UpdateStorageSpace(r.Context(), updateSpaceRequest)
resp, err := gatewayClient.UpdateStorageSpace(r.Context(), updateSpaceRequest)
if err != nil {
logger.Error().Err(err).Msg("could not update drive: transport error")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "transport error")
@@ -581,7 +592,10 @@ func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, storageSpaces
// ListStorageSpacesWithFilters List Storage Spaces using filters
func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*storageprovider.ListStorageSpacesRequest_Filter, unrestricted bool) (*storageprovider.ListStorageSpacesResponse, error) {
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return nil, err
}
grpcClient, err := grpc.NewClient(append(grpc.GetClientOptions(g.config.GRPCClientTLS), grpc.WithTraceProvider(gtracing.TraceProvider))...)
if err != nil {
@@ -615,7 +629,7 @@ func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*stor
}},
Filters: filters,
}
res, err := client.ListStorageSpaces(ctx, lReq)
res, err := gatewayClient.ListStorageSpaces(ctx, lReq)
return res, err
}
@@ -858,7 +872,10 @@ func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.Storage
if noQuotaInOpaque {
// we have to make a trip to the storage
// TODO only if quota property was requested
client := g.GetGatewayClient()
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return libregraph.Quota{}, err
}
req := &gateway.GetQuotaRequest{
Ref: &storageprovider.Reference{
@@ -866,7 +883,8 @@ func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.Storage
Path: ".",
},
}
res, err := client.GetQuota(ctx, req)
res, err := gatewayClient.GetQuota(ctx, req)
switch {
case err != nil:
logger.Error().Err(err).Interface("ref", req.Ref).Msg("could not call GetQuota: transport error")
@@ -1041,8 +1059,8 @@ func (g Graph) DeleteDrive(w http.ResponseWriter, r *http.Request) {
},
}
}
dRes, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
gatewayClient, _ := g.gatewaySelector.Next()
dRes, err := gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Opaque: opaque,
Id: &storageprovider.StorageSpaceId{
OpaqueId: storagespace.FormatResourceID(rid),

View File

@@ -9,14 +9,14 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/test-go/testify/mock"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
@@ -27,6 +27,8 @@ import (
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
"github.com/test-go/testify/mock"
"google.golang.org/grpc"
)
var _ = Describe("EducationClass", func() {
@@ -35,6 +37,7 @@ var _ = Describe("EducationClass", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
identityBackend *identitymocks.Backend
identityEducationBackend *identitymocks.EducationBackend
@@ -52,9 +55,18 @@ var _ = Describe("EducationClass", func() {
BeforeEach(func() {
eventsPublisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil)
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityEducationBackend = &identitymocks.EducationBackend{}
identityBackend = &identitymocks.Backend{}
gatewayClient = &cs3mocks.GatewayAPIClient{}
newClass = libregraph.NewEducationClass("math", "course")
newClass.SetMembersodataBind([]string{"/users/user1"})
newClass.SetId("math")
@@ -71,7 +83,7 @@ var _ = Describe("EducationClass", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithIdentityEducationBackend(identityEducationBackend),
@@ -320,7 +332,7 @@ var _ = Describe("EducationClass", func() {
cfg.API.GroupMembersPatchLimit = 21
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithIdentityEducationBackend(identityEducationBackend),

View File

@@ -9,13 +9,16 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/test-go/testify/mock"
"google.golang.org/grpc"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
@@ -37,6 +40,7 @@ var _ = Describe("Schools", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
identityEducationBackend *identitymocks.EducationBackend
rr *httptest.ResponseRecorder
@@ -50,8 +54,17 @@ var _ = Describe("Schools", func() {
)
BeforeEach(func() {
identityEducationBackend = &identitymocks.EducationBackend{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityEducationBackend = &identitymocks.EducationBackend{}
newSchool = libregraph.NewEducationSchool()
newSchool.SetId("school1")
@@ -67,7 +80,7 @@ var _ = Describe("Schools", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.WithIdentityEducationBackend(identityEducationBackend),
)
})

View File

@@ -239,13 +239,19 @@ func (g Graph) DeleteEducationUser(w http.ResponseWriter, r *http.Request) {
e.Executant = currentUser.GetId()
}
if g.gatewayClient != nil {
if g.gatewaySelector != nil {
logger.Debug().
Str("user", user.GetId()).
Msg("calling list spaces with user filter to fetch the personal space for deletion")
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
f := listStorageSpacesUserFilter(user.GetId())
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
client, err := g.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
lspr, err := client.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f},
})
@@ -266,7 +272,7 @@ func (g Graph) DeleteEducationUser(w http.ResponseWriter, r *http.Request) {
// Deleting a space a two step process (1. disabling/trashing, 2. purging)
// Do the "disable/trash" step only if the space is not marked as trashed yet:
if _, ok := sp.Opaque.Map["trashed"]; !ok {
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
_, err := client.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,
},
@@ -278,7 +284,7 @@ func (g Graph) DeleteEducationUser(w http.ResponseWriter, r *http.Request) {
}
}
purgeFlag := utils.AppendPlainToOpaque(nil, "purge", "")
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
_, err := client.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Opaque: purgeFlag,
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,

View File

@@ -8,17 +8,17 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -28,6 +28,8 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
type educationUserList struct {
@@ -40,6 +42,7 @@ var _ = Describe("EducationUsers", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
roleService *mocks.RoleService
identityEducationBackend *identitymocks.EducationBackend
@@ -56,9 +59,18 @@ var _ = Describe("EducationUsers", func() {
BeforeEach(func() {
eventsPublisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil)
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityEducationBackend = &identitymocks.EducationBackend{}
roleService = &mocks.RoleService{}
gatewayClient = &cs3mocks.GatewayAPIClient{}
rr = httptest.NewRecorder()
ctx = context.Background()
@@ -72,7 +84,7 @@ var _ = Describe("EducationUsers", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityEducationBackend(identityEducationBackend),
service.WithRoleService(roleService),

View File

@@ -10,6 +10,7 @@ import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/go-chi/chi/v5"
"github.com/jellydator/ttlcache/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
@@ -62,7 +63,7 @@ type Graph struct {
logger *log.Logger
identityBackend identity.Backend
identityEducationBackend identity.EducationBackend
gatewayClient gateway.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
roleService RoleService
permissionsService Permissions
specialDriveItemsCache *ttlcache.Cache[string, interface{}]
@@ -86,11 +87,6 @@ func (g Graph) ServeHTTP(w http.ResponseWriter, r *http.Request) {
g.mux.ServeHTTP(w, r)
}
// GetGatewayClient returns a gateway client to talk to reva
func (g Graph) GetGatewayClient() gateway.GatewayAPIClient {
return g.gatewayClient
}
func (g Graph) publishEvent(ev interface{}) {
if g.eventsPublisher != nil {
if err := events.Publish(g.eventsPublisher, ev); err != nil {

View File

@@ -3,10 +3,24 @@ package svc_test
import (
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
mRegistry "go-micro.dev/v4/registry"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func init() {
registry.Configure("memory")
r := registry.GetRegistry()
service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
service.Nodes = []*mRegistry.Node{{
Address: "any",
}}
_ = r.Register(service)
}
func TestGraph(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Graph Suite")

View File

@@ -16,13 +16,13 @@ import (
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
v0 "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -40,6 +40,7 @@ var _ = Describe("Graph", func() {
var (
svc service.Service
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
permissionService mocks.Permissions
ctx context.Context
@@ -63,13 +64,21 @@ var _ = Describe("Graph", func() {
cfg.Commons = &shared.Commons{}
cfg.GRPCClientTLS = &shared.GRPCClientTLS{}
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
eventsPublisher = mocks.Publisher{}
permissionService = mocks.Permissions{}
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.PermissionService(&permissionService),
)

View File

@@ -9,14 +9,14 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/test-go/testify/mock"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -26,6 +26,8 @@ import (
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
"github.com/test-go/testify/mock"
"google.golang.org/grpc"
)
type groupList struct {
@@ -38,6 +40,7 @@ var _ = Describe("Groups", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
identityBackend *identitymocks.Backend
@@ -54,8 +57,17 @@ var _ = Describe("Groups", func() {
BeforeEach(func() {
eventsPublisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil)
identityBackend = &identitymocks.Backend{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityBackend = &identitymocks.Backend{}
newGroup = libregraph.NewGroup()
newGroup.SetMembersodataBind([]string{"/users/user1"})
newGroup.SetId("group1")
@@ -72,7 +84,7 @@ var _ = Describe("Groups", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
)
@@ -316,7 +328,7 @@ var _ = Describe("Groups", func() {
cfg.API.GroupMembersPatchLimit = 21
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
)

View File

@@ -5,6 +5,7 @@ import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
@@ -24,7 +25,7 @@ type Options struct {
Config *config.Config
Middleware []func(http.Handler) http.Handler
RequireAdminMiddleware func(http.Handler) http.Handler
GatewayClient gateway.GatewayAPIClient
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
IdentityBackend identity.Backend
IdentityEducationBackend identity.EducationBackend
RoleService RoleService
@@ -75,10 +76,10 @@ func WithRequireAdminMiddleware(val func(http.Handler) http.Handler) Option {
}
}
// WithGatewayClient provides a function to set the gateway client option.
func WithGatewayClient(val gateway.GatewayAPIClient) Option {
// WithGatewaySelector provides a function to set the gateway client option.
func WithGatewaySelector(val pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.GatewayClient = val
o.GatewaySelector = val
}
}

View File

@@ -61,7 +61,12 @@ func (g Graph) ChangeOwnPassword(w http.ResponseWriter, r *http.Request) {
ClientId: u.Username,
ClientSecret: currentPw,
}
authRes, err := g.gatewayClient.Authenticate(r.Context(), authReq)
client, err := g.gatewaySelector.Next()
if err != nil {
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
authRes, err := client.Authenticate(r.Context(), authReq)
if err != nil {
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error())
return

View File

@@ -12,6 +12,7 @@ import (
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-ldap/ldap/v3"
. "github.com/onsi/ginkgo/v2"
@@ -25,12 +26,14 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
var _ = Describe("Users changing their own password", func() {
var (
svc service.Service
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
ldapClient *mocks.Client
ldapConfig config.LDAP
identityBackend identity.Backend
@@ -47,7 +50,16 @@ var _ = Describe("Users changing their own password", func() {
cfg.TokenManager.JWTSecret = "loremipsum"
cfg.GRPCClientTLS = &shared.GRPCClientTLS{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
ldapClient = mockedLDAPClient()
ldapConfig = config.LDAP{
@@ -68,7 +80,7 @@ var _ = Describe("Users changing their own password", func() {
eventsPublisher = mocks.Publisher{}
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.WithIdentityBackend(identityBackend),
service.EventsPublisher(&eventsPublisher),
)

View File

@@ -10,6 +10,8 @@ import (
"path/filepath"
"strconv"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
@@ -68,8 +70,15 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
Path: loc,
}
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "could not select next gateway client, aborting")
return
}
// touch file
if err := mustTouchFile(ctx, ref, g.GetGatewayClient()); err != nil {
if err := mustTouchFile(ctx, ref, gatewayClient); err != nil {
g.logger.Error().Err(err).Msg("error touching file")
w.WriteHeader(http.StatusInternalServerError)
return
@@ -83,8 +92,14 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
// GatherPersonalData will all gather all personal data of the user and save it to a file in the users personal space
func (g Graph) GatherPersonalData(usr *user.User, ref *provider.Reference, token string, marsh Marshaller) {
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
return
}
// the context might already be cancelled. We need to impersonate the acting user again
ctx, err := utils.ImpersonateUser(usr, g.gatewayClient, g.config.MachineAuthAPIKey)
ctx, err := utils.ImpersonateUser(usr, gatewayClient, g.config.MachineAuthAPIKey)
if err != nil {
g.logger.Error().Err(err).Str("userID", usr.GetId().GetOpaqueId()).Msg("cannot impersonate user")
}
@@ -141,13 +156,22 @@ func (g Graph) upload(u *user.User, data []byte, ref *provider.Reference, th str
Opaque: utils.AppendPlainToOpaque(nil, "Upload-Length", strconv.FormatUint(uint64(len(data)), 10)),
}
gwc := g.GetGatewayClient()
ctx, err := utils.ImpersonateUser(u, gwc, g.config.MachineAuthAPIKey)
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
return err
}
ctx, err := utils.ImpersonateUser(u, gatewayClient, g.config.MachineAuthAPIKey)
if err != nil {
return err
}
client, err := g.gatewaySelector.Next()
if err != nil {
return err
}
ctx = revactx.ContextSetToken(ctx, th)
uRes, err := gwc.InitiateFileUpload(ctx, uReq)
uRes, err := client.InitiateFileUpload(ctx, uReq)
if err != nil {
return err
}

View File

@@ -10,6 +10,7 @@ import (
"strconv"
"time"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/store"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
@@ -17,6 +18,7 @@ import (
"github.com/jellydator/ttlcache/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
ocisldap "github.com/owncloud/ocis/v2/ocis-pkg/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -144,7 +146,7 @@ func NewService(opts ...Option) (Graph, error) {
usersCache: usersCache,
groupsCache: groupsCache,
eventsPublisher: options.EventsPublisher,
gatewayClient: options.GatewayClient,
gatewaySelector: options.GatewaySelector,
searchService: options.SearchService,
identityEducationBackend: options.IdentityEducationBackend,
keycloakClient: options.KeycloakClient,
@@ -316,9 +318,18 @@ func setIdentityBackends(options Options, svc *Graph) error {
if options.IdentityBackend == nil {
switch options.Config.Identity.Backend {
case "cs3":
gatewaySelector, err := pool.GatewaySelector(
options.Config.Reva.Address,
append(options.Config.Reva.GetRevaOptions(), pool.WithRegistry(registry.GetRegistry()))...,
)
if err != nil {
return err
}
svc.identityBackend = &identity.CS3{
Config: options.Config.Reva,
Logger: &options.Logger,
Config: options.Config.Reva,
Logger: &options.Logger,
GatewaySelector: gatewaySelector,
}
case "ldap":
var err error

View File

@@ -66,7 +66,13 @@ func (g Graph) AssignTags(w http.ResponseWriter, r *http.Request) {
return
}
sres, err := g.gatewayClient.Stat(ctx, &provider.StatRequest{
client, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("error selecting next gateway client")
w.WriteHeader(http.StatusInternalServerError)
return
}
sres, err := client.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{ResourceId: &rid},
})
if err != nil {
@@ -105,7 +111,7 @@ func (g Graph) AssignTags(w http.ResponseWriter, r *http.Request) {
return
}
resp, err := g.gatewayClient.SetArbitraryMetadata(ctx, &provider.SetArbitraryMetadataRequest{
resp, err := client.SetArbitraryMetadata(ctx, &provider.SetArbitraryMetadataRequest{
Ref: &provider.Reference{ResourceId: &rid},
ArbitraryMetadata: &provider.ArbitraryMetadata{
Metadata: map[string]string{
@@ -155,7 +161,13 @@ func (g Graph) UnassignTags(w http.ResponseWriter, r *http.Request) {
return
}
sres, err := g.gatewayClient.Stat(ctx, &provider.StatRequest{
client, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("error selecting next gateway client")
w.WriteHeader(http.StatusInternalServerError)
return
}
sres, err := client.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{ResourceId: &rid},
})
if err != nil {
@@ -194,7 +206,7 @@ func (g Graph) UnassignTags(w http.ResponseWriter, r *http.Request) {
return
}
resp, err := g.gatewayClient.SetArbitraryMetadata(ctx, &provider.SetArbitraryMetadataRequest{
resp, err := client.SetArbitraryMetadata(ctx, &provider.SetArbitraryMetadataRequest{
Ref: &provider.Reference{ResourceId: &rid},
ArbitraryMetadata: &provider.ArbitraryMetadata{
Metadata: map[string]string{

View File

@@ -427,10 +427,18 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
return
}
logger.Debug().Str("id", user.GetId()).Msg("calling list storage spaces with filter")
// use the unrestricted flag to get all possible spaces
// users with the canListAllSpaces permission should see all spaces
client, err := g.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("error selecting next gateway client")
render.Status(r, http.StatusInternalServerError)
return
}
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
lspr, err := client.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: filters,
})
@@ -545,13 +553,19 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
e.Executant = currentUser.GetId()
}
if g.gatewayClient != nil {
if g.gatewaySelector != nil {
logger.Debug().
Str("user", user.GetId()).
Msg("calling list spaces with user filter to fetch the personal space for deletion")
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
f := listStorageSpacesUserFilter(user.GetId())
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
client, err := g.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("error selecting next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, "error selecting next gateway client, aborting")
return
}
lspr, err := client.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f},
})
@@ -572,7 +586,7 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
// Deleting a space a two step process (1. disabling/trashing, 2. purging)
// Do the "disable/trash" step only if the space is not marked as trashed yet:
if _, ok := sp.Opaque.Map["trashed"]; !ok {
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
_, err := client.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,
},
@@ -584,7 +598,7 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
}
}
purgeFlag := utils.AppendPlainToOpaque(nil, "purge", "")
_, err := g.gatewayClient.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
_, err := client.DeleteStorageSpace(r.Context(), &storageprovider.DeleteStorageSpaceRequest{
Opaque: purgeFlag,
Id: &storageprovider.StorageSpaceId{
OpaqueId: sp.Id.OpaqueId,

View File

@@ -9,18 +9,17 @@ import (
"net/http/httptest"
"net/url"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
"go-micro.dev/v4/client"
libregraph "github.com/owncloud/libre-graph-api-go"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -31,6 +30,9 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks"
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
"github.com/stretchr/testify/mock"
"go-micro.dev/v4/client"
"google.golang.org/grpc"
)
type userList struct {
@@ -43,6 +45,7 @@ var _ = Describe("Users", func() {
ctx context.Context
cfg *config.Config
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
eventsPublisher mocks.Publisher
roleService *mocks.RoleService
identityBackend *identitymocks.Backend
@@ -59,9 +62,18 @@ var _ = Describe("Users", func() {
BeforeEach(func() {
eventsPublisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil)
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
identityBackend = &identitymocks.Backend{}
roleService = &mocks.RoleService{}
gatewayClient = &cs3mocks.GatewayAPIClient{}
rr = httptest.NewRecorder()
ctx = context.Background()
@@ -76,7 +88,7 @@ var _ = Describe("Users", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
svc, _ = service.NewService(
service.Config(cfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithRoleService(roleService),
@@ -681,7 +693,7 @@ var _ = Describe("Users", func() {
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
localSvc, _ := service.NewService(
service.Config(localCfg),
service.WithGatewayClient(gatewayClient),
service.WithGatewaySelector(gatewaySelector),
service.EventsPublisher(&eventsPublisher),
service.WithIdentityBackend(identityBackend),
service.WithRoleService(roleService),

View File

@@ -11,7 +11,7 @@ import (
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/groups/pkg/config"
@@ -43,10 +43,6 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.GroupsConfigFromStruct(cfg)
// the reva runtime calls os.Exit in the case of a failure and there is no way for the oCIS
// runtime to catch it and restart a reva service. Therefore we need to ensure the service has
// everything it needs, before starting the service.
@@ -60,7 +56,15 @@ func Server(cfg *config.Config) *cli.Command {
}
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.GroupsConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -90,15 +94,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -15,6 +15,7 @@ import (
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/crypto"
"github.com/owncloud/ocis/v2/ocis-pkg/handlers"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/debug"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
@@ -122,16 +123,17 @@ func Server(cfg *config.Config) *cli.Command {
if err != nil {
return err
}
gwclient, err := pool.GetGatewayServiceClient(
gatewaySelector, err := pool.GatewaySelector(
cfg.Notifications.RevaGateway,
pool.WithTLSCACert(cfg.Notifications.GRPCClientTLS.CACert),
pool.WithTLSMode(tm),
pool.WithRegistry(registry.GetRegistry()),
)
if err != nil {
logger.Fatal().Err(err).Str("addr", cfg.Notifications.RevaGateway).Msg("could not get reva client")
logger.Fatal().Err(err).Str("addr", cfg.Notifications.RevaGateway).Msg("could not get reva gateway selector")
}
valueService := settingssvc.NewValueService("com.owncloud.api.settings", grpc.DefaultClient())
svc := service.NewEventsNotifier(evts, channel, logger, gwclient, valueService, cfg.Notifications.MachineAuthAPIKey, cfg.Notifications.EmailTemplatePath, cfg.WebUIURL)
svc := service.NewEventsNotifier(evts, channel, logger, gatewaySelector, valueService, cfg.Notifications.MachineAuthAPIKey, cfg.Notifications.EmailTemplatePath, cfg.WebUIURL)
gr.Add(svc.Run, func(error) {
cancel()

View File

@@ -3,10 +3,24 @@ package service_test
import (
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
mRegistry "go-micro.dev/v4/registry"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func init() {
registry.Configure("memory")
r := registry.GetRegistry()
service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
service.Nodes = []*mRegistry.Node{{
Address: "any",
}}
_ = r.Register(service)
}
func TestNotifications(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Notification Suite")

View File

@@ -16,6 +16,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -38,7 +39,7 @@ func NewEventsNotifier(
events <-chan events.Event,
channel channels.Channel,
logger log.Logger,
gwClient gateway.GatewayAPIClient,
gatewaySelector pool.Selectable[gateway.GatewayAPIClient],
valueService settingssvc.ValueService,
machineAuthAPIKey, emailTemplatePath, ocisURL string) Service {
@@ -47,7 +48,7 @@ func NewEventsNotifier(
channel: channel,
events: events,
signals: make(chan os.Signal, 1),
gwClient: gwClient,
gatewaySelector: gatewaySelector,
valueService: valueService,
machineAuthAPIKey: machineAuthAPIKey,
emailTemplatePath: emailTemplatePath,
@@ -60,7 +61,7 @@ type eventsNotifier struct {
channel channels.Channel
events <-chan events.Event
signals chan os.Signal
gwClient gateway.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
valueService settingssvc.ValueService
machineAuthAPIKey string
emailTemplatePath string
@@ -137,7 +138,12 @@ func (s eventsNotifier) getGranteeList(ctx context.Context, executant, u *user.U
}
return []*user.User{usr}, nil
case g != nil:
res, err := s.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: g})
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
res, err := gatewayClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: g})
if err != nil {
return nil, err
}
@@ -171,7 +177,11 @@ func (s eventsNotifier) getUser(ctx context.Context, u *user.UserId) (*user.User
if u == nil {
return nil, errors.New("need at least one non-nil grantee")
}
r, err := s.gwClient.GetUser(ctx, &user.GetUserRequest{UserId: u})
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
r, err := gatewayClient.GetUser(ctx, &user.GetUserRequest{UserId: u})
if err != nil {
return nil, err
}
@@ -213,7 +223,12 @@ func (s eventsNotifier) disableEmails(ctx context.Context, u *user.UserId) bool
func (s eventsNotifier) getResourceInfo(ctx context.Context, resourceID *provider.ResourceId, fieldmask *fieldmaskpb.FieldMask) (*provider.ResourceInfo, error) {
// TODO: maybe cache this stat to reduce storage iops
md, err := s.gwClient.Stat(ctx, &provider.StatRequest{
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
md, err := gatewayClient.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{
ResourceId: resourceID,
},

View File

@@ -9,6 +9,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
@@ -22,13 +23,15 @@ import (
"github.com/owncloud/ocis/v2/services/notifications/pkg/service"
"github.com/test-go/testify/mock"
"go-micro.dev/v4/client"
"google.golang.org/grpc"
)
var _ = Describe("Notifications", func() {
var (
gwc *cs3mocks.GatewayAPIClient
vs *settingssvc.MockValueService
sharer = &user.User{
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
vs *settingssvc.MockValueService
sharer = &user.User{
Id: &user.UserId{
OpaqueId: "sharer",
},
@@ -50,11 +53,20 @@ var _ = Describe("Notifications", func() {
)
BeforeEach(func() {
gwc = &cs3mocks.GatewayAPIClient{}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil).Once()
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharee}, nil).Once()
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
gwc.On("Stat", mock.Anything, mock.Anything).Return(&provider.StatResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, Info: &provider.ResourceInfo{Name: "secrets of the board", Space: &provider.StorageSpace{Name: "secret space"}}}, nil)
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil).Once()
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharee}, nil).Once()
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(&provider.StatResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, Info: &provider.ResourceInfo{Name: "secrets of the board", Space: &provider.StorageSpace{Name: "secret space"}}}, nil)
vs = &settingssvc.MockValueService{}
vs.GetValueByUniqueIdentifiersFunc = func(ctx context.Context, req *settingssvc.GetValueByUniqueIdentifiersRequest, opts ...client.CallOption) (*settingssvc.GetValueResponse, error) {
return nil, nil
@@ -67,7 +79,7 @@ var _ = Describe("Notifications", func() {
cfg.GRPCClientTLS = &shared.GRPCClientTLS{}
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
ch := make(chan events.Event)
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gwc, vs, "", "", "")
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gatewaySelector, vs, "", "", "")
go evts.Run()
ch <- ev
@@ -210,9 +222,10 @@ https://owncloud.com
var _ = Describe("Notifications X-Site Scripting", func() {
var (
gwc *cs3mocks.GatewayAPIClient
vs *settingssvc.MockValueService
sharer = &user.User{
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
vs *settingssvc.MockValueService
sharer = &user.User{
Id: &user.UserId{
OpaqueId: "sharer",
},
@@ -234,11 +247,20 @@ var _ = Describe("Notifications X-Site Scripting", func() {
)
BeforeEach(func() {
gwc = &cs3mocks.GatewayAPIClient{}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil).Once()
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharee}, nil).Once()
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
gwc.On("Stat", mock.Anything, mock.Anything).Return(&provider.StatResponse{
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil).Once()
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharee}, nil).Once()
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}, User: sharer}, nil)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(&provider.StatResponse{
Status: &rpc.Status{Code: rpc.Code_CODE_OK},
Info: &provider.ResourceInfo{
Name: "<script>alert('secrets of the board');</script>",
@@ -256,7 +278,7 @@ var _ = Describe("Notifications X-Site Scripting", func() {
cfg.GRPCClientTLS = &shared.GRPCClientTLS{}
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...)
ch := make(chan events.Event)
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gwc, vs, "", "", "")
evts := service.NewEventsNotifier(ch, tc, log.NewLogger(), gatewaySelector, vs, "", "", "")
go evts.Run()
ch <- ev

View File

@@ -13,7 +13,13 @@ func (s eventsNotifier) handleShareCreated(e events.ShareCreated) {
Str("itemid", e.ItemID.OpaqueId).
Logger()
ownerCtx, owner, err := utils.Impersonate(e.Sharer, s.gwClient, s.machineAuthAPIKey)
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
return
}
ownerCtx, owner, err := utils.Impersonate(e.Sharer, gatewayClient, s.machineAuthAPIKey)
if err != nil {
logger.Error().Err(err).Msg("Could not impersonate sharer")
return
@@ -62,7 +68,13 @@ func (s eventsNotifier) handleShareExpired(e events.ShareExpired) {
Str("itemid", e.ItemID.GetOpaqueId()).
Logger()
ownerCtx, owner, err := utils.Impersonate(e.ShareOwner, s.gwClient, s.machineAuthAPIKey)
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
return
}
ownerCtx, owner, err := utils.Impersonate(e.ShareOwner, gatewayClient, s.machineAuthAPIKey)
if err != nil {
logger.Error().Err(err).Msg("Could not impersonate sharer")
return

View File

@@ -13,7 +13,13 @@ func (s eventsNotifier) handleSpaceShared(e events.SpaceShared) {
Str("itemid", e.ID.OpaqueId).
Logger()
executantCtx, executant, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
return
}
executantCtx, executant, err := utils.Impersonate(e.Executant, gatewayClient, s.machineAuthAPIKey)
if err != nil {
logger.Error().
Err(err).
@@ -75,7 +81,13 @@ func (s eventsNotifier) handleSpaceUnshared(e events.SpaceUnshared) {
Str("itemid", e.ID.OpaqueId).
Logger()
executantCtx, executant, err := utils.Impersonate(e.Executant, s.gwClient, s.machineAuthAPIKey)
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
return
}
executantCtx, executant, err := utils.Impersonate(e.Executant, gatewayClient, s.machineAuthAPIKey)
if err != nil {
logger.Error().Err(err).Msg("could not handle space unshared event")
return
@@ -135,7 +147,13 @@ func (s eventsNotifier) handleSpaceMembershipExpired(e events.SpaceMembershipExp
Str("itemid", e.SpaceID.GetOpaqueId()).
Logger()
ownerCtx, owner, err := utils.Impersonate(e.SpaceOwner, s.gwClient, s.machineAuthAPIKey)
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not select next gateway client")
return
}
ownerCtx, owner, err := utils.Impersonate(e.SpaceOwner, gatewayClient, s.machineAuthAPIKey)
if err != nil {
logger.Error().Err(err).Msg("Could not impersonate sharer")
return

View File

@@ -20,6 +20,7 @@ import (
"github.com/owncloud/ocis/v2/ocis-pkg/log"
pkgmiddleware "github.com/owncloud/ocis/v2/ocis-pkg/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -276,9 +277,9 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
logger.Fatal().Err(err).Msg("Failed to get gateway client")
}
rolesClient := settingssvc.NewRoleService("com.owncloud.api.settings", grpcClient)
revaClient, err := pool.GetGatewayServiceClient(cfg.Reva.Address, cfg.Reva.GetRevaOptions()...)
gatewaySelector, err := pool.GatewaySelector(cfg.Reva.Address, append(cfg.Reva.GetRevaOptions(), pool.WithRegistry(registry.GetRegistry()))...)
if err != nil {
logger.Fatal().Err(err).Msg("Failed to get gateway client")
logger.Fatal().Err(err).Msg("Failed to get gateway selector")
}
tokenManager, err := jwt.New(map[string]interface{}{
"secret": cfg.TokenManager.JWTSecret,
@@ -291,10 +292,9 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
var userProvider backend.UserBackend
switch cfg.AccountBackend {
case "cs3":
userProvider = backend.NewCS3UserBackend(
backend.WithLogger(logger),
backend.WithRevaAuthenticator(revaClient),
backend.WithRevaGatewaySelector(gatewaySelector),
backend.WithMachineAuthAPIKey(cfg.MachineAuthAPIKey),
backend.WithOIDCissuer(cfg.OIDC.Issuer),
backend.WithAutoProvisonCreator(autoProvsionCreator),
@@ -364,8 +364,8 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
)),
))
authenticators = append(authenticators, middleware.PublicShareAuthenticator{
Logger: logger,
RevaGatewayClient: revaClient,
Logger: logger,
RevaGatewaySelector: gatewaySelector,
})
authenticators = append(authenticators, middleware.SignedURLAuthenticator{
Logger: logger,
@@ -412,7 +412,7 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
// finally, trigger home creation when a user logs in
middleware.CreateHome(
middleware.Logger(logger),
middleware.RevaGatewayClient(revaClient),
middleware.WithRevaGatewaySelector(gatewaySelector),
middleware.RoleQuotas(cfg.RoleQuotas),
),
)

View File

@@ -10,6 +10,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
@@ -23,19 +24,19 @@ func CreateHome(optionSetters ...Option) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return &createHome{
next: next,
logger: logger,
revaGatewayClient: options.RevaGatewayClient,
roleQuotas: options.RoleQuotas,
next: next,
logger: logger,
revaGatewaySelector: options.RevaGatewaySelector,
roleQuotas: options.RoleQuotas,
}
}
}
type createHome struct {
next http.Handler
logger log.Logger
revaGatewayClient gateway.GatewayAPIClient
roleQuotas map[string]uint64
next http.Handler
logger log.Logger
revaGatewaySelector pool.Selectable[gateway.GatewayAPIClient]
roleQuotas map[string]uint64
}
func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
@@ -64,14 +65,18 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
createHomeRes, err := m.revaGatewayClient.CreateHome(ctx, createHomeReq)
client, err := m.revaGatewaySelector.Next()
if err != nil {
m.logger.Err(err).Msg("error calling CreateHome")
} else if createHomeRes.Status.Code != rpc.Code_CODE_OK {
err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway")
if createHomeRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS {
m.logger.Err(err).Msg("error when calling Createhome")
m.logger.Err(err).Msg("error selecting next gateway client")
} else {
createHomeRes, err := client.CreateHome(ctx, createHomeReq)
if err != nil {
m.logger.Err(err).Msg("error calling CreateHome")
} else if createHomeRes.Status.Code != rpc.Code_CODE_OK {
err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway")
if createHomeRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS {
m.logger.Err(err).Msg("error when calling Createhome")
}
}
}

View File

@@ -5,6 +5,7 @@ import (
"time"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
@@ -38,8 +39,8 @@ type Options struct {
OIDCClient oidc.OIDCClient
// OIDCIss is the oidcAuth-issuer
OIDCIss string
// RevaGatewayClient to send requests to the reva gateway
RevaGatewayClient gateway.GatewayAPIClient
// RevaGatewaySelector to send requests to the reva gateway
RevaGatewaySelector pool.Selectable[gateway.GatewayAPIClient]
// Store for persisting data
Store storesvc.StoreService
// PreSignedURLConfig to configure the middleware
@@ -135,10 +136,10 @@ func CredentialsByUserAgent(v map[string]string) Option {
}
}
// RevaGatewayClient provides a function to set the the reva gateway service client option.
func RevaGatewayClient(gc gateway.GatewayAPIClient) Option {
// WithRevaGatewaySelector provides a function to set the the reva gateway service selector option.
func WithRevaGatewaySelector(val pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.RevaGatewayClient = gc
o.RevaGatewaySelector = val
}
}

View File

@@ -5,6 +5,7 @@ import (
"strings"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
)
@@ -21,8 +22,8 @@ const (
// PublicShareAuthenticator is the authenticator which can authenticate public share requests.
// It will add the share owner into the request context.
type PublicShareAuthenticator struct {
Logger log.Logger
RevaGatewayClient gateway.GatewayAPIClient
Logger log.Logger
RevaGatewaySelector pool.Selectable[gateway.GatewayAPIClient]
}
// The archiver is able to create archives from public shares in which case it needs to use the
@@ -83,7 +84,18 @@ func (a PublicShareAuthenticator) Authenticate(r *http.Request) (*http.Request,
}
}
authResp, err := a.RevaGatewayClient.Authenticate(r.Context(), &gateway.AuthenticateRequest{
client, err := a.RevaGatewaySelector.Next()
if err != nil {
a.Logger.Error().
Err(err).
Str("authenticator", "public_share").
Str("public_share_token", shareToken).
Str("path", r.URL.Path).
Msg("could not select next gateway client")
return nil, false
}
authResp, err := client.Authenticate(r.Context(), &gateway.AuthenticateRequest{
Type: authenticationType,
ClientId: shareToken,
ClientSecret: sharePassword,

View File

@@ -5,8 +5,10 @@ import (
"net/http"
"net/http/httptest"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
@@ -18,23 +20,29 @@ var _ = Describe("Authenticating requests", Label("PublicShareAuthenticator"), f
BeforeEach(func() {
authenticator = PublicShareAuthenticator{
Logger: log.NewLogger(),
RevaGatewayClient: mockGatewayClient{
AuthenticateFunc: func(authType, clientID, clientSecret string) (string, rpcv1beta1.Code) {
if authType != "publicshares" {
return "", rpcv1beta1.Code_CODE_NOT_FOUND
}
RevaGatewaySelector: pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return mockGatewayClient{
AuthenticateFunc: func(authType, clientID, clientSecret string) (string, rpcv1beta1.Code) {
if authType != "publicshares" {
return "", rpcv1beta1.Code_CODE_NOT_FOUND
}
if clientID == "sharetoken" && (clientSecret == "password|examples3cr3t" || clientSecret == "signature|examplesignature|exampleexpiration") {
return "exampletoken", rpcv1beta1.Code_CODE_OK
}
if clientID == "sharetoken" && (clientSecret == "password|examples3cr3t" || clientSecret == "signature|examplesignature|exampleexpiration") {
return "exampletoken", rpcv1beta1.Code_CODE_OK
}
if clientID == "sharetoken" && clientSecret == "password|" {
return "otherexampletoken", rpcv1beta1.Code_CODE_OK
}
if clientID == "sharetoken" && clientSecret == "password|" {
return "otherexampletoken", rpcv1beta1.Code_CODE_OK
}
return "", rpcv1beta1.Code_CODE_NOT_FOUND
return "", rpcv1beta1.Code_CODE_NOT_FOUND
},
}
},
},
),
}
})
When("the request contains correct data", func() {

View File

@@ -4,9 +4,7 @@ import (
"context"
"errors"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"google.golang.org/grpc"
)
var (
@@ -26,8 +24,3 @@ type UserBackend interface {
Authenticate(ctx context.Context, username string, password string) (*cs3.User, string, error)
CreateUserFromClaims(ctx context.Context, claims map[string]interface{}) (*cs3.User, error)
}
// RevaAuthenticator helper interface to mock auth-method from reva gateway-client.
type RevaAuthenticator interface {
Authenticate(ctx context.Context, in *gateway.AuthenticateRequest, opts ...grpc.CallOption) (*gateway.AuthenticateResponse, error)
}

View File

@@ -11,6 +11,7 @@ import (
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
@@ -31,7 +32,7 @@ type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
logger log.Logger
authProvider RevaAuthenticator
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
machineAuthAPIKey string
oidcISS string
autoProvsionCreator autoprovision.Creator
@@ -44,10 +45,10 @@ func WithLogger(l log.Logger) Option {
}
}
// WithRevaAuthenticator set the RevaAuthenticator option
func WithRevaAuthenticator(ra RevaAuthenticator) Option {
// WithRevaGatewaySelector set the gatewaySelector option
func WithRevaGatewaySelector(selectable pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.authProvider = ra
o.gatewaySelector = selectable
}
}
@@ -91,7 +92,12 @@ func NewCS3UserBackend(opts ...Option) UserBackend {
}
func (c *cs3backend) GetUserByClaims(ctx context.Context, claim, value string) (*cs3.User, string, error) {
res, err := c.authProvider.Authenticate(ctx, &gateway.AuthenticateRequest{
gatewayClient, err := c.gatewaySelector.Next()
if err != nil {
return nil, "", fmt.Errorf("could not obtain gatewayClient: %s", err)
}
res, err := gatewayClient.Authenticate(ctx, &gateway.AuthenticateRequest{
Type: "machine",
ClientId: claim + ":" + value,
ClientSecret: c.machineAuthAPIKey,
@@ -113,7 +119,12 @@ func (c *cs3backend) GetUserByClaims(ctx context.Context, claim, value string) (
}
func (c *cs3backend) Authenticate(ctx context.Context, username string, password string) (*cs3.User, string, error) {
res, err := c.authProvider.Authenticate(ctx, &gateway.AuthenticateRequest{
gatewayClient, err := c.gatewaySelector.Next()
if err != nil {
return nil, "", fmt.Errorf("could not obtain gatewayClient: %s", err)
}
res, err := gatewayClient.Authenticate(ctx, &gateway.AuthenticateRequest{
Type: "basic",
ClientId: username,
ClientSecret: password,

View File

@@ -35,7 +35,7 @@ func (d defaultRoleAssigner) UpdateUserRoleAssignment(ctx context.Context, user
var err error
roleIDs, err = loadRolesIDs(ctx, user.Id.OpaqueId, d.roleService)
if err != nil {
d.logger.Error().Err(err).Msgf("Could not load roles")
d.logger.Error().Err(err).Msg("Could not load roles")
return nil, err
}
@@ -68,7 +68,7 @@ func (d defaultRoleAssigner) UpdateUserRoleAssignment(ctx context.Context, user
func (d defaultRoleAssigner) ApplyUserRole(ctx context.Context, user *cs3.User) (*cs3.User, error) {
roleIDs, err := loadRolesIDs(ctx, user.Id.OpaqueId, d.roleService)
if err != nil {
d.logger.Error().Err(err).Msgf("Could not load roles")
d.logger.Error().Err(err).Msg("Could not load roles")
return nil, err
}

View File

@@ -120,7 +120,7 @@ func (ra oidcRoleAssigner) UpdateUserRoleAssignment(ctx context.Context, user *c
func (ra oidcRoleAssigner) ApplyUserRole(ctx context.Context, user *cs3.User) (*cs3.User, error) {
roleIDs, err := loadRolesIDs(ctx, user.Id.OpaqueId, ra.roleService)
if err != nil {
ra.logger.Error().Err(err).Msgf("Could not load roles")
ra.logger.Error().Err(err).Msg("Could not load roles")
return nil, err
}

View File

@@ -11,24 +11,25 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
)
type cs3 struct {
httpClient http.Client
gwClient gateway.GatewayAPIClient
logger log.Logger
httpClient http.Client
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
logger log.Logger
}
func newCS3Retriever(client gateway.GatewayAPIClient, logger log.Logger, insecure bool) cs3 {
func newCS3Retriever(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], logger log.Logger, insecure bool) cs3 {
return cs3{
httpClient: http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure}, //nolint:gosec
},
},
gwClient: client,
logger: logger,
gatewaySelector: gatewaySelector,
logger: logger,
}
}
@@ -40,7 +41,13 @@ func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadClo
return nil, fmt.Errorf("context without %s", revactx.TokenHeader)
}
res, err := s.gwClient.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &provider.Reference{ResourceId: rID, Path: "."}})
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
s.logger.Error().Err(err).Msg("could not get reva gatewayClient")
return nil, err
}
res, err := gatewayClient.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &provider.Reference{ResourceId: rID, Path: "."}})
if err != nil {
return nil, err
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/bbalet/stopwords"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/google/go-tika/tika"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/search/pkg/config"
@@ -23,7 +24,7 @@ type Tika struct {
}
// NewTikaExtractor creates a new Tika instance.
func NewTikaExtractor(gw gateway.GatewayAPIClient, logger log.Logger, cfg *config.Config) (*Tika, error) {
func NewTikaExtractor(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], logger log.Logger, cfg *config.Config) (*Tika, error) {
basic, err := NewBasicExtractor(logger)
if err != nil {
return nil, err
@@ -38,7 +39,7 @@ func NewTikaExtractor(gw gateway.GatewayAPIClient, logger log.Logger, cfg *confi
return &Tika{
Basic: basic,
Retriever: newCS3Retriever(gw, logger, cfg.Extractor.CS3AllowInsecure),
Retriever: newCS3Retriever(gatewaySelector, logger, cfg.Extractor.CS3AllowInsecure),
tika: tika.NewClient(nil, cfg.Extractor.Tika.TikaURL),
contentExtractionSizeLimit: cfg.ContentExtractionSizeLimit,
}, nil

View File

@@ -12,6 +12,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
searchmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/search/v0"
@@ -20,12 +21,17 @@ import (
)
// ResolveReference makes sure the path is relative to the space root
func ResolveReference(ctx context.Context, ref *provider.Reference, ri *provider.ResourceInfo, gw gateway.GatewayAPIClient) (*provider.Reference, error) {
func ResolveReference(ctx context.Context, ref *provider.Reference, ri *provider.ResourceInfo, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (*provider.Reference, error) {
if ref.GetResourceId().GetOpaqueId() == ref.GetResourceId().GetSpaceId() {
return ref, nil
}
gpRes, err := gw.GetPath(ctx, &provider.GetPathRequest{
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
gpRes, err := gatewayClient.GetPath(ctx, &provider.GetPathRequest{
ResourceId: ri.Id,
})
if err != nil || gpRes.Status.Code != rpc.Code_CODE_OK {
@@ -61,9 +67,15 @@ func logDocCount(engine engine.Engine, logger log.Logger) {
logger.Debug().Interface("count", c).Msg("new document count")
}
func getAuthContext(owner *user.User, gw gateway.GatewayAPIClient, secret string, logger log.Logger) (context.Context, error) {
func getAuthContext(owner *user.User, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], secret string, logger log.Logger) (context.Context, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
logger.Error().Err(err).Msg("could not get reva gatewayClient")
return nil, err
}
ownerCtx := ctxpkg.ContextSetUser(context.Background(), owner)
authRes, err := gw.Authenticate(ownerCtx, &gateway.AuthenticateRequest{
authRes, err := gatewayClient.Authenticate(ownerCtx, &gateway.AuthenticateRequest{
Type: "machine",
ClientId: "userid:" + owner.GetId().GetOpaqueId(),
ClientSecret: secret,
@@ -81,8 +93,13 @@ func getAuthContext(owner *user.User, gw gateway.GatewayAPIClient, secret string
return metadata.AppendToOutgoingContext(ownerCtx, ctxpkg.TokenHeader, authRes.Token), nil
}
func statResource(ctx context.Context, ref *provider.Reference, gw gateway.GatewayAPIClient, logger log.Logger) (*provider.StatResponse, error) {
res, err := gw.Stat(ctx, &provider.StatRequest{Ref: ref})
func statResource(ctx context.Context, ref *provider.Reference, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], logger log.Logger) (*provider.StatResponse, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
res, err := gatewayClient.Stat(ctx, &provider.StatRequest{Ref: ref})
if err != nil {
logger.Error().Err(err).Msg("failed to stat the moved resource")
return nil, err

View File

@@ -3,10 +3,23 @@ package search_test
import (
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
mRegistry "go-micro.dev/v4/registry"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func init() {
registry.Configure("memory")
r := registry.GetRegistry()
service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
service.Nodes = []*mRegistry.Node{{
Address: "any",
}}
_ = r.Register(service)
}
func TestSearch(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Search Suite")

View File

@@ -13,6 +13,7 @@ import (
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
sdk "github.com/cs3org/reva/v2/pkg/sdk/common"
"github.com/cs3org/reva/v2/pkg/storage/utils/walker"
"github.com/cs3org/reva/v2/pkg/storagespace"
@@ -46,23 +47,23 @@ type Searcher interface {
// Service is responsible for indexing spaces and pass on a search
// to it's underlying engine.
type Service struct {
logger log.Logger
gateway gateway.GatewayAPIClient
engine engine.Engine
extractor content.Extractor
secret string
logger log.Logger
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
engine engine.Engine
extractor content.Extractor
secret string
}
var errSkipSpace error
// NewService creates a new Provider instance.
func NewService(gw gateway.GatewayAPIClient, eng engine.Engine, extractor content.Extractor, logger log.Logger, cfg *config.Config) *Service {
func NewService(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], eng engine.Engine, extractor content.Extractor, logger log.Logger, cfg *config.Config) *Service {
var s = &Service{
gateway: gw,
engine: eng,
secret: cfg.MachineAuthAPIKey,
logger: logger,
extractor: extractor,
gatewaySelector: gatewaySelector,
engine: eng,
secret: cfg.MachineAuthAPIKey,
logger: logger,
extractor: extractor,
}
return s
@@ -75,7 +76,12 @@ func (s *Service) Search(ctx context.Context, req *searchsvc.SearchRequest) (*se
}
s.logger.Debug().Str("query", req.Query).Msg("performing a search")
listSpacesRes, err := s.gateway.ListStorageSpaces(ctx, &provider.ListStorageSpacesRequest{
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
listSpacesRes, err := gatewayClient.ListStorageSpaces(ctx, &provider.ListStorageSpacesRequest{
Filters: []*provider.ListStorageSpacesRequest_Filter{
{
Type: provider.ListStorageSpacesRequest_Filter_TYPE_SPACE_TYPE,
@@ -227,7 +233,13 @@ func (s *Service) searchIndex(ctx context.Context, req *searchsvc.SearchRequest,
s.logger.Warn().Interface("space", space).Msg("could not find mountpoint space for grant space")
return nil, errSkipSpace
}
gpRes, err := s.gateway.GetPath(ctx, &provider.GetPathRequest{
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
gpRes, err := gatewayClient.GetPath(ctx, &provider.GetPathRequest{
ResourceId: space.Root,
})
if err != nil {
@@ -296,7 +308,7 @@ func (s *Service) searchIndex(ctx context.Context, req *searchsvc.SearchRequest,
// IndexSpace (re)indexes all resources of a given space.
func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId, uID *user.UserId) error {
ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gateway, s.secret, s.logger)
ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gatewaySelector, s.secret, s.logger)
if err != nil {
return err
}
@@ -312,7 +324,7 @@ func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId, uID *user.UserId)
}
rootID.OpaqueId = rootID.SpaceId
w := walker.NewWalker(s.gateway)
w := walker.NewWalker(s.gatewaySelector)
err = w.Walk(ownerCtx, &rootID, func(wd string, info *provider.ResourceInfo, err error) error {
if err != nil {
s.logger.Error().Err(err).Msg("error walking the tree")
@@ -426,17 +438,17 @@ func (s *Service) MoveItem(ref *provider.Reference, uID *user.UserId) {
}
func (s *Service) resInfo(uID *user.UserId, ref *provider.Reference) (context.Context, *provider.StatResponse, string) {
ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gateway, s.secret, s.logger)
ownerCtx, err := getAuthContext(&user.User{Id: uID}, s.gatewaySelector, s.secret, s.logger)
if err != nil {
return nil, nil, ""
}
statRes, err := statResource(ownerCtx, ref, s.gateway, s.logger)
statRes, err := statResource(ownerCtx, ref, s.gatewaySelector, s.logger)
if err != nil {
return nil, nil, ""
}
r, err := ResolveReference(ownerCtx, ref, statRes.GetInfo(), s.gateway)
r, err := ResolveReference(ownerCtx, ref, statRes.GetInfo(), s.gatewaySelector)
if err != nil {
return nil, nil, ""
}

View File

@@ -8,6 +8,7 @@ import (
sprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
@@ -20,17 +21,19 @@ import (
engineMocks "github.com/owncloud/ocis/v2/services/search/pkg/engine/mocks"
"github.com/owncloud/ocis/v2/services/search/pkg/search"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
var _ = Describe("Searchprovider", func() {
var (
s search.Searcher
extractor *contentMocks.Extractor
gw *cs3mocks.GatewayAPIClient
indexClient *engineMocks.Engine
ctx context.Context
logger = log.NewLogger()
user = &userv1beta1.User{
s search.Searcher
extractor *contentMocks.Extractor
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
indexClient *engineMocks.Engine
ctx context.Context
logger = log.NewLogger()
user = &userv1beta1.User{
Id: &userv1beta1.UserId{
OpaqueId: "user",
},
@@ -70,22 +73,31 @@ var _ = Describe("Searchprovider", func() {
)
BeforeEach(func() {
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
ctx = context.Background()
gw = &cs3mocks.GatewayAPIClient{}
indexClient = &engineMocks.Engine{}
extractor = &contentMocks.Extractor{}
s = search.NewService(gw, indexClient, extractor, logger, &config.Config{})
s = search.NewService(gatewaySelector, indexClient, extractor, logger, &config.Config{})
gw.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{
Status: status.NewOK(ctx),
Token: "authtoken",
}, nil)
gw.On("Stat", mock.Anything, mock.Anything).Return(&sprovider.StatResponse{
gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(&sprovider.StatResponse{
Status: status.NewOK(context.Background()),
Info: ri,
}, nil)
gw.On("GetPath", mock.Anything, mock.MatchedBy(func(req *sprovider.GetPathRequest) bool {
gatewayClient.On("GetPath", mock.Anything, mock.MatchedBy(func(req *sprovider.GetPathRequest) bool {
return req.ResourceId.OpaqueId == ri.Id.OpaqueId
})).Return(&sprovider.GetPathResponse{
Status: status.NewOK(context.Background()),
@@ -96,14 +108,14 @@ var _ = Describe("Searchprovider", func() {
Describe("New", func() {
It("returns a new instance", func() {
s := search.NewService(gw, indexClient, extractor, logger, &config.Config{})
s := search.NewService(gatewaySelector, indexClient, extractor, logger, &config.Config{})
Expect(s).ToNot(BeNil())
})
})
Describe("IndexSpace", func() {
It("walks the space and indexes all files", func() {
gw.On("GetUserByClaim", mock.Anything, mock.Anything).Return(&userv1beta1.GetUserByClaimResponse{
gatewayClient.On("GetUserByClaim", mock.Anything, mock.Anything).Return(&userv1beta1.GetUserByClaimResponse{
Status: status.NewOK(context.Background()),
User: user,
}, nil)
@@ -127,7 +139,7 @@ var _ = Describe("Searchprovider", func() {
Context("with a personal space", func() {
BeforeEach(func() {
gw.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
Status: status.NewOK(ctx),
StorageSpaces: []*sprovider.StorageSpace{personalSpace},
}, nil)
@@ -210,14 +222,14 @@ var _ = Describe("Searchprovider", func() {
},
},
}
gw.On("GetPath", mock.Anything, mock.Anything).Return(&sprovider.GetPathResponse{
gatewayClient.On("GetPath", mock.Anything, mock.Anything).Return(&sprovider.GetPathResponse{
Status: status.NewOK(ctx),
Path: "/grant/path",
}, nil)
})
It("searches the received spaces", func() {
gw.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
Status: status.NewOK(ctx),
StorageSpaces: []*sprovider.StorageSpace{grantSpace, mountpointSpace},
}, nil)
@@ -259,7 +271,7 @@ var _ = Describe("Searchprovider", func() {
Context("when searching both spaces", func() {
BeforeEach(func() {
gw.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
Status: status.NewOK(ctx),
StorageSpaces: []*sprovider.StorageSpace{personalSpace, grantSpace, mountpointSpace},
}, nil)

View File

@@ -19,6 +19,7 @@ import (
"github.com/jellydator/ttlcache/v2"
ociscrypto "github.com/owncloud/ocis/v2/ocis-pkg/crypto"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
v0 "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/search/v0"
searchsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/search/v0"
"github.com/owncloud/ocis/v2/services/search/pkg/content"
@@ -55,9 +56,9 @@ func NewHandler(opts ...Option) (searchsvc.SearchProviderHandler, func(), error)
}
// initialize gateway
gw, err := pool.GetGatewayServiceClient(cfg.Reva.Address)
selector, err := pool.GatewaySelector(cfg.Reva.Address, pool.WithRegistry(registry.GetRegistry()))
if err != nil {
logger.Fatal().Err(err).Str("addr", cfg.Reva.Address).Msg("could not get reva client")
logger.Fatal().Err(err).Msg("could not get reva gateway selector")
return nil, teardown, err
}
// initialize search content extractor
@@ -68,7 +69,7 @@ func NewHandler(opts ...Option) (searchsvc.SearchProviderHandler, func(), error)
return nil, teardown, err
}
case "tika":
if extractor, err = content.NewTikaExtractor(gw, logger, cfg); err != nil {
if extractor, err = content.NewTikaExtractor(selector, logger, cfg); err != nil {
return nil, teardown, err
}
default:
@@ -106,7 +107,7 @@ func NewHandler(opts ...Option) (searchsvc.SearchProviderHandler, func(), error)
return nil, teardown, err
}
ss := search.NewService(gw, eng, extractor, logger, cfg)
ss := search.NewService(selector, eng, extractor, logger, cfg)
// setup event handling
if err := search.HandleEvents(ss, bus, logger, cfg); err != nil {

View File

@@ -53,8 +53,8 @@ func DefaultConfig() *config.Config {
DataPath: path.Join(defaults.BaseDataPath(), "settings"),
SetupDefaultAssignments: false,
Metadata: config.Metadata{
GatewayAddress: "127.0.0.1:9215", // system storage
StorageAddress: "127.0.0.1:9215",
GatewayAddress: "com.owncloud.api.storage-system",
StorageAddress: "com.owncloud.api.storage-system",
SystemUserIDP: "internal",
Cache: &config.Cache{
Store: "memory",

View File

@@ -11,7 +11,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/sharing/pkg/config"
@@ -55,12 +55,16 @@ func Server(cfg *config.Config) *cli.Command {
}
}
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.SharingConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.SharingConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -90,15 +94,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -41,11 +41,11 @@ func DefaultConfig() *config.Config {
File: filepath.Join(defaults.BaseDataPath(), "storage", "shares.json"),
},
CS3: config.UserSharingCS3Driver{
ProviderAddr: "127.0.0.1:9215", // system storage
ProviderAddr: "com.owncloud.api.storage-system",
SystemUserIDP: "internal",
},
JSONCS3: config.UserSharingJSONCS3Driver{
ProviderAddr: "127.0.0.1:9215", // system storage
ProviderAddr: "com.owncloud.api.storage-system",
SystemUserIDP: "internal",
},
OwnCloudSQL: config.UserSharingOwnCloudSQLDriver{
@@ -61,11 +61,11 @@ func DefaultConfig() *config.Config {
File: filepath.Join(defaults.BaseDataPath(), "storage", "publicshares.json"),
},
CS3: config.PublicSharingCS3Driver{
ProviderAddr: "127.0.0.1:9215", // system storage
ProviderAddr: "com.owncloud.api.storage-system", // system storage
SystemUserIDP: "internal",
},
JSONCS3: config.PublicSharingJSONCS3Driver{
ProviderAddr: "127.0.0.1:9215", // system storage
ProviderAddr: "com.owncloud.api.storage-system", // system storage
SystemUserIDP: "internal",
},
// TODO implement and add owncloudsql publicshare driver

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/storage-publiclink/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.StoragePublicLinkConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.StoragePublicLinkConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,15 +81,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/storage-shares/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.StorageSharesConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.StorageSharesConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,15 +81,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -34,7 +34,7 @@ func DefaultConfig() *config.Config {
Reva: shared.DefaultRevaConfig(),
MountID: "7639e57c-4433-4a12-8201-722fd0009154",
ReadOnly: false,
SharesProviderEndpoint: "localhost:9150",
SharesProviderEndpoint: "com.owncloud.api.sharing",
}
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/storage-system/pkg/config"
@@ -42,12 +42,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.StorageSystemFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.StorageSystemFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -77,26 +81,14 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
if err := external.RegisterHTTPEndpoint(
ctx,
cfg.HTTP.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.HTTP.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the http endpoint")
httpScv := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.HTTP.Addr, version.GetString())
if err := registry.RegisterService(ctx, httpScv, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the http service")
}
return gr.Run()

View File

@@ -34,12 +34,12 @@ func StorageSystemFromStruct(cfg *config.Config) map[string]interface{} {
"services": map[string]interface{}{
"gateway": map[string]interface{}{
// registries are located on the gateway
"authregistrysvc": cfg.GRPC.Addr,
"storageregistrysvc": cfg.GRPC.Addr,
"authregistrysvc": "com.owncloud.api.storage-system",
"storageregistrysvc": "com.owncloud.api.storage-system",
// user metadata is located on the users services
"userprovidersvc": cfg.GRPC.Addr,
"groupprovidersvc": cfg.GRPC.Addr,
"permissionssvc": cfg.GRPC.Addr,
"userprovidersvc": "com.owncloud.api.storage-system",
"groupprovidersvc": "com.owncloud.api.storage-system",
"permissionssvc": "com.owncloud.api.storage-system",
// other
"disable_home_creation_on_login": true, // metadata manually creates a space
// metadata always uses the simple upload, so no transfer secret or datagateway needed
@@ -69,7 +69,7 @@ func StorageSystemFromStruct(cfg *config.Config) map[string]interface{} {
"drivers": map[string]interface{}{
"static": map[string]interface{}{
"rules": map[string]interface{}{
"machine": cfg.GRPC.Addr,
"machine": "com.owncloud.api.storage-system",
},
},
},
@@ -79,7 +79,7 @@ func StorageSystemFromStruct(cfg *config.Config) map[string]interface{} {
"auth_managers": map[string]interface{}{
"machine": map[string]interface{}{
"api_key": cfg.SystemUserAPIKey,
"gateway_addr": cfg.GRPC.Addr,
"gateway_addr": "com.owncloud.api.storage-system",
},
},
},
@@ -95,7 +95,7 @@ func StorageSystemFromStruct(cfg *config.Config) map[string]interface{} {
"static": map[string]interface{}{
"rules": map[string]interface{}{
"/": map[string]interface{}{
"address": cfg.GRPC.Addr,
"address": "com.owncloud.api.storage-system",
},
},
},
@@ -161,7 +161,7 @@ func metadataDrivers(cfg *config.Config) map[string]interface{} {
"user_layout": "{{.Id.OpaqueId}}",
"treetime_accounting": false,
"treesize_accounting": false,
"permissionssvc": cfg.GRPC.Addr,
"permissionssvc": "com.owncloud.api.storage-system",
"max_acquire_lock_cycles": cfg.Drivers.OCIS.MaxAcquireLockCycles,
"lock_cycle_duration_factor": cfg.Drivers.OCIS.LockCycleDurationFactor,
"statcache": map[string]interface{}{

View File

@@ -11,7 +11,7 @@ import (
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/storage-users/pkg/config"
@@ -44,12 +44,16 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.StorageUsersConfigFromStruct(cfg)
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.StorageUsersConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -79,15 +83,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
{
@@ -96,12 +94,12 @@ func Server(cfg *config.Config) *cli.Command {
logger.Fatal().Err(err).Msg("can't connect to nats")
}
gw, err := pool.GetGatewayServiceClient(cfg.Reva.Address)
selector, err := pool.GatewaySelector(cfg.Reva.Address, pool.WithRegistry(registry.GetRegistry()))
if err != nil {
return err
}
eventSVC, err := event.NewService(gw, stream, logger, *cfg)
eventSVC, err := event.NewService(selector, stream, logger, *cfg)
if err != nil {
logger.Fatal().Err(err).Msg("can't create event service")
}

View File

@@ -58,7 +58,7 @@ func DefaultConfig() *config.Config {
DBHost: "",
DBPort: 3306,
DBName: "owncloud",
UsersProviderEndpoint: "localhost:9144",
UsersProviderEndpoint: "com.owncloud.api.users",
},
S3NG: config.S3NGDriver{
MetadataBackend: "messagepack",
@@ -68,7 +68,7 @@ func DefaultConfig() *config.Config {
Region: "default",
PersonalSpaceAliasTemplate: "{{.SpaceType}}/{{.User.Username | lower}}",
GeneralSpaceAliasTemplate: "{{.SpaceType}}/{{.SpaceName | replace \" \" \"-\" | lower}}",
PermissionsEndpoint: "127.0.0.1:9191",
PermissionsEndpoint: "com.owncloud.api.settings",
MaxAcquireLockCycles: 20,
LockCycleDurationFactor: 30,
},
@@ -79,7 +79,7 @@ func DefaultConfig() *config.Config {
UserLayout: "{{.Id.OpaqueId}}",
PersonalSpaceAliasTemplate: "{{.SpaceType}}/{{.User.Username | lower}}",
GeneralSpaceAliasTemplate: "{{.SpaceType}}/{{.SpaceName | replace \" \" \"-\" | lower}}",
PermissionsEndpoint: "127.0.0.1:9191",
PermissionsEndpoint: "com.owncloud.api.settings",
MaxAcquireLockCycles: 20,
LockCycleDurationFactor: 30,
},

View File

@@ -6,6 +6,7 @@ import (
apiGateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
apiUser "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/storage-users/pkg/config"
"github.com/owncloud/ocis/v2/services/storage-users/pkg/task"
@@ -17,19 +18,19 @@ const (
// Service wraps all common logic that is needed to react to incoming events.
type Service struct {
gatewayClient apiGateway.GatewayAPIClient
eventStream events.Stream
logger log.Logger
config config.Config
gatewaySelector pool.Selectable[apiGateway.GatewayAPIClient]
eventStream events.Stream
logger log.Logger
config config.Config
}
// NewService prepares and returns a Service implementation.
func NewService(gatewayClient apiGateway.GatewayAPIClient, eventStream events.Stream, logger log.Logger, conf config.Config) (Service, error) {
func NewService(gatewaySelector pool.Selectable[apiGateway.GatewayAPIClient], eventStream events.Stream, logger log.Logger, conf config.Config) (Service, error) {
svc := Service{
gatewayClient: gatewayClient,
eventStream: eventStream,
logger: logger,
config: conf,
gatewaySelector: gatewaySelector,
eventStream: eventStream,
logger: logger,
config: conf,
}
return svc, nil
@@ -69,7 +70,7 @@ func (s Service) Run() error {
continue
}
if err = task.PurgeTrashBin(executantID, deleteBefore, spaceType, s.gatewayClient, s.config.Commons.MachineAuthAPIKey); err != nil {
if err = task.PurgeTrashBin(executantID, deleteBefore, spaceType, s.gatewaySelector, s.config.Commons.MachineAuthAPIKey); err != nil {
errs = append(errs, err)
}
}

View File

@@ -3,10 +3,23 @@ package task_test
import (
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
mRegistry "go-micro.dev/v4/registry"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func init() {
registry.Configure("memory")
r := registry.GetRegistry()
service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
service.Nodes = []*mRegistry.Node{{
Address: "any",
}}
_ = r.Register(service)
}
func TestTask(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Task Suite")

View File

@@ -9,6 +9,7 @@ import (
apiRpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
apiProvider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
)
@@ -16,13 +17,18 @@ import (
// the provided executantID must have space access.
// removeBefore specifies how long an item must be in the trash-bin to be deleted,
// items that stay there for a shorter time are ignored and kept in place.
func PurgeTrashBin(executantID *apiUser.UserId, deleteBefore time.Time, spaceType SpaceType, gwc apiGateway.GatewayAPIClient, machineAuthAPIKey string) error {
executantCtx, _, err := utils.Impersonate(executantID, gwc, machineAuthAPIKey)
func PurgeTrashBin(executantID *apiUser.UserId, deleteBefore time.Time, spaceType SpaceType, gatewaySelector pool.Selectable[apiGateway.GatewayAPIClient], machineAuthAPIKey string) error {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return err
}
listStorageSpacesResponse, err := gwc.ListStorageSpaces(executantCtx, &apiProvider.ListStorageSpacesRequest{
executantCtx, _, err := utils.Impersonate(executantID, gatewayClient, machineAuthAPIKey)
if err != nil {
return err
}
listStorageSpacesResponse, err := gatewayClient.ListStorageSpaces(executantCtx, &apiProvider.ListStorageSpacesRequest{
Filters: []*apiProvider.ListStorageSpacesRequest_Filter{
{
Type: apiProvider.ListStorageSpacesRequest_Filter_TYPE_SPACE_TYPE,
@@ -77,12 +83,12 @@ func PurgeTrashBin(executantID *apiUser.UserId, deleteBefore time.Time, spaceTyp
return fmt.Errorf("can't impersonate space user for space: %s", storageSpace.GetId().GetOpaqueId())
}
impersonatedCtx, _, err := utils.Impersonate(impersonationID, gwc, machineAuthAPIKey)
impersonatedCtx, _, err := utils.Impersonate(impersonationID, gatewayClient, machineAuthAPIKey)
if err != nil {
return err
}
listRecycleResponse, err := gwc.ListRecycle(impersonatedCtx, &apiProvider.ListRecycleRequest{Ref: storageSpaceReference})
listRecycleResponse, err := gatewayClient.ListRecycle(impersonatedCtx, &apiProvider.ListRecycleRequest{Ref: storageSpaceReference})
if err != nil {
return err
}
@@ -93,7 +99,7 @@ func PurgeTrashBin(executantID *apiUser.UserId, deleteBefore time.Time, spaceTyp
continue
}
purgeRecycleResponse, err := gwc.PurgeRecycle(impersonatedCtx, &apiProvider.PurgeRecycleRequest{
purgeRecycleResponse, err := gatewayClient.PurgeRecycle(impersonatedCtx, &apiProvider.PurgeRecycleRequest{
Ref: storageSpaceReference,
Key: recycleItem.Key,
})

View File

@@ -4,21 +4,23 @@ import (
"context"
"encoding/json"
"errors"
"google.golang.org/grpc"
"time"
apiGateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
apiUser "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
apiRpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
apiProvider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
apiTypes "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/owncloud/ocis/v2/services/storage-users/pkg/task"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
func MustMarshal(v any) []byte {
@@ -31,7 +33,8 @@ func MustMarshal(v any) []byte {
var _ = Describe("trash", func() {
var (
gwc *cs3mocks.GatewayAPIClient
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
ctx context.Context
now time.Time
genericError error
@@ -45,7 +48,16 @@ var _ = Describe("trash", func() {
)
BeforeEach(func() {
gwc = &cs3mocks.GatewayAPIClient{}
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
ctx = context.Background()
now = time.Now()
genericError = errors.New("any")
@@ -100,36 +112,36 @@ var _ = Describe("trash", func() {
Describe("PurgeTrashBin", func() {
It("throws an error if the user cannot authenticate", func() {
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(nil, genericError)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(nil, genericError)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(HaveOccurred())
})
It("throws an error if space listing fails", func() {
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(nil, genericError)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(nil, genericError)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(HaveOccurred())
})
It("throws an error if a personal space user can't be impersonated", func() {
listStorageSpacesResponse.StorageSpaces = []*apiProvider.StorageSpace{personalSpace}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(MatchError(errors.New("can't impersonate space user for space: personal")))
})
It("throws an error if a project space user can't be impersonated", func() {
listStorageSpacesResponse.StorageSpaces = []*apiProvider.StorageSpace{projectSpace}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(MatchError(errors.New("can't impersonate space user for space: project")))
})
It("throws an error if a project space has no user with delete permissions", func() {
@@ -143,11 +155,11 @@ var _ = Describe("trash", func() {
}),
},
}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(MatchError(errors.New("can't impersonate space user for space: project")))
})
It("only deletes items older than the specified period", func() {
@@ -188,17 +200,17 @@ var _ = Describe("trash", func() {
},
}
gwc.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
gwc.On("ListRecycle", mock.Anything, mock.Anything).Return(
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(authenticateResponse, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(listStorageSpacesResponse, nil)
gatewayClient.On("ListRecycle", mock.Anything, mock.Anything).Return(
func(_ context.Context, req *apiProvider.ListRecycleRequest, _ ...grpc.CallOption) *apiProvider.ListRecycleResponse {
return &apiProvider.ListRecycleResponse{
RecycleItems: recycleItems[req.Ref.ResourceId.OpaqueId],
}
}, nil,
)
gwc.On("PurgeRecycle", mock.Anything, mock.Anything).Return(
gatewayClient.On("PurgeRecycle", mock.Anything, mock.Anything).Return(
func(_ context.Context, req *apiProvider.PurgeRecycleRequest, _ ...grpc.CallOption) *apiProvider.PurgeRecycleResponse {
var items []*apiProvider.RecycleItem
for _, item := range recycleItems[req.Ref.ResourceId.OpaqueId] {
@@ -219,7 +231,7 @@ var _ = Describe("trash", func() {
}, nil,
)
err := task.PurgeTrashBin(user.Id, now, task.Project, gwc, "")
err := task.PurgeTrashBin(user.Id, now, task.Project, gatewaySelector, "")
Expect(err).To(BeNil())
Expect(recycleItems["personal"]).To(HaveLen(2))
Expect(recycleItems["project"]).To(HaveLen(2))

View File

@@ -2,6 +2,7 @@ package grpc
import (
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
thumbnailssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/thumbnails/v0"
@@ -41,12 +42,14 @@ func NewService(opts ...Option) grpc.Service {
options.Logger.Error().Err(err).Msg("could not get gateway client tls mode")
return grpc.Service{}
}
gc, err := pool.GetGatewayServiceClient(tconf.RevaGateway,
gatewaySelector, err := pool.GatewaySelector(tconf.RevaGateway,
pool.WithTLSCACert(options.Config.GRPCClientTLS.CACert),
pool.WithTLSMode(tm),
pool.WithRegistry(registry.GetRegistry()),
)
if err != nil {
options.Logger.Error().Err(err).Msg("could not get gateway client")
options.Logger.Error().Err(err).Msg("could not get gateway selector")
return grpc.Service{}
}
var thumbnail decorators.DecoratedService
@@ -61,8 +64,8 @@ func NewService(opts ...Option) grpc.Service {
options.Logger,
),
),
svc.CS3Source(imgsource.NewCS3Source(tconf, gc)),
svc.CS3Client(gc),
svc.CS3Source(imgsource.NewCS3Source(tconf, gatewaySelector)),
svc.GatewaySelector(gatewaySelector),
)
thumbnail = decorators.NewInstrument(thumbnail, options.Metrics)
thumbnail = decorators.NewLogging(thumbnail, options.Logger)

View File

@@ -4,7 +4,7 @@ import (
"net/http"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/thumbnails/pkg/config"
"github.com/owncloud/ocis/v2/services/thumbnails/pkg/thumbnail/imgsource"
@@ -22,7 +22,7 @@ type Options struct {
ThumbnailStorage storage.Storage
ImageSource imgsource.Source
CS3Source imgsource.Source
CS3Client gateway.GatewayAPIClient
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
}
// newOptions initializes the available default options.
@@ -71,14 +71,16 @@ func ThumbnailSource(val imgsource.Source) Option {
}
}
// CS3Source provides a function to set the CS3Source option
func CS3Source(val imgsource.Source) Option {
return func(o *Options) {
o.CS3Source = val
}
}
func CS3Client(c gateway.GatewayAPIClient) Option {
// GatewaySelector adds a grpc client selector for the gateway service
func GatewaySelector(val pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.CS3Client = c
o.GatewaySelector = val
}
}

View File

@@ -12,6 +12,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/golang-jwt/jwt/v4"
@@ -45,7 +46,7 @@ func NewService(opts ...Option) decorators.DecoratedService {
webdavSource: options.ImageSource,
cs3Source: options.CS3Source,
logger: logger,
cs3Client: options.CS3Client,
selector: options.GatewaySelector,
preprocessorOpts: PreprocessorOpts{
TxtFontFileMap: options.Config.Thumbnail.FontMapFile,
},
@@ -65,10 +66,11 @@ type Thumbnail struct {
webdavSource imgsource.Source
cs3Source imgsource.Source
logger log.Logger
cs3Client gateway.GatewayAPIClient
selector pool.Selectable[gateway.GatewayAPIClient]
preprocessorOpts PreprocessorOpts
}
// PreprocessorOpts holds the options for the preprocessor
type PreprocessorOpts struct {
TxtFontFileMap string
}
@@ -161,21 +163,24 @@ func (g Thumbnail) handleWebdavSource(ctx context.Context, req *thumbnailssvc.Ge
}
var auth, statPath string
if src.IsPublicLink {
q := imgURL.Query()
var rsp *gateway.AuthenticateResponse
client, err := g.selector.Next()
if err != nil {
return "", merrors.InternalServerError(g.serviceID, "could not select next gateway client: %s", err.Error())
}
if q.Get("signature") != "" && q.Get("expiration") != "" {
// Handle pre-signed public links
sig := q.Get("signature")
exp := q.Get("expiration")
rsp, err = g.cs3Client.Authenticate(ctx, &gateway.AuthenticateRequest{
rsp, err = client.Authenticate(ctx, &gateway.AuthenticateRequest{
Type: "publicshares",
ClientId: src.PublicLinkToken,
ClientSecret: strings.Join([]string{"signature", sig, exp}, "|"),
})
} else {
rsp, err = g.cs3Client.Authenticate(ctx, &gateway.AuthenticateRequest{
rsp, err = client.Authenticate(ctx, &gateway.AuthenticateRequest{
Type: "publicshares",
ClientId: src.PublicLinkToken,
// We pass an empty password because we expect non pre-signed public links
@@ -248,8 +253,12 @@ func (g Thumbnail) stat(path, auth string) (*provider.StatResponse, error) {
}
}
client, err := g.selector.Next()
if err != nil {
return nil, merrors.InternalServerError(g.serviceID, "could not select next gateway client: %s", err.Error())
}
req := &provider.StatRequest{Ref: &ref}
rsp, err := g.cs3Client.Stat(ctx, req)
rsp, err := client.Stat(ctx, req)
if err != nil {
g.logger.Error().Err(err).Str("path", path).Msg("could not stat file")
return nil, merrors.InternalServerError(g.serviceID, "could not stat file: %s", err.Error())

View File

@@ -11,6 +11,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/rhttp"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/owncloud/ocis/v2/services/thumbnails/pkg/config"
@@ -24,15 +25,17 @@ const (
TokenTransportHeader = "X-Reva-Transfer"
)
// CS3 implements a CS3 image source
type CS3 struct {
client gateway.GatewayAPIClient
insecure bool
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
insecure bool
}
func NewCS3Source(cfg config.Thumbnail, c gateway.GatewayAPIClient) CS3 {
// NewCS3Source configures a new CS3 image source
func NewCS3Source(cfg config.Thumbnail, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) CS3 {
return CS3{
client: c,
insecure: cfg.CS3AllowInsecure,
gatewaySelector: gatewaySelector,
insecure: cfg.CS3AllowInsecure,
}
}
@@ -51,8 +54,13 @@ func (s CS3) Get(ctx context.Context, path string) (io.ReadCloser, error) {
Path: path,
}
}
ctx = metadata.AppendToOutgoingContext(context.Background(), revactx.TokenHeader, auth)
rsp, err := s.client.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &ref})
gwc, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
}
rsp, err := gwc.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &ref})
if err != nil {
return nil, err

View File

@@ -11,6 +11,7 @@ import (
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/handlers"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/debug"
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
@@ -90,13 +91,14 @@ func Server(cfg *config.Config) *cli.Command {
if err != nil {
return err
}
gwclient, err := pool.GetGatewayServiceClient(
gatewaySelector, err := pool.GatewaySelector(
cfg.RevaGateway,
pool.WithTLSCACert(cfg.GRPCClientTLS.CACert),
pool.WithTLSMode(tm),
pool.WithRegistry(registry.GetRegistry()),
)
if err != nil {
return fmt.Errorf("could not get reva client: %s", err)
return fmt.Errorf("could not get reva client selector: %s", err)
}
hClient := ehsvc.NewEventHistoryService("com.owncloud.api.eventhistory", ogrpc.DefaultClient())
@@ -109,7 +111,7 @@ func Server(cfg *config.Config) *cli.Command {
http.Metrics(mtrcs),
http.Store(st),
http.Consumer(consumer),
http.Gateway(gwclient),
http.GatewaySelector(gatewaySelector),
http.History(hClient),
http.RegisteredEvents(_registeredEvents),
)

View File

@@ -5,6 +5,7 @@ import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
"github.com/owncloud/ocis/v2/services/userlog/pkg/config"
@@ -26,7 +27,7 @@ type Options struct {
Namespace string
Store store.Store
Consumer events.Consumer
GatewayClient gateway.GatewayAPIClient
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
HistoryClient ehsvc.EventHistoryService
RegisteredEvents []events.Unmarshaller
}
@@ -98,10 +99,10 @@ func Consumer(consumer events.Consumer) Option {
}
}
// Gateway provides a function to configure the gateway client
func Gateway(gw gateway.GatewayAPIClient) Option {
// GatewaySelector provides a function to configure the gateway client selector
func GatewaySelector(gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.GatewayClient = gw
o.GatewaySelector = gatewaySelector
}
}

View File

@@ -75,7 +75,7 @@ func Server(opts ...Option) (http.Service, error) {
svc.Store(options.Store),
svc.Config(options.Config),
svc.HistoryClient(options.HistoryClient),
svc.GatewayClient(options.GatewayClient),
svc.GatewaySelector(options.GatewaySelector),
svc.RegisteredEvents(options.RegisteredEvents),
)
if err != nil {

View File

@@ -16,6 +16,7 @@ import (
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/leonelquinteros/gotext"
@@ -52,7 +53,7 @@ type OC10Notification struct {
// Converter is responsible for converting eventhistory events to OC10Notifications
type Converter struct {
locale string
gwClient gateway.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
machineAuthAPIKey string
serviceName string
registeredEvents map[string]events.Unmarshaller
@@ -66,10 +67,10 @@ type Converter struct {
}
// NewConverter returns a new Converter
func NewConverter(loc string, gwc gateway.GatewayAPIClient, machineAuthAPIKey string, name string, translationPath string, registeredEvents map[string]events.Unmarshaller) *Converter {
func NewConverter(loc string, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], machineAuthAPIKey string, name string, translationPath string, registeredEvents map[string]events.Unmarshaller) *Converter {
return &Converter{
locale: loc,
gwClient: gwc,
gatewaySelector: gatewaySelector,
machineAuthAPIKey: machineAuthAPIKey,
serviceName: name,
registeredEvents: registeredEvents,
@@ -306,7 +307,7 @@ func (c *Converter) authenticate(usr *user.User) (context.Context, error) {
if ctx, ok := c.contexts[usr.GetId().GetOpaqueId()]; ok {
return ctx, nil
}
ctx, err := authenticate(usr, c.gwClient, c.machineAuthAPIKey)
ctx, err := authenticate(usr, c.gatewaySelector, c.machineAuthAPIKey)
if err == nil {
c.contexts[usr.GetId().GetOpaqueId()] = ctx
}
@@ -317,7 +318,7 @@ func (c *Converter) getSpace(ctx context.Context, spaceID string) (*storageprovi
if space, ok := c.spaces[spaceID]; ok {
return space, nil
}
space, err := getSpace(ctx, spaceID, c.gwClient)
space, err := getSpace(ctx, spaceID, c.gatewaySelector)
if err == nil {
c.spaces[spaceID] = space
}
@@ -328,7 +329,7 @@ func (c *Converter) getResource(ctx context.Context, resourceID *storageprovider
if r, ok := c.resources[resourceID.GetOpaqueId()]; ok {
return r, nil
}
resource, err := getResource(ctx, resourceID, c.gwClient)
resource, err := getResource(ctx, resourceID, c.gatewaySelector)
if err == nil {
c.resources[resourceID.GetOpaqueId()] = resource
}
@@ -339,7 +340,7 @@ func (c *Converter) getUser(ctx context.Context, userID *user.UserId) (*user.Use
if u, ok := c.users[userID.GetOpaqueId()]; ok {
return u, nil
}
usr, err := getUser(ctx, userID, c.gwClient)
usr, err := getUser(ctx, userID, c.gatewaySelector)
if err == nil {
c.users[userID.GetOpaqueId()] = usr
}

View File

@@ -31,7 +31,7 @@ func (ul *UserlogService) HandleGetEvents(w http.ResponseWriter, r *http.Request
return
}
conv := NewConverter(r.Header.Get(HeaderAcceptLanguage), ul.gwClient, ul.cfg.MachineAuthAPIKey, ul.cfg.Service.Name, ul.cfg.TranslationPath, ul.registeredEvents)
conv := NewConverter(r.Header.Get(HeaderAcceptLanguage), ul.gatewaySelector, ul.cfg.MachineAuthAPIKey, ul.cfg.Service.Name, ul.cfg.TranslationPath, ul.registeredEvents)
resp := GetEventResponseOC10{}
for _, e := range evs {

View File

@@ -3,6 +3,7 @@ package service
import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/go-chi/chi/v5"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
@@ -21,7 +22,7 @@ type Options struct {
Store store.Store
Config *config.Config
HistoryClient ehsvc.EventHistoryService
GatewayClient gateway.GatewayAPIClient
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
RegisteredEvents []events.Unmarshaller
}
@@ -67,10 +68,10 @@ func HistoryClient(hc ehsvc.EventHistoryService) Option {
}
}
// GatewayClient adds a grpc client for the gateway service
func GatewayClient(gwc gateway.GatewayAPIClient) Option {
// GatewaySelector adds a grpc client selector for the gateway service
func GatewaySelector(gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.GatewayClient = gwc
o.GatewaySelector = gatewaySelector
}
}

View File

@@ -14,6 +14,7 @@ import (
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/go-chi/chi/v5"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
@@ -31,7 +32,7 @@ type UserlogService struct {
store store.Store
cfg *config.Config
historyClient ehsvc.EventHistoryService
gwClient gateway.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
registeredEvents map[string]events.Unmarshaller
translationPath string
}
@@ -58,7 +59,7 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) {
store: o.Store,
cfg: o.Config,
historyClient: o.HistoryClient,
gwClient: o.GatewayClient,
gatewaySelector: o.GatewaySelector,
registeredEvents: make(map[string]events.Unmarshaller),
}
@@ -283,7 +284,7 @@ func (ul *UserlogService) findSpaceMembers(ctx context.Context, spaceID string,
return nil, errors.New("need authenticated context to find space members")
}
space, err := getSpace(ctx, spaceID, ul.gwClient)
space, err := getSpace(ctx, spaceID, ul.gatewaySelector)
if err != nil {
return nil, err
}
@@ -361,7 +362,7 @@ func (ul *UserlogService) resolveID(ctx context.Context, userid *user.UserId, gr
// resolves the users of a group
func (ul *UserlogService) resolveGroup(ctx context.Context, groupID string) ([]string, error) {
grp, err := getGroup(ctx, groupID, ul.gwClient)
grp, err := getGroup(ctx, groupID, ul.gatewaySelector)
if err != nil {
return nil, err
}
@@ -380,13 +381,13 @@ func (ul *UserlogService) impersonate(uid *user.UserId) context.Context {
return nil
}
u, err := getUser(context.Background(), uid, ul.gwClient)
u, err := getUser(context.Background(), uid, ul.gatewaySelector)
if err != nil {
ul.log.Error().Err(err).Msg("cannot get user")
return nil
}
ctx, err := authenticate(u, ul.gwClient, ul.cfg.MachineAuthAPIKey)
ctx, err := authenticate(u, ul.gatewaySelector, ul.cfg.MachineAuthAPIKey)
if err != nil {
ul.log.Error().Err(err).Str("userid", u.GetId().GetOpaqueId()).Msg("failed to impersonate user")
return nil
@@ -394,9 +395,14 @@ func (ul *UserlogService) impersonate(uid *user.UserId) context.Context {
return ctx
}
func authenticate(usr *user.User, gwc gateway.GatewayAPIClient, machineAuthAPIKey string) (context.Context, error) {
func authenticate(usr *user.User, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], machineAuthAPIKey string) (context.Context, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
ctx := revactx.ContextSetUser(context.Background(), usr)
authRes, err := gwc.Authenticate(ctx, &gateway.AuthenticateRequest{
authRes, err := gatewayClient.Authenticate(ctx, &gateway.AuthenticateRequest{
Type: "machine",
ClientId: "userid:" + usr.GetId().GetOpaqueId(),
ClientSecret: machineAuthAPIKey,
@@ -411,8 +417,13 @@ func authenticate(usr *user.User, gwc gateway.GatewayAPIClient, machineAuthAPIKe
return metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, authRes.Token), nil
}
func getSpace(ctx context.Context, spaceID string, gwc gateway.GatewayAPIClient) (*storageprovider.StorageSpace, error) {
res, err := gwc.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
func getSpace(ctx context.Context, spaceID string, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (*storageprovider.StorageSpace, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
res, err := gatewayClient.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
if err != nil {
return nil, err
}
@@ -428,8 +439,13 @@ func getSpace(ctx context.Context, spaceID string, gwc gateway.GatewayAPIClient)
return res.StorageSpaces[0], nil
}
func getUser(ctx context.Context, userid *user.UserId, gwc gateway.GatewayAPIClient) (*user.User, error) {
getUserResponse, err := gwc.GetUser(context.Background(), &user.GetUserRequest{
func getUser(ctx context.Context, userid *user.UserId, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (*user.User, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
getUserResponse, err := gatewayClient.GetUser(context.Background(), &user.GetUserRequest{
UserId: userid,
})
if err != nil {
@@ -443,8 +459,13 @@ func getUser(ctx context.Context, userid *user.UserId, gwc gateway.GatewayAPICli
return getUserResponse.GetUser(), nil
}
func getGroup(ctx context.Context, groupid string, gwc gateway.GatewayAPIClient) (*group.Group, error) {
r, err := gwc.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupid}})
func getGroup(ctx context.Context, groupid string, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (*group.Group, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
r, err := gatewayClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupid}})
if err != nil {
return nil, err
}
@@ -456,8 +477,13 @@ func getGroup(ctx context.Context, groupid string, gwc gateway.GatewayAPIClient)
return r.GetGroup(), nil
}
func getResource(ctx context.Context, resourceid *storageprovider.ResourceId, gwc gateway.GatewayAPIClient) (*storageprovider.ResourceInfo, error) {
res, err := gwc.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: resourceid}})
func getResource(ctx context.Context, resourceid *storageprovider.ResourceId, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (*storageprovider.ResourceInfo, error) {
gatewayClient, err := gatewaySelector.Next()
if err != nil {
return nil, err
}
res, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: resourceid}})
if err != nil {
return nil, err
}

View File

@@ -3,10 +3,23 @@ package service_test
import (
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
mRegistry "go-micro.dev/v4/registry"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func init() {
registry.Configure("memory")
r := registry.GetRegistry()
service := registry.BuildGRPCService("com.owncloud.api.gateway", "", "", "")
service.Nodes = []*mRegistry.Node{{
Address: "any",
}}
_ = r.Register(service)
}
func TestSearch(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Userlog service Suite")

View File

@@ -11,6 +11,7 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/store"
"github.com/cs3org/reva/v2/pkg/utils"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
@@ -27,6 +28,7 @@ import (
"github.com/test-go/testify/mock"
microevents "go-micro.dev/v4/events"
microstore "go-micro.dev/v4/store"
"google.golang.org/grpc"
)
var _ = Describe("UserlogService", func() {
@@ -37,7 +39,9 @@ var _ = Describe("UserlogService", func() {
bus testBus
sto microstore.Store
gwc cs3mocks.GatewayAPIClient
gatewayClient *cs3mocks.GatewayAPIClient
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
ehc mocks.EventHistoryService
)
@@ -45,15 +49,26 @@ var _ = Describe("UserlogService", func() {
var err error
sto = store.Create()
bus = testBus(make(chan events.Event))
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
"GatewaySelector",
"com.owncloud.api.gateway",
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
return gatewayClient
},
)
o := utils.AppendJSONToOpaque(nil, "grants", map[string]*provider.ResourcePermissions{"userid": {Stat: true}})
gwc.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&provider.ListStorageSpacesResponse{StorageSpaces: []*provider.StorageSpace{
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&provider.ListStorageSpacesResponse{StorageSpaces: []*provider.StorageSpace{
{
Opaque: o,
SpaceType: "project",
},
}, Status: &rpc.Status{Code: rpc.Code_CODE_OK}}, nil)
gwc.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{User: &user.User{Id: &user.UserId{OpaqueId: "userid"}}, Status: &rpc.Status{Code: rpc.Code_CODE_OK}}, nil)
gwc.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}}, nil)
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&user.GetUserResponse{User: &user.User{Id: &user.UserId{OpaqueId: "userid"}}, Status: &rpc.Status{Code: rpc.Code_CODE_OK}}, nil)
gatewayClient.On("Authenticate", mock.Anything, mock.Anything).Return(&gateway.AuthenticateResponse{Status: &rpc.Status{Code: rpc.Code_CODE_OK}}, nil)
ul, err = service.NewUserlogService(
service.Config(cfg),
@@ -61,7 +76,7 @@ var _ = Describe("UserlogService", func() {
service.Store(sto),
service.Logger(log.NewLogger()),
service.Mux(chi.NewMux()),
service.GatewayClient(&gwc),
service.GatewaySelector(gatewaySelector),
service.HistoryClient(&ehc),
service.RegisteredEvents([]events.Unmarshaller{
events.SpaceDisabled{},

View File

@@ -11,7 +11,7 @@ import (
"github.com/oklog/run"
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/users/pkg/config"
@@ -43,10 +43,6 @@ func Server(cfg *config.Config) *cli.Command {
defer cancel()
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rcfg := revaconfig.UsersConfigFromStruct(cfg)
// the reva runtime calls os.Exit in the case of a failure and there is no way for the oCIS
// runtime to catch it and restart a reva service. Therefore we need to ensure the service has
// everything it needs, before starting the service.
@@ -60,7 +56,15 @@ func Server(cfg *config.Config) *cli.Command {
}
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.UsersConfigFromStruct(cfg)
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,
runtime.WithLogger(&logger.Logger),
runtime.WithRegistry(reg),
)
return nil
}, func(err error) {
logger.Error().
@@ -90,15 +94,9 @@ func Server(cfg *config.Config) *cli.Command {
sync.Trap(&gr, cancel)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc service")
}
return gr.Run()

View File

@@ -82,7 +82,7 @@ func DefaultConfig() *config.Config {
Asset: config.Asset{
Path: filepath.Join(defaults.BaseDataPath(), "web/assets"),
},
GatewayAddress: "127.0.0.1:9142",
GatewayAddress: "com.owncloud.api.gateway",
Web: config.Web{
Path: "",
ThemeServer: "https://localhost:9200",

View File

@@ -7,6 +7,7 @@ import (
chimiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/cors"
"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/service/http"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
webmid "github.com/owncloud/ocis/v2/services/web/pkg/middleware"
@@ -35,7 +36,7 @@ func Server(opts ...Option) (http.Service, error) {
return http.Service{}, fmt.Errorf("could not initialize http service: %w", err)
}
client, err := pool.GetGatewayServiceClient(options.Config.GatewayAddress)
gatewaySelector, err := pool.GatewaySelector(options.Config.GatewayAddress, pool.WithRegistry(registry.GetRegistry()))
if err != nil {
return http.Service{}, err
}
@@ -43,7 +44,7 @@ func Server(opts ...Option) (http.Service, error) {
handle := svc.NewService(
svc.Logger(options.Logger),
svc.Config(options.Config),
svc.GatewayClient(client),
svc.GatewaySelector(gatewaySelector),
svc.Middleware(
chimiddleware.RealIP,
chimiddleware.RequestID,

View File

@@ -26,8 +26,14 @@ var (
// UploadLogo implements the endpoint to upload a custom logo for the oCIS instance.
func (p Web) UploadLogo(w http.ResponseWriter, r *http.Request) {
gatewayClient, err := p.gatewaySelector.Next()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
user := revactx.ContextMustGetUser(r.Context())
rsp, err := p.gatewayClient.CheckPermission(r.Context(), &permissionsapi.CheckPermissionRequest{
rsp, err := gatewayClient.CheckPermission(r.Context(), &permissionsapi.CheckPermissionRequest{
Permission: "Logo.Write",
SubjectRef: &permissionsapi.SubjectReference{
Spec: &permissionsapi.SubjectReference_UserId{
@@ -79,8 +85,14 @@ func (p Web) UploadLogo(w http.ResponseWriter, r *http.Request) {
// ResetLogo implements the endpoint to reset the instance logo.
// The config will be changed back to use the embedded logo asset.
func (p Web) ResetLogo(w http.ResponseWriter, r *http.Request) {
gatewayClient, err := p.gatewaySelector.Next()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
user := revactx.ContextMustGetUser(r.Context())
rsp, err := p.gatewayClient.CheckPermission(r.Context(), &permissionsapi.CheckPermissionRequest{
rsp, err := gatewayClient.CheckPermission(r.Context(), &permissionsapi.CheckPermissionRequest{
Permission: "Logo.Write",
SubjectRef: &permissionsapi.SubjectReference{
Spec: &permissionsapi.SubjectReference_UserId{

View File

@@ -4,6 +4,7 @@ import (
"net/http"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/web/pkg/config"
)
@@ -13,10 +14,10 @@ type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
Logger log.Logger
Config *config.Config
Middleware []func(http.Handler) http.Handler
GatewayClient gateway.GatewayAPIClient
Logger log.Logger
Config *config.Config
Middleware []func(http.Handler) http.Handler
GatewaySelector pool.Selectable[gateway.GatewayAPIClient]
}
// newOptions initializes the available default options.
@@ -51,9 +52,9 @@ func Middleware(val ...func(http.Handler) http.Handler) Option {
}
}
// GatewayClient provides a function to set the GatewayClient option.
func GatewayClient(client gateway.GatewayAPIClient) Option {
// GatewaySelector provides a function to set the gatewaySelector option.
func GatewaySelector(gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) Option {
return func(o *Options) {
o.GatewayClient = client
o.GatewaySelector = gatewaySelector
}
}

Some files were not shown because too many files have changed in this diff Show More