From 084c1b56a2f04dfe13556262fd1327b0d5d8933e Mon Sep 17 00:00:00 2001 From: Hugo Labrador Date: Tue, 10 Oct 2023 14:59:36 +0200 Subject: [PATCH] New observability + general refactor of http/grpc clients (#4166) * remove unused fs and tracing * add helloworld example and fix auth logic to bail out early * remove hack on appctx and add traceid * configurable prom collectors * grpc reflection working * wire http traffic * intrument outgoing grpc calls * add stuff * merge appctx and ctx * refactor rhttp to httpclient * tidy go.mod * remove drone tests * add changelog * fix test * go 1.21 * pass tests * fix sql tests * go fmt * more linters * make all linters happy * update docs * add back ceph example * remove otelhttp library * remove files and add tests * align with upstream --- .gitignore | 1 + changelog/unreleased/observability.md | 6 + cmd/reva/download.go | 8 +- cmd/reva/grpc.go | 7 +- cmd/reva/main.go | 13 +- cmd/reva/upload.go | 10 +- cmd/revad/runtime/grpc.go | 27 +- cmd/revad/runtime/http.go | 4 + cmd/revad/runtime/loader.go | 1 + cmd/revad/runtime/runtime.go | 10 +- .../grpc/services/ocminvitemanager/_index.md | 2 +- .../grpc/services/ocmshareprovider/_index.md | 2 +- .../grpc/services/storageprovider/_index.md | 18 +- .../http/services/appprovider/_index.md | 2 +- .../config/http/services/archiver/_index.md | 2 +- .../http/services/datagateway/_index.md | 2 +- .../http/services/ocmprovider/_index.md | 18 +- .../config/http/services/overleaf/_index.md | 8 +- .../http/services/owncloud/ocdav/_index.md | 4 +- .../packages/auth/manager/oidc/_index.md | 16 +- .../ocm/provider/authorizer/mentix/_index.md | 2 +- .../packages/storage/registry/_index.md | 7 + .../storage/registry/dynamic/_index.md | 26 + .../packages/user/manager/nextcloud/_index.md | 2 +- examples/helloworld/revad.toml | 15 + examples/pingpong/revad.toml | 12 + go.mod | 26 +- go.sum | 53 +- internal/grpc/interceptors/appctx/appctx.go | 26 +- internal/grpc/interceptors/auth/auth.go | 25 +- internal/grpc/interceptors/auth/scope.go | 3 +- internal/grpc/interceptors/log/log.go | 5 +- internal/grpc/interceptors/metrics/metrics.go | 51 ++ internal/grpc/interceptors/token/token.go | 14 +- internal/grpc/interceptors/trace/trace.go | 84 +++ .../grpc/interceptors/useragent/useragent.go | 10 +- .../services/appregistry/appregistry_test.go | 18 +- internal/grpc/services/datatx/datatx.go | 6 +- internal/grpc/services/gateway/appprovider.go | 7 +- .../grpc/services/gateway/authprovider.go | 13 +- .../grpc/services/gateway/ocmshareprovider.go | 4 +- .../grpc/services/gateway/storageprovider.go | 10 +- .../services/gateway/usershareprovider.go | 6 +- .../services/gateway/webdavstorageprovider.go | 13 +- .../grpc/services/helloworld/helloworld.go | 2 +- internal/grpc/services/loader/loader.go | 1 + .../ocminvitemanager/ocminvitemanager.go | 13 +- .../ocmshareprovider/ocmshareprovider.go | 19 +- internal/grpc/services/pingpong/pingpong.go | 135 ++++ .../services/pingpong/proto/pingpong.pb.go | 364 +++++++++ .../services/pingpong/proto/pingpong.proto | 46 ++ .../pingpong/proto/pingpong_grpc.pb.go | 142 ++++ .../publicshareprovider.go | 15 +- .../publicstorageprovider.go | 41 - .../storageprovider/storageprovider.go | 19 - .../usershareprovider/usershareprovider.go | 7 +- internal/http/interceptors/appctx/appctx.go | 14 +- internal/http/interceptors/auth/auth.go | 24 +- .../auth/token/strategy/header/header.go | 5 +- .../tokenwriter/strategy/header/header.go | 5 +- internal/http/interceptors/metrics/metrics.go | 106 +++ internal/http/interceptors/trace/trace.go | 68 ++ .../http/interceptors/trace/trace_test.go | 74 ++ .../http/services/appprovider/appprovider.go | 12 +- internal/http/services/archiver/handler.go | 8 +- .../http/services/datagateway/datagateway.go | 23 +- internal/http/services/loader/loader.go | 1 + internal/http/services/ocmd/shares.go | 8 +- internal/http/services/overleaf/overleaf.go | 11 +- internal/http/services/owncloud/ocdav/copy.go | 18 +- internal/http/services/owncloud/ocdav/dav.go | 18 +- .../http/services/owncloud/ocdav/delete.go | 7 - .../http/services/owncloud/ocdav/download.go | 20 +- internal/http/services/owncloud/ocdav/get.go | 12 +- internal/http/services/owncloud/ocdav/head.go | 9 +- .../http/services/owncloud/ocdav/mkcol.go | 9 +- internal/http/services/owncloud/ocdav/move.go | 9 +- .../http/services/owncloud/ocdav/ocdav.go | 16 +- .../http/services/owncloud/ocdav/propfind.go | 33 +- .../http/services/owncloud/ocdav/proppatch.go | 15 +- .../services/owncloud/ocdav/publicfile.go | 9 +- internal/http/services/owncloud/ocdav/put.go | 15 +- .../http/services/owncloud/ocdav/report.go | 3 +- internal/http/services/owncloud/ocdav/tpc.go | 5 +- .../http/services/owncloud/ocdav/trashbin.go | 17 +- internal/http/services/owncloud/ocdav/tus.go | 12 +- .../http/services/owncloud/ocdav/versions.go | 16 +- internal/http/services/owncloud/ocs/cache.go | 12 +- .../ocs/handlers/apps/sharing/shares/group.go | 5 +- .../handlers/apps/sharing/shares/public.go | 6 +- .../handlers/apps/sharing/shares/shares.go | 4 +- .../ocs/handlers/apps/sharing/shares/user.go | 6 +- .../handlers/cloud/capabilities/uploads.go | 5 +- .../owncloud/ocs/handlers/cloud/user/user.go | 5 +- .../ocs/handlers/cloud/users/users.go | 3 +- internal/http/services/pingpong/pingpong.go | 140 ++++ .../http/services/prometheus/prometheus.go | 33 +- .../services/reverseproxy/reverseproxy.go | 6 +- internal/http/services/sciencemesh/token.go | 4 +- pkg/app/provider/wopi/wopi.go | 36 +- pkg/appauth/manager/json/json.go | 9 +- pkg/appauth/manager/json/json_test.go | 11 +- pkg/{ctx => appctx}/agentctx.go | 2 +- pkg/{ctx => appctx}/agentctx_test.go | 2 +- pkg/appctx/{appctx.go => logger.go} | 3 - pkg/{ctx => appctx}/pathctx.go | 6 +- pkg/{ctx => appctx}/tokenctx.go | 2 +- pkg/{ctx => appctx}/userctx.go | 2 +- pkg/auth/manager/nextcloud/nextcloud_test.go | 9 +- pkg/auth/manager/oidc/oidc.go | 18 +- pkg/cbox/utils/tokenmanagement.go | 13 +- pkg/datatx/manager/rclone/rclone.go | 8 +- pkg/eosclient/eosbinary/eosbinary.go | 6 +- pkg/httpclient/httpclient.go | 135 ++++ pkg/ocm/client/client.go | 10 +- pkg/ocm/provider/authorizer/mentix/mentix.go | 14 +- .../repository/nextcloud/nextcloud_test.go | 9 +- pkg/ocm/share/sender/sender.go | 6 +- pkg/ocm/storage/outcoming/ocm.go | 19 +- pkg/preferences/memory/memory.go | 6 +- pkg/preferences/sql/sql.go | 6 +- pkg/prom/base/base.go | 39 + pkg/prom/loader/loader.go | 27 + pkg/prom/registry/registry.go | 38 + pkg/rgrpc/status/status.go | 5 +- pkg/rgrpc/todo/pool/pool.go | 21 - pkg/rhttp/client.go | 69 -- pkg/rhttp/option.go | 74 -- pkg/rhttp/rhttp.go | 21 +- pkg/sdk/common/net/net.go | 4 +- pkg/share/cache/warmup/cbox/cbox.go | 5 +- pkg/share/manager/json/json.go | 21 +- pkg/share/manager/memory/memory.go | 21 +- pkg/share/manager/sql/conversions.go | 262 +++++++ pkg/share/manager/sql/mocks/UserConverter.go | 78 ++ pkg/share/manager/sql/sql.go | 439 +++++------ .../manager/sql/sql_suite_test.go} | 14 +- pkg/share/manager/sql/sql_test.go | 274 +++++++ pkg/share/manager/sql/test.db | Bin 0 -> 655360 bytes pkg/storage/favorite/memory/memory_test.go | 8 +- pkg/storage/favorite/sql/sql.go | 9 +- pkg/storage/fs/cback/cback.go | 16 +- pkg/storage/fs/cephfs/cephfs.go | 11 +- pkg/storage/fs/cephfs/chunking.go | 122 ++- pkg/storage/fs/cephfs/connections.go | 11 +- pkg/storage/fs/cephfs/upload.go | 336 ++++++++- pkg/storage/fs/cephfs/user.go | 9 +- pkg/storage/fs/loader/loader.go | 1 - pkg/storage/fs/nextcloud/nextcloud.go | 4 +- pkg/storage/fs/nextcloud/nextcloud_test.go | 9 +- pkg/storage/fs/s3/s3.go | 702 ------------------ pkg/storage/registry/dynamic/dynamic_test.go | 8 +- .../registry/dynamic/rewriter/userrewriter.go | 4 +- pkg/storage/registry/static/static.go | 5 +- pkg/storage/registry/static/static_test.go | 7 +- pkg/storage/utils/downloader/downloader.go | 10 +- pkg/storage/utils/eosfs/eosfs.go | 12 +- pkg/storage/utils/eosfs/eosfs_test.go | 5 +- pkg/storage/utils/localfs/localfs.go | 7 +- pkg/storage/utils/localfs/upload.go | 6 +- pkg/trace/trace.go | 93 +-- pkg/user/manager/nextcloud/nextcloud.go | 3 +- pkg/user/manager/nextcloud/nextcloud_test.go | 9 +- tests/helpers/helpers.go | 14 +- tests/integration/grpc/ocm_invitation_test.go | 13 +- tests/integration/grpc/ocm_share_test.go | 6 +- .../integration/grpc/storageprovider_test.go | 8 +- tests/integration/grpc/userprovider_test.go | 9 +- 168 files changed, 3443 insertions(+), 1992 deletions(-) create mode 100644 changelog/unreleased/observability.md create mode 100644 docs/content/en/docs/config/packages/storage/registry/_index.md create mode 100644 docs/content/en/docs/config/packages/storage/registry/dynamic/_index.md create mode 100644 examples/helloworld/revad.toml create mode 100644 examples/pingpong/revad.toml create mode 100644 internal/grpc/interceptors/metrics/metrics.go create mode 100644 internal/grpc/interceptors/trace/trace.go create mode 100644 internal/grpc/services/pingpong/pingpong.go create mode 100644 internal/grpc/services/pingpong/proto/pingpong.pb.go create mode 100644 internal/grpc/services/pingpong/proto/pingpong.proto create mode 100644 internal/grpc/services/pingpong/proto/pingpong_grpc.pb.go create mode 100644 internal/http/interceptors/metrics/metrics.go create mode 100644 internal/http/interceptors/trace/trace.go create mode 100644 internal/http/interceptors/trace/trace_test.go create mode 100644 internal/http/services/pingpong/pingpong.go rename pkg/{ctx => appctx}/agentctx.go (99%) rename pkg/{ctx => appctx}/agentctx_test.go (99%) rename pkg/appctx/{appctx.go => logger.go} (90%) rename pkg/{ctx => appctx}/pathctx.go (97%) rename pkg/{ctx => appctx}/tokenctx.go (99%) rename pkg/{ctx => appctx}/userctx.go (99%) create mode 100644 pkg/httpclient/httpclient.go create mode 100644 pkg/prom/base/base.go create mode 100644 pkg/prom/loader/loader.go create mode 100644 pkg/prom/registry/registry.go delete mode 100644 pkg/rhttp/client.go delete mode 100644 pkg/rhttp/option.go create mode 100644 pkg/share/manager/sql/conversions.go create mode 100644 pkg/share/manager/sql/mocks/UserConverter.go rename pkg/{storage/fs/s3/upload.go => share/manager/sql/sql_suite_test.go} (65%) create mode 100644 pkg/share/manager/sql/sql_test.go create mode 100644 pkg/share/manager/sql/test.db delete mode 100644 pkg/storage/fs/s3/s3.go diff --git a/.gitignore b/.gitignore index 119d753fd0..45b92b2ad3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ cmd/revad/revad cmd/revad/revad.pid cmd/reva/reva +cmd/revad/main/main tools/release/release # Ignore pid files diff --git a/changelog/unreleased/observability.md b/changelog/unreleased/observability.md new file mode 100644 index 0000000000..9bb1640c61 --- /dev/null +++ b/changelog/unreleased/observability.md @@ -0,0 +1,6 @@ +Enhancement: Add better observability with metrics and traces + +Adds prometheus collectors that can be registered dynamically and also +refactors the http and grpc clients and servers to propage trace info. + +https://github.com/cs3org/reva/pull/4166 diff --git a/cmd/reva/download.go b/cmd/reva/download.go index b870e57d61..1e2eabf574 100644 --- a/cmd/reva/download.go +++ b/cmd/reva/download.go @@ -29,9 +29,9 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/utils" "github.com/pkg/errors" "github.com/studio-b12/gowebdav" @@ -95,7 +95,7 @@ func downloadCommand() *command { dataServerURL := p.DownloadEndpoint // TODO(labkode): do a protocol switch - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, dataServerURL, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, dataServerURL, nil) if err != nil { return err } @@ -183,7 +183,7 @@ func checkDownloadWebdavRef(protocols []*gateway.FileDownloadProtocol) (io.Reade } c := gowebdav.NewClient(p.DownloadEndpoint, "", "") - c.SetHeader(ctxpkg.TokenHeader, token) + c.SetHeader(appctx.TokenHeader, token) reader, err := c.ReadStream(filePath) if err != nil { diff --git a/cmd/reva/grpc.go b/cmd/reva/grpc.go index 10d0400227..b3a76d7c8e 100644 --- a/cmd/reva/grpc.go +++ b/cmd/reva/grpc.go @@ -26,7 +26,8 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" + "google.golang.org/grpc" "google.golang.org/grpc/credentials" ins "google.golang.org/grpc/credentials/insecure" @@ -41,8 +42,8 @@ func getAuthContext() context.Context { log.Println(err) return ctx } - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) return ctx } diff --git a/cmd/reva/main.go b/cmd/reva/main.go index d9188f2265..3d1bfe22b5 100644 --- a/cmd/reva/main.go +++ b/cmd/reva/main.go @@ -19,6 +19,7 @@ package main import ( + "crypto/tls" "flag" "fmt" "net/http" @@ -27,7 +28,7 @@ import ( "time" "github.com/c-bata/go-prompt" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" ) var ( @@ -40,7 +41,7 @@ var ( gitCommit, buildDate, version, goVersion string - client *http.Client + client *httpclient.Client commands = []*command{ versionCommand(), @@ -124,9 +125,11 @@ func main() { } } - client = rhttp.GetHTTPClient( - rhttp.Insecure(insecuredatagateway), - rhttp.Timeout(time.Duration(timeout*int64(time.Hour))), + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: insecuredatagateway}} + + client = httpclient.New( + httpclient.RoundTripper(tr), + httpclient.Timeout(time.Duration(timeout*int64(time.Hour))), ) generateMainUsage() diff --git a/cmd/reva/upload.go b/cmd/reva/upload.go index 09eebc457f..eda27893a5 100644 --- a/cmd/reva/upload.go +++ b/cmd/reva/upload.go @@ -35,10 +35,10 @@ import ( // TODO(labkode): this should not come from this package. "github.com/cs3org/reva/internal/grpc/services/storageprovider" "github.com/cs3org/reva/internal/http/services/datagateway" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/crypto" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/utils" "github.com/eventials/go-tus" "github.com/eventials/go-tus/memorystore" @@ -147,7 +147,7 @@ func uploadCommand() *command { dataServerURL := p.UploadEndpoint if *protocolFlag == "simple" { - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, dataServerURL, fd) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, dataServerURL, fd) if err != nil { return err } @@ -170,7 +170,7 @@ func uploadCommand() *command { // create the tus client. c := tus.DefaultConfig() c.Resume = true - c.HttpClient = client + c.HttpClient = client.GetNativeHTTP() c.Store, err = memorystore.NewMemoryStore() if err != nil { return err @@ -268,7 +268,7 @@ func checkUploadWebdavRef(protocols []*gateway.FileUploadProtocol, md os.FileInf } c := gowebdav.NewClient(p.UploadEndpoint, "", "") - c.SetHeader(ctxpkg.TokenHeader, token) + c.SetHeader(appctx.TokenHeader, token) c.SetHeader("Upload-Length", strconv.FormatInt(md.Size(), 10)) if err = c.WriteStream(filePath, fd, 0700); err != nil { diff --git a/cmd/revad/runtime/grpc.go b/cmd/revad/runtime/grpc.go index 5cd1b4b195..c71b2f5ee5 100644 --- a/cmd/revad/runtime/grpc.go +++ b/cmd/revad/runtime/grpc.go @@ -24,14 +24,14 @@ import ( "github.com/cs3org/reva/internal/grpc/interceptors/appctx" "github.com/cs3org/reva/internal/grpc/interceptors/auth" "github.com/cs3org/reva/internal/grpc/interceptors/log" + "github.com/cs3org/reva/internal/grpc/interceptors/metrics" "github.com/cs3org/reva/internal/grpc/interceptors/recovery" "github.com/cs3org/reva/internal/grpc/interceptors/token" + "github.com/cs3org/reva/internal/grpc/interceptors/trace" "github.com/cs3org/reva/internal/grpc/interceptors/useragent" "github.com/cs3org/reva/pkg/rgrpc" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/pkg/errors" "github.com/rs/zerolog" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" ) @@ -75,24 +75,21 @@ func initGRPCInterceptors(conf map[string]map[string]any, unprotected []string, return nil, nil, errors.Wrap(err, "error creating unary auth interceptor") } - unaryInterceptors := []grpc.UnaryServerInterceptor{authUnary} + unaryInterceptors := []grpc.UnaryServerInterceptor{} for _, t := range unaryTriples { unaryInterceptors = append(unaryInterceptors, t.Interceptor) logger.Info().Msgf("rgrpc: chaining grpc unary interceptor %s with priority %d", t.Name, t.Priority) } - unaryInterceptors = append(unaryInterceptors, - otelgrpc.UnaryServerInterceptor( - otelgrpc.WithTracerProvider(rtrace.Provider), - otelgrpc.WithPropagators(rtrace.Propagator)), - ) - unaryInterceptors = append([]grpc.UnaryServerInterceptor{ + trace.NewUnary(), + metrics.NewUnary(), appctx.NewUnary(*logger), token.NewUnary(), useragent.NewUnary(), log.NewUnary(), recovery.NewUnary(), + authUnary, }, unaryInterceptors...) streamTriples := []*streamInterceptorTriple{} @@ -131,7 +128,8 @@ func initGRPCInterceptors(conf map[string]map[string]any, unprotected []string, } streamInterceptors = append([]grpc.StreamServerInterceptor{ - authStream, + trace.NewStream(), + metrics.NewStream(), appctx.NewStream(*logger), token.NewStream(), useragent.NewStream(), @@ -142,7 +140,14 @@ func initGRPCInterceptors(conf map[string]map[string]any, unprotected []string, return unaryInterceptors, streamInterceptors, nil } -func grpcUnprotected(s map[string]rgrpc.Service) (unprotected []string) { +func grpcUnprotected(reflection bool, s map[string]rgrpc.Service) (unprotected []string) { + if reflection { + // TODO(labkode): do not hardcode service endpoint and try to obtain from reflection library + unprotected = append(unprotected, + "/grpc.reflection.v1alpha.ServerReflection", + "/grpc.reflection.v1.ServerReflection", + ) + } for _, svc := range s { unprotected = append(unprotected, svc.UnprotectedEndpoints()...) } diff --git a/cmd/revad/runtime/http.go b/cmd/revad/runtime/http.go index 7568c174ea..5cbb2db9f4 100644 --- a/cmd/revad/runtime/http.go +++ b/cmd/revad/runtime/http.go @@ -25,6 +25,8 @@ import ( "github.com/cs3org/reva/internal/http/interceptors/appctx" "github.com/cs3org/reva/internal/http/interceptors/auth" "github.com/cs3org/reva/internal/http/interceptors/log" + "github.com/cs3org/reva/internal/http/interceptors/metrics" + "github.com/cs3org/reva/internal/http/interceptors/trace" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -70,6 +72,8 @@ func initHTTPMiddlewares(conf map[string]map[string]any, unprotected []string, l authMiddle, log.New(), appctx.New(*logger), + metrics.New(), + trace.New(), } for _, triple := range triples { diff --git a/cmd/revad/runtime/loader.go b/cmd/revad/runtime/loader.go index 163b66d823..23788f24a8 100644 --- a/cmd/revad/runtime/loader.go +++ b/cmd/revad/runtime/loader.go @@ -43,6 +43,7 @@ import ( _ "github.com/cs3org/reva/pkg/ocm/share/repository/loader" _ "github.com/cs3org/reva/pkg/permission/manager/loader" _ "github.com/cs3org/reva/pkg/preferences/loader" + _ "github.com/cs3org/reva/pkg/prom/loader" _ "github.com/cs3org/reva/pkg/publicshare/manager/loader" _ "github.com/cs3org/reva/pkg/rhttp/datatx/manager/loader" _ "github.com/cs3org/reva/pkg/share/cache/loader" diff --git a/cmd/revad/runtime/runtime.go b/cmd/revad/runtime/runtime.go index 40b1df3670..6dbdfcc4a6 100644 --- a/cmd/revad/runtime/runtime.go +++ b/cmd/revad/runtime/runtime.go @@ -41,7 +41,6 @@ import ( "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rserverless" "github.com/cs3org/reva/pkg/sharedconf" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils/list" "github.com/cs3org/reva/pkg/utils/maps" netutil "github.com/cs3org/reva/pkg/utils/net" @@ -86,7 +85,6 @@ func New(config *config.Config, opt ...Option) (*Reva, error) { if err := initCPUCount(config.Core, log); err != nil { return nil, err } - initTracing(config.Core) if opts.PidFile == "" { return nil, errors.New("pid file not provided") @@ -347,12 +345,6 @@ func handlePIDFlag(l *zerolog.Logger, pidFile string) (*grace.Watcher, error) { return w, nil } -func initTracing(conf *config.Core) { - if conf.TracingEnabled { - rtrace.SetTraceProvider(conf.TracingCollector, conf.TracingEndpoint, conf.TracingServiceName) - } -} - // adjustCPU parses string cpu and sets GOMAXPROCS // according to its value. It accepts either // a number (e.g. 3) or a percent (e.g. 50%). @@ -411,7 +403,7 @@ func newServers(ctx context.Context, grpc []*config.GRPC, http []*config.HTTP, l if err != nil { return nil, err } - unaryChain, streamChain, err := initGRPCInterceptors(cfg.Interceptors, grpcUnprotected(services), log) + unaryChain, streamChain, err := initGRPCInterceptors(cfg.Interceptors, grpcUnprotected(cfg.EnableReflection, services), log) if err != nil { return nil, err } diff --git a/docs/content/en/docs/config/grpc/services/ocminvitemanager/_index.md b/docs/content/en/docs/config/grpc/services/ocminvitemanager/_index.md index 871faa3ce8..363d33b540 100644 --- a/docs/content/en/docs/config/grpc/services/ocminvitemanager/_index.md +++ b/docs/content/en/docs/config/grpc/services/ocminvitemanager/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="provider_domain" type="string" default="The same domain registered in the provider authorizer" %}} - [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/ocminvitemanager/ocminvitemanager.go#L62) + [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/ocminvitemanager/ocminvitemanager.go#L61) {{< highlight toml >}} [grpc.services.ocminvitemanager] provider_domain = "The same domain registered in the provider authorizer" diff --git a/docs/content/en/docs/config/grpc/services/ocmshareprovider/_index.md b/docs/content/en/docs/config/grpc/services/ocmshareprovider/_index.md index 08235771f3..f68b1ea656 100644 --- a/docs/content/en/docs/config/grpc/services/ocmshareprovider/_index.md +++ b/docs/content/en/docs/config/grpc/services/ocmshareprovider/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="provider_domain" type="string" default="The same domain registered in the provider authorizer" %}} - [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/ocmshareprovider/ocmshareprovider.go#L70) + [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/ocmshareprovider/ocmshareprovider.go#L71) {{< highlight toml >}} [grpc.services.ocmshareprovider] provider_domain = "The same domain registered in the provider authorizer" diff --git a/docs/content/en/docs/config/grpc/services/storageprovider/_index.md b/docs/content/en/docs/config/grpc/services/storageprovider/_index.md index ecd6f8eb34..6c1b9fbb75 100644 --- a/docs/content/en/docs/config/grpc/services/storageprovider/_index.md +++ b/docs/content/en/docs/config/grpc/services/storageprovider/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="mount_path" type="string" default="/" %}} -The path where the file system would be mounted. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L63) +The path where the file system would be mounted. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L61) {{< highlight toml >}} [grpc.services.storageprovider] mount_path = "/" @@ -17,7 +17,7 @@ mount_path = "/" {{% /dir %}} {{% dir name="mount_id" type="string" default="-" %}} -The ID of the mounted file system. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L64) +The ID of the mounted file system. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L62) {{< highlight toml >}} [grpc.services.storageprovider] mount_id = "-" @@ -25,7 +25,7 @@ mount_id = "-" {{% /dir %}} {{% dir name="driver" type="string" default="localhome" %}} -The storage driver to be used. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L65) +The storage driver to be used. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L63) {{< highlight toml >}} [grpc.services.storageprovider] driver = "localhome" @@ -33,7 +33,7 @@ driver = "localhome" {{% /dir %}} {{% dir name="drivers" type="map[string]map[string]interface{}" default="localhome" %}} - [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L66) + [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L64) {{< highlight toml >}} [grpc.services.storageprovider.drivers.localhome] root = "/var/tmp/reva/" @@ -44,7 +44,7 @@ user_layout = "{{.Username}}" {{% /dir %}} {{% dir name="tmp_folder" type="string" default="/var/tmp" %}} -Path to temporary folder. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L67) +Path to temporary folder. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L65) {{< highlight toml >}} [grpc.services.storageprovider] tmp_folder = "/var/tmp" @@ -52,7 +52,7 @@ tmp_folder = "/var/tmp" {{% /dir %}} {{% dir name="data_server_url" type="string" default="http://localhost/data" %}} -The URL for the data server. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L68) +The URL for the data server. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L66) {{< highlight toml >}} [grpc.services.storageprovider] data_server_url = "http://localhost/data" @@ -60,7 +60,7 @@ data_server_url = "http://localhost/data" {{% /dir %}} {{% dir name="expose_data_server" type="bool" default=false %}} -Whether to expose data server. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L69) +Whether to expose data server. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L67) {{< highlight toml >}} [grpc.services.storageprovider] expose_data_server = false @@ -68,7 +68,7 @@ expose_data_server = false {{% /dir %}} {{% dir name="available_checksums" type="map[string]uint32" default=nil %}} -List of available checksums. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L70) +List of available checksums. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L68) {{< highlight toml >}} [grpc.services.storageprovider] available_checksums = nil @@ -76,7 +76,7 @@ available_checksums = nil {{% /dir %}} {{% dir name="custom_mime_types_json" type="string" default="nil" %}} -An optional mapping file with the list of supported custom file extensions and corresponding mime types. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L71) +An optional mapping file with the list of supported custom file extensions and corresponding mime types. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/storageprovider/storageprovider.go#L69) {{< highlight toml >}} [grpc.services.storageprovider] custom_mime_types_json = "nil" diff --git a/docs/content/en/docs/config/http/services/appprovider/_index.md b/docs/content/en/docs/config/http/services/appprovider/_index.md index bda4901bfc..9c0b7d6059 100644 --- a/docs/content/en/docs/config/http/services/appprovider/_index.md +++ b/docs/content/en/docs/config/http/services/appprovider/_index.md @@ -9,7 +9,7 @@ description: > # _struct: Config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/appprovider/appprovider.go#L56) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/appprovider/appprovider.go#L57) {{< highlight toml >}} [http.services.appprovider] insecure = false diff --git a/docs/content/en/docs/config/http/services/archiver/_index.md b/docs/content/en/docs/config/http/services/archiver/_index.md index 56a4f4f622..391e9a23e0 100644 --- a/docs/content/en/docs/config/http/services/archiver/_index.md +++ b/docs/content/en/docs/config/http/services/archiver/_index.md @@ -9,7 +9,7 @@ description: > # _struct: Config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/archiver/handler.go#L63) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/archiver/handler.go#L64) {{< highlight toml >}} [http.services.archiver] insecure = false diff --git a/docs/content/en/docs/config/http/services/datagateway/_index.md b/docs/content/en/docs/config/http/services/datagateway/_index.md index e293489e5d..2e70830e53 100644 --- a/docs/content/en/docs/config/http/services/datagateway/_index.md +++ b/docs/content/en/docs/config/http/services/datagateway/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/datagateway/datagateway.go#L61) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/datagateway/datagateway.go#L62) {{< highlight toml >}} [http.services.datagateway] insecure = false diff --git a/docs/content/en/docs/config/http/services/ocmprovider/_index.md b/docs/content/en/docs/config/http/services/ocmprovider/_index.md index ca19a1691f..0e76159136 100644 --- a/docs/content/en/docs/config/http/services/ocmprovider/_index.md +++ b/docs/content/en/docs/config/http/services/ocmprovider/_index.md @@ -9,23 +9,23 @@ description: > # _struct: config_ {{% dir name="ocm_prefix" type="string" default="ocm" %}} -The prefix URL where the OCM API is served. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L39) +The prefix URL where the OCM API is served. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L40) {{< highlight toml >}} [http.services.ocmprovider] ocm_prefix = "ocm" {{< /highlight >}} {{% /dir %}} -{{% dir name="endpoint" type="string" default="This host's URL. If it's not configured, it is assumed OCM is not available." %}} - [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L40) +{{% dir name="endpoint" type="string" default="This host's full URL. If it's not configured, it is assumed OCM is not available." %}} + [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L41) {{< highlight toml >}} [http.services.ocmprovider] -endpoint = "This host's URL. If it's not configured, it is assumed OCM is not available." +endpoint = "This host's full URL. If it's not configured, it is assumed OCM is not available." {{< /highlight >}} {{% /dir %}} {{% dir name="provider" type="string" default="reva" %}} -A friendly name that defines this service. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L41) +A friendly name that defines this service. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L42) {{< highlight toml >}} [http.services.ocmprovider] provider = "reva" @@ -33,7 +33,7 @@ provider = "reva" {{% /dir %}} {{% dir name="webdav_root" type="string" default="/remote.php/dav/ocm" %}} -The root URL of the WebDAV endpoint to serve OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L42) +The root URL of the WebDAV endpoint to serve OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L43) {{< highlight toml >}} [http.services.ocmprovider] webdav_root = "/remote.php/dav/ocm" @@ -41,7 +41,7 @@ webdav_root = "/remote.php/dav/ocm" {{% /dir %}} {{% dir name="webapp_root" type="string" default="/external/sciencemesh" %}} -The root URL to serve Web apps via OCM. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L43) +The root URL to serve Web apps via OCM. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L44) {{< highlight toml >}} [http.services.ocmprovider] webapp_root = "/external/sciencemesh" @@ -49,7 +49,7 @@ webapp_root = "/external/sciencemesh" {{% /dir %}} {{% dir name="enable_webapp" type="bool" default=false %}} -Whether web apps are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L44) +Whether web apps are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L45) {{< highlight toml >}} [http.services.ocmprovider] enable_webapp = false @@ -57,7 +57,7 @@ enable_webapp = false {{% /dir %}} {{% dir name="enable_datatx" type="bool" default=false %}} -Whether data transfers are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L45) +Whether data transfers are enabled in OCM shares. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/ocmprovider/ocmprovider.go#L46) {{< highlight toml >}} [http.services.ocmprovider] enable_datatx = false diff --git a/docs/content/en/docs/config/http/services/overleaf/_index.md b/docs/content/en/docs/config/http/services/overleaf/_index.md index fb9b328397..4b44721c5e 100644 --- a/docs/content/en/docs/config/http/services/overleaf/_index.md +++ b/docs/content/en/docs/config/http/services/overleaf/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="app_name" type="string" default="" %}} -The App user-friendly name. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L59) +The App user-friendly name. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L58) {{< highlight toml >}} [http.services.overleaf] app_name = "" @@ -17,7 +17,7 @@ app_name = "" {{% /dir %}} {{% dir name="archiver_url" type="string" default="" %}} -Internet-facing URL of the archiver service, used to serve the files to Overleaf. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L60) +Internet-facing URL of the archiver service, used to serve the files to Overleaf. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L59) {{< highlight toml >}} [http.services.overleaf] archiver_url = "" @@ -25,7 +25,7 @@ archiver_url = "" {{% /dir %}} {{% dir name="app_url" type="string" default="" %}} -The App URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L61) +The App URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L60) {{< highlight toml >}} [http.services.overleaf] app_url = "" @@ -33,7 +33,7 @@ app_url = "" {{% /dir %}} {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L62) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/overleaf/overleaf.go#L61) {{< highlight toml >}} [http.services.overleaf] insecure = false diff --git a/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md b/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md index 874587adfb..09f3385228 100644 --- a/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md +++ b/docs/content/en/docs/config/http/services/owncloud/ocdav/_index.md @@ -9,7 +9,7 @@ description: > # _struct: Config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L103) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L110) {{< highlight toml >}} [http.services.owncloud.ocdav] insecure = false @@ -17,7 +17,7 @@ insecure = false {{% /dir %}} {{% dir name="notifications" type="map[string]interface{}" default=Settingsg for the Notification Helper %}} - [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L114) + [[Ref]](https://github.com/cs3org/reva/tree/master/internal/http/services/owncloud/ocdav/ocdav.go#L122) {{< highlight toml >}} [http.services.owncloud.ocdav] notifications = Settingsg for the Notification Helper diff --git a/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md b/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md index 96d81c6d93..c56eeed2d5 100644 --- a/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md +++ b/docs/content/en/docs/config/packages/auth/manager/oidc/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L63) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L65) {{< highlight toml >}} [auth.manager.oidc] insecure = false @@ -17,7 +17,7 @@ insecure = false {{% /dir %}} {{% dir name="issuer" type="string" default="" %}} -The issuer of the OIDC token. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L64) +The issuer of the OIDC token. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L66) {{< highlight toml >}} [auth.manager.oidc] issuer = "" @@ -25,7 +25,7 @@ issuer = "" {{% /dir %}} {{% dir name="id_claim" type="string" default="sub" %}} -The claim containing the ID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L65) +The claim containing the ID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L67) {{< highlight toml >}} [auth.manager.oidc] id_claim = "sub" @@ -33,7 +33,7 @@ id_claim = "sub" {{% /dir %}} {{% dir name="uid_claim" type="string" default="" %}} -The claim containing the UID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L66) +The claim containing the UID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L68) {{< highlight toml >}} [auth.manager.oidc] uid_claim = "" @@ -41,7 +41,7 @@ uid_claim = "" {{% /dir %}} {{% dir name="gid_claim" type="string" default="" %}} -The claim containing the GID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L67) +The claim containing the GID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L69) {{< highlight toml >}} [auth.manager.oidc] gid_claim = "" @@ -49,7 +49,7 @@ gid_claim = "" {{% /dir %}} {{% dir name="gatewaysvc" type="string" default="" %}} -The endpoint at which the GRPC gateway is exposed. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L68) +The endpoint at which the GRPC gateway is exposed. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L70) {{< highlight toml >}} [auth.manager.oidc] gatewaysvc = "" @@ -57,7 +57,7 @@ gatewaysvc = "" {{% /dir %}} {{% dir name="users_mapping" type="string" default="" %}} - The optional OIDC users mapping file path [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L69) + The optional OIDC users mapping file path [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L71) {{< highlight toml >}} [auth.manager.oidc] users_mapping = "" @@ -65,7 +65,7 @@ users_mapping = "" {{% /dir %}} {{% dir name="group_claim" type="string" default="" %}} - The group claim to be looked up to map the user (default to 'groups'). [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L70) + The group claim to be looked up to map the user (default to 'groups'). [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidc/oidc.go#L72) {{< highlight toml >}} [auth.manager.oidc] group_claim = "" diff --git a/docs/content/en/docs/config/packages/ocm/provider/authorizer/mentix/_index.md b/docs/content/en/docs/config/packages/ocm/provider/authorizer/mentix/_index.md index fe12cab3b7..1194dc447b 100644 --- a/docs/content/en/docs/config/packages/ocm/provider/authorizer/mentix/_index.md +++ b/docs/content/en/docs/config/packages/ocm/provider/authorizer/mentix/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="insecure" type="bool" default=false %}} -Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/ocm/provider/authorizer/mentix/mentix.go#L79) +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/ocm/provider/authorizer/mentix/mentix.go#L81) {{< highlight toml >}} [ocm.provider.authorizer.mentix] insecure = false diff --git a/docs/content/en/docs/config/packages/storage/registry/_index.md b/docs/content/en/docs/config/packages/storage/registry/_index.md new file mode 100644 index 0000000000..0fac6a5ca7 --- /dev/null +++ b/docs/content/en/docs/config/packages/storage/registry/_index.md @@ -0,0 +1,7 @@ +--- +title: "registry" +linkTitle: "registry" +weight: 10 +description: > + Configuration for the registry service +--- \ No newline at end of file diff --git a/docs/content/en/docs/config/packages/storage/registry/dynamic/_index.md b/docs/content/en/docs/config/packages/storage/registry/dynamic/_index.md new file mode 100644 index 0000000000..f7fda188cc --- /dev/null +++ b/docs/content/en/docs/config/packages/storage/registry/dynamic/_index.md @@ -0,0 +1,26 @@ +--- +title: "dynamic" +linkTitle: "dynamic" +weight: 10 +description: > + Configuration for the dynamic service +--- + +# _struct: config_ + +{{% dir name="rules" type="map[string]string" default=nil %}} +A map from mountID to provider address [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/storage/registry/dynamic/dynamic.go#L53) +{{< highlight toml >}} +[storage.registry.dynamic] +rules = nil +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="rewrites" type="map[string]string" default=nil %}} +A map from a path to an template alias to use when resolving [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/storage/registry/dynamic/dynamic.go#L54) +{{< highlight toml >}} +[storage.registry.dynamic] +rewrites = nil +{{< /highlight >}} +{{% /dir %}} + diff --git a/docs/content/en/docs/config/packages/user/manager/nextcloud/_index.md b/docs/content/en/docs/config/packages/user/manager/nextcloud/_index.md index f24a0f23d0..c4974097ee 100644 --- a/docs/content/en/docs/config/packages/user/manager/nextcloud/_index.md +++ b/docs/content/en/docs/config/packages/user/manager/nextcloud/_index.md @@ -9,7 +9,7 @@ description: > # _struct: UserManagerConfig_ {{% dir name="endpoint" type="string" default="" %}} -The Nextcloud backend endpoint for user management [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/user/manager/nextcloud/nextcloud.go#L54) +The Nextcloud backend endpoint for user management [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/user/manager/nextcloud/nextcloud.go#L53) {{< highlight toml >}} [user.manager.nextcloud] endpoint = "" diff --git a/examples/helloworld/revad.toml b/examples/helloworld/revad.toml new file mode 100644 index 0000000000..e034fb8ebb --- /dev/null +++ b/examples/helloworld/revad.toml @@ -0,0 +1,15 @@ +[log] +mode = "json" + +[http] +address = "localhost:8080" + +[http.services.helloworld] +[http.services.prometheus] + + +[grpc] +address = "localhost:8081" +enable_reflection = true + +[grpc.services.helloworld] diff --git a/examples/pingpong/revad.toml b/examples/pingpong/revad.toml new file mode 100644 index 0000000000..159812a7a1 --- /dev/null +++ b/examples/pingpong/revad.toml @@ -0,0 +1,12 @@ +[log] + +[http] +address = "localhost:8080" + +[http.services.pingpong] + +[grpc] +address = "localhost:8081" +enable_reflection = true + +[grpc.services.pingpong] diff --git a/go.mod b/go.mod index 61f17de78f..b5df636545 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,10 @@ module github.com/cs3org/reva require ( bou.ke/monkey v1.0.2 - contrib.go.opencensus.io/exporter/prometheus v0.4.2 github.com/BurntSushi/toml v1.3.2 github.com/Masterminds/sprig v2.22.0+incompatible github.com/ReneKroon/ttlcache/v2 v2.11.0 github.com/asim/go-micro/plugins/events/nats/v4 v4.7.0 - github.com/aws/aws-sdk-go v1.45.1 github.com/beevik/etree v1.2.0 github.com/bluele/gcache v0.0.2 github.com/c-bata/go-prompt v0.2.5 @@ -29,12 +27,14 @@ require ( github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.15.4 github.com/go-sql-driver/mysql v1.7.1 + github.com/gofrs/uuid v4.4.0+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/protobuf v1.5.3 github.com/gomodule/redigo v1.8.9 github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/juliangruber/go-intersect v1.1.0 github.com/mattn/go-sqlite3 v1.14.17 @@ -48,6 +48,7 @@ require ( github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 github.com/prometheus/alertmanager v0.26.0 + github.com/prometheus/client_golang v1.16.0 github.com/rs/cors v1.9.0 github.com/rs/zerolog v1.28.0 github.com/sethvargo/go-password v0.2.0 @@ -58,11 +59,8 @@ require ( github.com/wk8/go-ordered-map v1.0.0 go-micro.dev/v4 v4.3.1-0.20211108085239-0c2041e43908 go.opencensus.io v0.24.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.37.0 - go.opentelemetry.io/otel v1.14.0 - go.opentelemetry.io/otel/exporters/jaeger v1.11.2 - go.opentelemetry.io/otel/sdk v1.11.2 - go.opentelemetry.io/otel/trace v1.14.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 + go.opentelemetry.io/otel/trace v1.18.0 go.step.sm/crypto v0.35.0 golang.org/x/crypto v0.13.0 golang.org/x/oauth2 v0.11.0 @@ -90,13 +88,12 @@ require ( github.com/dolthub/vitess v0.0.0-20221031111135-9aad77e7b39f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-kit/kit v0.10.0 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/errors v0.20.4 // indirect @@ -104,8 +101,8 @@ require ( github.com/gocraft/dbr/v2 v2.7.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.1.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect @@ -114,7 +111,6 @@ require ( github.com/hashicorp/raft v1.5.0 // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.12 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lestrrat-go/strftime v1.0.4 // indirect @@ -139,11 +135,9 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pkg/term v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.0 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect @@ -152,16 +146,16 @@ require ( github.com/tidwall/pretty v1.2.0 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect - go.opentelemetry.io/otel/metric v0.34.0 // indirect + go.opentelemetry.io/otel v1.18.0 // indirect + go.opentelemetry.io/otel/metric v1.18.0 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.14.0 // indirect + golang.org/x/net v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.9.3 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect gopkg.in/src-d/go-errors.v1 v1.0.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f1a846c20c..596abae755 100644 --- a/go.sum +++ b/go.sum @@ -42,7 +42,6 @@ cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= @@ -213,12 +212,10 @@ cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/ cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= @@ -760,8 +757,6 @@ cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= @@ -865,7 +860,6 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.37.27/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.45.1 h1:PXuxDZIo/Y9Bvtg2t055+dY4hRwNAEcq6bUMv9fXcjk= github.com/aws/aws-sdk-go v1.45.1/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw= @@ -929,7 +923,6 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -1019,8 +1012,6 @@ github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exoscale/egoscale v0.46.0/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -1029,6 +1020,8 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -1077,7 +1070,6 @@ github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= @@ -1086,7 +1078,6 @@ github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8V github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -1286,6 +1277,10 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 h1:mdLirNAJBxnGgyB6pjZLcs6ue/6eZGBui6gXspfq4ks= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go.mod h1:kdXbOySqcQeTxiqglW7aahTmWZy3Pgi6SYL36yvKeyA= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -1356,9 +1351,7 @@ github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4Fw github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= @@ -1635,8 +1628,6 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= @@ -1659,7 +1650,6 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= @@ -1678,8 +1668,6 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1780,7 +1768,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/studio-b12/gowebdav v0.9.0 h1:1j1sc9gQnNxbXXM4M/CebPOX4aXYtr7MojAVcN4dHjU= github.com/studio-b12/gowebdav v0.9.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o= @@ -1852,18 +1839,14 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.37.0 h1:+uFejS4DCfNH6d3xODVIGsdhzgzhh45p9gpbHQMbdZI= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.37.0/go.mod h1:HSmzQvagH8pS2/xrK7ScWsk0vAMtRTGbMFgInXCi8Tc= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/exporters/jaeger v1.11.2 h1:ES8/j2+aB+3/BUw51ioxa50V9btN1eew/2J7N7n1tsE= -go.opentelemetry.io/otel/exporters/jaeger v1.11.2/go.mod h1:nwcF/DK4Hk0auZ/a5vw20uMsaJSXbzeeimhN5f9d0Lc= -go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= -go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= -go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= -go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= @@ -2027,6 +2010,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2056,8 +2040,9 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2069,6 +2054,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -2225,7 +2211,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2498,6 +2483,7 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2685,6 +2671,7 @@ google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/grpc/interceptors/appctx/appctx.go b/internal/grpc/interceptors/appctx/appctx.go index 321ef153a3..9aa0201aa3 100644 --- a/internal/grpc/interceptors/appctx/appctx.go +++ b/internal/grpc/interceptors/appctx/appctx.go @@ -22,23 +22,17 @@ import ( "context" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/trace" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" ) // NewUnary returns a new unary interceptor that creates the application context. func NewUnary(log zerolog.Logger) grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - span := trace.SpanFromContext(ctx) - defer span.End() - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("grpc").Start(ctx, "grpc unary") - } - - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() - ctx = appctx.WithLogger(ctx, &sub) + traceID := trace.Get(ctx) + log := log.With().Str("traceid", traceID).Logger() + ctx = appctx.WithLogger(ctx, &log) res, err := handler(ctx, req) return res, err } @@ -50,15 +44,9 @@ func NewUnary(log zerolog.Logger) grpc.UnaryServerInterceptor { func NewStream(log zerolog.Logger) grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() - span := trace.SpanFromContext(ctx) - defer span.End() - - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("grpc").Start(ctx, "grpc stream") - } - - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() - ctx = appctx.WithLogger(ctx, &sub) + traceID := trace.Get(ctx) + log := log.With().Str("traceid", traceID).Logger() + ctx = appctx.WithLogger(ctx, &log) wrapped := newWrappedServerStream(ctx, ss) err := handler(srv, wrapped) diff --git a/internal/grpc/interceptors/auth/auth.go b/internal/grpc/interceptors/auth/auth.go index 601a0e2ee3..ed42c2939e 100644 --- a/internal/grpc/interceptors/auth/auth.go +++ b/internal/grpc/interceptors/auth/auth.go @@ -28,7 +28,6 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" @@ -102,21 +101,21 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI // If a token is present, set it anyway, as we might need the user info // to decide the storage provider. - tkn, ok := ctxpkg.ContextGetToken(ctx) + tkn, ok := appctx.ContextGetToken(ctx) if ok { u, scopes, err := dismantleToken(ctx, tkn, req, tokenManager, conf.GatewayAddr, true) if err == nil { if blockedUsers.IsBlocked(u.Username) { return nil, status.Errorf(codes.PermissionDenied, "user %s blocked", u.Username) } - ctx = ctxpkg.ContextSetUser(ctx, u) - ctx = ctxpkg.ContextSetScopes(ctx, scopes) + ctx = appctx.ContextSetUser(ctx, u) + ctx = appctx.ContextSetScopes(ctx, scopes) } } return handler(ctx, req) } - tkn, ok := ctxpkg.ContextGetToken(ctx) + tkn, ok := appctx.ContextGetToken(ctx) if !ok || tkn == "" { log.Warn().Msg("access token not found or empty") @@ -134,8 +133,8 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI return nil, status.Errorf(codes.PermissionDenied, "user %s blocked", u.Username) } - ctx = ctxpkg.ContextSetUser(ctx, u) - ctx = ctxpkg.ContextSetScopes(ctx, scopes) + ctx = appctx.ContextSetUser(ctx, u) + ctx = appctx.ContextSetScopes(ctx, scopes) return handler(ctx, req) } return interceptor, nil @@ -175,12 +174,12 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe // If a token is present, set it anyway, as we might need the user info // to decide the storage provider. - tkn, ok := ctxpkg.ContextGetToken(ctx) + tkn, ok := appctx.ContextGetToken(ctx) if ok { u, scopes, err := dismantleToken(ctx, tkn, ss, tokenManager, conf.GatewayAddr, true) if err == nil { - ctx = ctxpkg.ContextSetUser(ctx, u) - ctx = ctxpkg.ContextSetScopes(ctx, scopes) + ctx = appctx.ContextSetUser(ctx, u) + ctx = appctx.ContextSetScopes(ctx, scopes) ss = newWrappedServerStream(ctx, ss) } } @@ -188,7 +187,7 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe return handler(srv, ss) } - tkn, ok := ctxpkg.ContextGetToken(ctx) + tkn, ok := appctx.ContextGetToken(ctx) if !ok || tkn == "" { log.Warn().Msg("access token not found") @@ -203,8 +202,8 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe } // store user and core access token in context. - ctx = ctxpkg.ContextSetUser(ctx, u) - ctx = ctxpkg.ContextSetScopes(ctx, scopes) + ctx = appctx.ContextSetUser(ctx, u) + ctx = appctx.ContextSetScopes(ctx, scopes) wrapped := newWrappedServerStream(ctx, ss) return handler(srv, wrapped) } diff --git a/internal/grpc/interceptors/auth/scope.go b/internal/grpc/interceptors/auth/scope.go index 50fc65dad2..c3cd7bec3e 100644 --- a/internal/grpc/interceptors/auth/scope.go +++ b/internal/grpc/interceptors/auth/scope.go @@ -37,7 +37,6 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" statuspkg "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -305,7 +304,7 @@ func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent if err != nil { return false, err } - ctx = metadata.AppendToOutgoingContext(context.Background(), ctxpkg.TokenHeader, token) + ctx = metadata.AppendToOutgoingContext(context.Background(), appctx.TokenHeader, token) childStat, err := client.Stat(ctx, &provider.StatRequest{Ref: ref}) if err != nil { diff --git a/internal/grpc/interceptors/log/log.go b/internal/grpc/interceptors/log/log.go index 8d7ee05b0c..99805a4a97 100644 --- a/internal/grpc/interceptors/log/log.go +++ b/internal/grpc/interceptors/log/log.go @@ -23,7 +23,6 @@ import ( "time" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/rs/zerolog" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -44,7 +43,7 @@ func NewUnary() grpc.UnaryServerInterceptor { if p, ok := peer.FromContext(ctx); ok { fromAddress = p.Addr.Network() + "://" + p.Addr.String() } - userAgent, ok := ctxpkg.ContextGetUserAgentString(ctx) + userAgent, ok := appctx.ContextGetUserAgentString(ctx) if !ok { userAgent = "" } @@ -86,7 +85,7 @@ func NewStream() grpc.StreamServerInterceptor { if p, ok := peer.FromContext(ss.Context()); ok { fromAddress = p.Addr.Network() + "://" + p.Addr.String() } - userAgent, ok := ctxpkg.ContextGetUserAgentString(ctx) + userAgent, ok := appctx.ContextGetUserAgentString(ctx) if !ok { userAgent = "" } diff --git a/internal/grpc/interceptors/metrics/metrics.go b/internal/grpc/interceptors/metrics/metrics.go new file mode 100644 index 0000000000..5c18144122 --- /dev/null +++ b/internal/grpc/interceptors/metrics/metrics.go @@ -0,0 +1,51 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package metrics + +import ( + "context" + + "github.com/cs3org/reva/pkg/prom/registry" + grpcprom "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" +) + +var collector = grpcprom.NewServerMetrics() + +func init() { + registry.Register("grpc_metrics", NewPromCollectors) +} + +// New returns a prometheus collector. +func NewPromCollectors(_ context.Context, m map[string]interface{}) ([]prometheus.Collector, error) { + return []prometheus.Collector{collector}, nil +} + +// NewUnary returns a new unary interceptor that adds +// the useragent to the context. +func NewUnary() grpc.UnaryServerInterceptor { + return collector.UnaryServerInterceptor() +} + +// NewStream returns a new server stream interceptor +// that adds the user agent to the context. +func NewStream() grpc.StreamServerInterceptor { + return collector.StreamServerInterceptor() +} diff --git a/internal/grpc/interceptors/token/token.go b/internal/grpc/interceptors/token/token.go index fe3c62c4c6..ad1ddde8f1 100644 --- a/internal/grpc/interceptors/token/token.go +++ b/internal/grpc/interceptors/token/token.go @@ -21,7 +21,7 @@ package token import ( "context" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) @@ -32,11 +32,11 @@ func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { md, ok := metadata.FromIncomingContext(ctx) if ok && md != nil { - if val, ok := md[ctxpkg.TokenHeader]; ok { + if val, ok := md[appctx.TokenHeader]; ok { if len(val) > 0 && val[0] != "" { tkn := val[0] - ctx = ctxpkg.ContextSetToken(ctx, tkn) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, tkn) + ctx = appctx.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, tkn) } } } @@ -54,11 +54,11 @@ func NewStream() grpc.StreamServerInterceptor { md, ok := metadata.FromIncomingContext(ss.Context()) if ok && md != nil { - if val, ok := md[ctxpkg.TokenHeader]; ok { + if val, ok := md[appctx.TokenHeader]; ok { if len(val) > 0 && val[0] != "" { tkn := val[0] - ctx = ctxpkg.ContextSetToken(ctx, tkn) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, tkn) + ctx = appctx.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, tkn) } } } diff --git a/internal/grpc/interceptors/trace/trace.go b/internal/grpc/interceptors/trace/trace.go new file mode 100644 index 0000000000..aafffd9b28 --- /dev/null +++ b/internal/grpc/interceptors/trace/trace.go @@ -0,0 +1,84 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package trace + +import ( + "context" + + "github.com/cs3org/reva/pkg/trace" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +func getContext(ctx context.Context) context.Context { + traceID := trace.Get(ctx) + if traceID != "" { + return ctx + } + + md, ok := metadata.FromIncomingContext(ctx) + if ok && md != nil { + if val, ok := md["revad-grpc-trace-id"]; ok { + if len(val) > 0 && val[0] != "" { + traceID = val[0] + } + } + } + + if traceID == "" { + traceID = trace.Generate() + } + + ctx = trace.Set(ctx, traceID) + return ctx +} + +// NewUnary returns a new unary interceptor that adds +// trace information for the request. +func NewUnary() grpc.UnaryServerInterceptor { + interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + ctx = getContext(ctx) + return handler(ctx, req) + } + return interceptor +} + +// NewStream returns a new server stream interceptor +// that adds trace information to the request. +func NewStream() grpc.StreamServerInterceptor { + interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + ctx := getContext(ss.Context()) + wrapped := newWrappedServerStream(ctx, ss) + return handler(srv, wrapped) + } + return interceptor +} + +func newWrappedServerStream(ctx context.Context, ss grpc.ServerStream) *wrappedServerStream { + return &wrappedServerStream{ServerStream: ss, newCtx: ctx} +} + +type wrappedServerStream struct { + grpc.ServerStream + newCtx context.Context +} + +func (ss *wrappedServerStream) Context() context.Context { + return ss.newCtx +} diff --git a/internal/grpc/interceptors/useragent/useragent.go b/internal/grpc/interceptors/useragent/useragent.go index 5f83229308..b81cf7a6f3 100644 --- a/internal/grpc/interceptors/useragent/useragent.go +++ b/internal/grpc/interceptors/useragent/useragent.go @@ -21,7 +21,7 @@ package useragent import ( "context" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) @@ -31,8 +31,8 @@ import ( func NewUnary() grpc.UnaryServerInterceptor { interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { if md, ok := metadata.FromIncomingContext(ctx); ok { - if lst, ok := md[ctxpkg.UserAgentHeader]; ok && len(lst) != 0 { - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.UserAgentHeader, lst[0]) + if lst, ok := md[appctx.UserAgentHeader]; ok && len(lst) != 0 { + ctx = metadata.AppendToOutgoingContext(ctx, appctx.UserAgentHeader, lst[0]) } } return handler(ctx, req) @@ -46,8 +46,8 @@ func NewStream() grpc.StreamServerInterceptor { interceptor := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { ctx := ss.Context() if md, ok := metadata.FromIncomingContext(ctx); ok { - if lst, ok := md[ctxpkg.UserAgentHeader]; ok && len(lst) != 0 { - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.UserAgentHeader, lst[0]) + if lst, ok := md[appctx.UserAgentHeader]; ok && len(lst) != 0 { + ctx = metadata.AppendToOutgoingContext(ctx, appctx.UserAgentHeader, lst[0]) } } wrapped := newWrappedServerStream(ctx, ss) diff --git a/internal/grpc/services/appregistry/appregistry_test.go b/internal/grpc/services/appregistry/appregistry_test.go index f56dad5997..9a265f1e81 100644 --- a/internal/grpc/services/appregistry/appregistry_test.go +++ b/internal/grpc/services/appregistry/appregistry_test.go @@ -76,7 +76,7 @@ func Test_ListAppProviders(t *testing.T) { want: ®istrypb.ListAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 1, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "", }, Providers: []*registrypb.ProviderInfo{ @@ -98,7 +98,7 @@ func Test_ListAppProviders(t *testing.T) { want: ®istrypb.ListAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 1, - Trace: "00000000000000000000000000000000", + Trace: "", }, Providers: []*registrypb.ProviderInfo{}, }, @@ -112,7 +112,7 @@ func Test_ListAppProviders(t *testing.T) { want: ®istrypb.ListAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 1, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "", }, Providers: []*registrypb.ProviderInfo{}, @@ -218,7 +218,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 1, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "", }, Providers: []*registrypb.ProviderInfo{ @@ -235,7 +235,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 1, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "", }, Providers: []*registrypb.ProviderInfo{ @@ -252,7 +252,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 15, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "error looking for the app provider", }, Providers: nil, @@ -264,7 +264,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 15, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "error looking for the app provider", }, Providers: nil, @@ -276,7 +276,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 15, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "error looking for the app provider", }, Providers: nil, @@ -288,7 +288,7 @@ func Test_GetAppProviders(t *testing.T) { want: ®istrypb.GetAppProvidersResponse{ Status: &rpcv1beta1.Status{ Code: 15, - Trace: "00000000000000000000000000000000", + Trace: "", Message: "error looking for the app provider", }, Providers: nil, diff --git a/internal/grpc/services/datatx/datatx.go b/internal/grpc/services/datatx/datatx.go index 662dffded7..bb202a7783 100644 --- a/internal/grpc/services/datatx/datatx.go +++ b/internal/grpc/services/datatx/datatx.go @@ -24,7 +24,7 @@ import ( ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" datatx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + txdriver "github.com/cs3org/reva/pkg/datatx" txregistry "github.com/cs3org/reva/pkg/datatx/manager/registry" repoRegistry "github.com/cs3org/reva/pkg/datatx/repository/registry" @@ -126,7 +126,7 @@ func (s *service) CreateTransfer(ctx context.Context, req *datatx.CreateTransfer // we always save the transfer regardless of start transfer outcome // only then, if starting fails, can we try to restart it - userID := ctxpkg.ContextMustGetUser(ctx).GetId() + userID := appctx.ContextMustGetUser(ctx).GetId() transfer := &txdriver.Transfer{ TxID: txInfo.GetId().OpaqueId, SrcTargetURI: req.SrcTargetUri, @@ -219,7 +219,7 @@ func (s *service) CancelTransfer(ctx context.Context, req *datatx.CancelTransfer } func (s *service) ListTransfers(ctx context.Context, req *datatx.ListTransfersRequest) (*datatx.ListTransfersResponse, error) { - userID := ctxpkg.ContextMustGetUser(ctx).GetId() + userID := appctx.ContextMustGetUser(ctx).GetId() transfers, err := s.storageDriver.ListTransfers(req.Filters, userID) if err != nil { err = errors.Wrap(err, "datatx service: error listing transfers") diff --git a/internal/grpc/services/gateway/appprovider.go b/internal/grpc/services/gateway/appprovider.go index a6b06bcbde..7a317df61b 100644 --- a/internal/grpc/services/gateway/appprovider.go +++ b/internal/grpc/services/gateway/appprovider.go @@ -33,7 +33,6 @@ import ( storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -158,8 +157,8 @@ func (s *svc) openFederatedShares(ctx context.Context, targetURL string, req *ga } gatewayClient := gateway.NewGatewayAPIClient(conn) - remoteCtx := ctxpkg.ContextSetToken(context.Background(), ep.token) - remoteCtx = metadata.AppendToOutgoingContext(remoteCtx, ctxpkg.TokenHeader, ep.token) + remoteCtx := appctx.ContextSetToken(context.Background(), ep.token) + remoteCtx = metadata.AppendToOutgoingContext(remoteCtx, appctx.TokenHeader, ep.token) res, err := gatewayClient.OpenInApp(remoteCtx, appProviderReq) if err != nil { @@ -170,7 +169,7 @@ func (s *svc) openFederatedShares(ctx context.Context, targetURL string, req *ga } func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.ResourceInfo, req *gateway.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) { - accessToken, ok := ctxpkg.ContextGetToken(ctx) + accessToken, ok := appctx.ContextGetToken(ctx) if !ok || accessToken == "" { return &providerpb.OpenInAppResponse{ Status: status.NewUnauthenticated(ctx, errtypes.InvalidCredentials("Access token is invalid or empty"), ""), diff --git a/internal/grpc/services/gateway/authprovider.go b/internal/grpc/services/gateway/authprovider.go index b462bef6ed..da485f93c6 100644 --- a/internal/grpc/services/gateway/authprovider.go +++ b/internal/grpc/services/gateway/authprovider.go @@ -29,7 +29,6 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -112,9 +111,9 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest return res, nil } - ctx = ctxpkg.ContextSetToken(ctx, token) - ctx = ctxpkg.ContextSetUser(ctx, res.User) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, token) + ctx = appctx.ContextSetToken(ctx, token) + ctx = appctx.ContextSetUser(ctx, res.User) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, token) // Commenting out as the token size can get too big // For now, we'll try to resolve all resources on every request and cache those @@ -148,9 +147,9 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest // we need to pass the token to authenticate the CreateHome request. // TODO(labkode): appending to existing context will not pass the token. - ctx = ctxpkg.ContextSetToken(ctx, token) - ctx = ctxpkg.ContextSetUser(ctx, res.User) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, token) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? + ctx = appctx.ContextSetToken(ctx, token) + ctx = appctx.ContextSetUser(ctx, res.User) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, token) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? // create home directory if _, err = s.createHomeCache.Get(res.User.Id.OpaqueId); err != nil { diff --git a/internal/grpc/services/gateway/ocmshareprovider.go b/internal/grpc/services/gateway/ocmshareprovider.go index 5effeab924..50e974eeb6 100644 --- a/internal/grpc/services/gateway/ocmshareprovider.go +++ b/internal/grpc/services/gateway/ocmshareprovider.go @@ -30,7 +30,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" datatx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -318,7 +318,7 @@ func (s *svc) handleTransfer(ctx context.Context, share *ocm.ReceivedShare, tran // http://...token...@reva.eu/prefix/?name=remote.php/webdav/home/... destEndpointPath := strings.TrimPrefix(destWebdavEndpointURL.Path, dstWebdavHostURL.Path) destEndpointScheme := destWebdavEndpointURL.Scheme - destToken := ctxpkg.ContextMustGetToken(ctx) + destToken := appctx.ContextMustGetToken(ctx) destPath := path.Join(destEndpointPath, transferDestinationPath, path.Base(share.Name)) destTargetURI := fmt.Sprintf("%s://%s@%s?name=%s", destEndpointScheme, destToken, destServiceHost, destPath) // var destUri string diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 7dd35b1fe5..34cc89fa21 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -34,12 +34,11 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/storage/utils/etag" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/golang-jwt/jwt" "github.com/google/uuid" @@ -889,17 +888,12 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, nil } - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "Delete") - defer span.End() - if !s.inSharedFolder(ctx, p) { return s.delete(ctx, req) } if s.isSharedFolder(ctx, p) { // TODO(labkode): deleting share names should be allowed, means unmounting. - err := errtypes.BadRequest("gateway: cannot delete share folder or share name: path=" + p) - span.RecordError(err) return &provider.DeleteResponse{ Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), }, nil @@ -1781,7 +1775,7 @@ func (s *svc) listSharesFolder(ctx context.Context) (*provider.ListContainerResp } func (s *svc) filterProvidersByUserAgent(ctx context.Context, providers []*registry.ProviderInfo) []*registry.ProviderInfo { - cat, ok := ctxpkg.ContextGetUserAgentCategory(ctx) + cat, ok := appctx.ContextGetUserAgentCategory(ctx) if !ok { return providers } diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index da83877149..6914627fc2 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -29,7 +29,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -321,8 +321,8 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update // if we don't need to create/delete references then we return early. if !s.c.CommitShareToStorageRef || - ctxpkg.ContextMustGetUser(ctx).Id.Type == userpb.UserType_USER_TYPE_LIGHTWEIGHT || - ctxpkg.ContextMustGetUser(ctx).Id.Type == userpb.UserType_USER_TYPE_FEDERATED { + appctx.ContextMustGetUser(ctx).Id.Type == userpb.UserType_USER_TYPE_LIGHTWEIGHT || + appctx.ContextMustGetUser(ctx).Id.Type == userpb.UserType_USER_TYPE_FEDERATED { return res, nil } diff --git a/internal/grpc/services/gateway/webdavstorageprovider.go b/internal/grpc/services/gateway/webdavstorageprovider.go index a30da26d79..b5e82718c9 100644 --- a/internal/grpc/services/gateway/webdavstorageprovider.go +++ b/internal/grpc/services/gateway/webdavstorageprovider.go @@ -28,7 +28,8 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/pkg/errors" "github.com/studio-b12/gowebdav" @@ -56,7 +57,7 @@ func (s *svc) webdavRefStat(ctx context.Context, targetURL string, nameQueries . } c := gowebdav.NewClient(webdavEP, "", "") - c.SetHeader(ctxpkg.TokenHeader, ep.token) + c.SetHeader(appctx.TokenHeader, ep.token) // TODO(ishank011): We need to call PROPFIND ourselves as we need to retrieve // ownloud-specific fields to get the resource ID and permissions. @@ -83,7 +84,7 @@ func (s *svc) webdavRefLs(ctx context.Context, targetURL string, nameQueries ... } c := gowebdav.NewClient(webdavEP, "", "") - c.SetHeader(ctxpkg.TokenHeader, ep.token) + c.SetHeader(appctx.TokenHeader, ep.token) // TODO(ishank011): We need to call PROPFIND ourselves as we need to retrieve // ownloud-specific fields to get the resource ID and permissions. @@ -116,7 +117,7 @@ func (s *svc) webdavRefMkdir(ctx context.Context, targetURL string, nameQueries } c := gowebdav.NewClient(webdavEP, "", "") - c.SetHeader(ctxpkg.TokenHeader, ep.token) + c.SetHeader(appctx.TokenHeader, ep.token) err = c.Mkdir(ep.filePath, 0700) if err != nil { @@ -149,7 +150,7 @@ func (s *svc) webdavRefMove(ctx context.Context, targetURL, src, destination str } c := gowebdav.NewClient(srcWebdavEP, "", "") - c.SetHeader(ctxpkg.TokenHeader, srcEP.token) + c.SetHeader(appctx.TokenHeader, srcEP.token) err = c.Rename(srcEP.filePath, destEP.filePath, true) if err != nil { @@ -174,7 +175,7 @@ func (s *svc) webdavRefDelete(ctx context.Context, targetURL string, nameQueries } c := gowebdav.NewClient(webdavEP, "", "") - c.SetHeader(ctxpkg.TokenHeader, ep.token) + c.SetHeader(appctx.TokenHeader, ep.token) err = c.Remove(ep.filePath) if err != nil { diff --git a/internal/grpc/services/helloworld/helloworld.go b/internal/grpc/services/helloworld/helloworld.go index 8d4eab0566..db7bab0fa2 100644 --- a/internal/grpc/services/helloworld/helloworld.go +++ b/internal/grpc/services/helloworld/helloworld.go @@ -62,7 +62,7 @@ func (s *service) Close() error { } func (s *service) UnprotectedEndpoints() []string { - return []string{} + return []string{"/revad.helloworld.HelloWorldService/Hello"} } func (s *service) Register(ss *grpc.Server) { diff --git a/internal/grpc/services/loader/loader.go b/internal/grpc/services/loader/loader.go index 801acd285f..c028346e0f 100644 --- a/internal/grpc/services/loader/loader.go +++ b/internal/grpc/services/loader/loader.go @@ -34,6 +34,7 @@ import ( _ "github.com/cs3org/reva/internal/grpc/services/ocmproviderauthorizer" _ "github.com/cs3org/reva/internal/grpc/services/ocmshareprovider" _ "github.com/cs3org/reva/internal/grpc/services/permissions" + _ "github.com/cs3org/reva/internal/grpc/services/pingpong" _ "github.com/cs3org/reva/internal/grpc/services/preferences" _ "github.com/cs3org/reva/internal/grpc/services/publicshareprovider" _ "github.com/cs3org/reva/internal/grpc/services/publicstorageprovider" diff --git a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go index 2b257d5049..bcd0c4c919 100644 --- a/internal/grpc/services/ocminvitemanager/ocminvitemanager.go +++ b/internal/grpc/services/ocminvitemanager/ocminvitemanager.go @@ -27,7 +27,6 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/client" "github.com/cs3org/reva/pkg/ocm/invite" @@ -130,7 +129,7 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) GenerateInviteToken(ctx context.Context, req *invitepb.GenerateInviteTokenRequest) (*invitepb.GenerateInviteTokenResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) token := CreateToken(s.conf.tokenExpiration, user.GetId(), req.Description) if err := s.repo.AddToken(ctx, token); err != nil { @@ -146,7 +145,7 @@ func (s *service) GenerateInviteToken(ctx context.Context, req *invitepb.Generat } func (s *service) ListInviteTokens(ctx context.Context, req *invitepb.ListInviteTokensRequest) (*invitepb.ListInviteTokensResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) tokens, err := s.repo.ListTokens(ctx, user.Id) if err != nil { return &invitepb.ListInviteTokensResponse{ @@ -160,7 +159,7 @@ func (s *service) ListInviteTokens(ctx context.Context, req *invitepb.ListInvite } func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequest) (*invitepb.ForwardInviteResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) ocmEndpoint, err := getOCMEndpoint(req.GetOriginSystemProvider()) if err != nil { @@ -329,7 +328,7 @@ func (s *service) GetAcceptedUser(ctx context.Context, req *invitepb.GetAccepted } func getUserFilter(ctx context.Context, req *invitepb.GetAcceptedUserRequest) (*userpb.User, bool) { - user, ok := ctxpkg.ContextGetUser(ctx) + user, ok := appctx.ContextGetUser(ctx) if ok { return user, true } @@ -351,7 +350,7 @@ func getUserFilter(ctx context.Context, req *invitepb.GetAcceptedUserRequest) (* } func (s *service) FindAcceptedUsers(ctx context.Context, req *invitepb.FindAcceptedUsersRequest) (*invitepb.FindAcceptedUsersResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) acceptedUsers, err := s.repo.FindRemoteUsers(ctx, user.GetId(), req.GetFilter()) if err != nil { return &invitepb.FindAcceptedUsersResponse{ @@ -366,7 +365,7 @@ func (s *service) FindAcceptedUsers(ctx context.Context, req *invitepb.FindAccep } func (s *service) DeleteAcceptedUser(ctx context.Context, req *invitepb.DeleteAcceptedUserRequest) (*invitepb.DeleteAcceptedUserResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if err := s.repo.DeleteRemoteUser(ctx, user.Id, req.RemoteUserId); err != nil { return &invitepb.DeleteAcceptedUserResponse{ Status: status.NewInternal(ctx, err, "error deleting remote users: "+err.Error()), diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index 91f9f6a766..c713affab6 100644 --- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -35,7 +35,8 @@ import ( providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/ocmd" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/ocm/client" "github.com/cs3org/reva/pkg/ocm/share" @@ -281,7 +282,7 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq } info := statRes.Info - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) tkn := utils.RandString(32) now := time.Now().UnixNano() ts := &typespb.Timestamp{ @@ -373,7 +374,7 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq func (s *service) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareRequest) (*ocm.RemoveOCMShareResponse, error) { // TODO (gdelmont): notify the remote provider using the /notification ocm endpoint // https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org#/paths/~1notifications/post - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if err := s.repo.DeleteShare(ctx, user, req.Ref); err != nil { if errors.Is(err, share.ErrShareNotFound) { return &ocm.RemoveOCMShareResponse{ @@ -394,7 +395,7 @@ func (s *service) GetOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) // if the request is by token, the user does not need to be in the ctx var user *userpb.User if req.Ref.GetToken() == "" { - user = ctxpkg.ContextMustGetUser(ctx) + user = appctx.ContextMustGetUser(ctx) } ocmshare, err := s.repo.GetShare(ctx, user, req.Ref) if err != nil { @@ -438,7 +439,7 @@ func (s *service) GetOCMShareByToken(ctx context.Context, req *ocm.GetOCMShareBy } func (s *service) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesRequest) (*ocm.ListOCMSharesResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) shares, err := s.repo.ListShares(ctx, user, req.Filters) if err != nil { return &ocm.ListOCMSharesResponse{ @@ -454,7 +455,7 @@ func (s *service) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesReque } func (s *service) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareRequest) (*ocm.UpdateOCMShareResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if len(req.Field) == 0 { return &ocm.UpdateOCMShareResponse{ Status: status.NewOK(ctx), @@ -479,7 +480,7 @@ func (s *service) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareReq } func (s *service) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceivedOCMSharesRequest) (*ocm.ListReceivedOCMSharesResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) shares, err := s.repo.ListReceivedShares(ctx, user) if err != nil { return &ocm.ListReceivedOCMSharesResponse{ @@ -495,7 +496,7 @@ func (s *service) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceiv } func (s *service) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceivedOCMShareRequest) (*ocm.UpdateReceivedOCMShareResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) _, err := s.repo.UpdateReceivedShare(ctx, user, req.Share, req.UpdateMask) if err != nil { if errors.Is(err, share.ErrShareNotFound) { @@ -515,7 +516,7 @@ func (s *service) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateRec } func (s *service) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMShareRequest) (*ocm.GetReceivedOCMShareResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) ocmshare, err := s.repo.GetReceivedShare(ctx, user, req.Ref) if err != nil { if errors.Is(err, share.ErrShareNotFound) { diff --git a/internal/grpc/services/pingpong/pingpong.go b/internal/grpc/services/pingpong/pingpong.go new file mode 100644 index 0000000000..1056c78113 --- /dev/null +++ b/internal/grpc/services/pingpong/pingpong.go @@ -0,0 +1,135 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package pingpong + +import ( + "context" + "crypto/tls" + "io" + "net/http" + + "github.com/cs3org/reva/internal/grpc/services/pingpong/proto" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/httpclient" + "github.com/cs3org/reva/pkg/rgrpc" + "github.com/cs3org/reva/pkg/utils/cfg" + "google.golang.org/grpc" +) + +func init() { + rgrpc.Register("pingpong", New) +} + +type conf struct { + Endpoint string +} + +type service struct { + conf *conf + *proto.UnimplementedPingPongServiceServer +} + +func (c *conf) ApplyDefaults() { + if c.Endpoint == "" { + c.Endpoint = "http://localhost:8080/pingpong" + } +} + +func New(ctx context.Context, m map[string]interface{}) (rgrpc.Service, error) { + var c conf + if err := cfg.Decode(m, &c); err != nil { + return nil, err + } + service := &service{conf: &c} + return service, nil +} + +func (s *service) Close() error { + return nil +} + +func (s *service) UnprotectedEndpoints() []string { + return []string{"/revad.pingpong.PingPongService/Ping", "/revad.pingpong.PingPongService/Pong"} +} + +func (s *service) Register(ss *grpc.Server) { + proto.RegisterPingPongServiceServer(ss, s) +} + +func (s *service) Ping(ctx context.Context, _ *proto.PingRequest) (*proto.PingResponse, error) { + log := appctx.GetLogger(ctx) + + // we call the http Pong method + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + + client := httpclient.New(httpclient.RoundTripper(tr)) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.conf.Endpoint+"/ping", nil) + if err != nil { + log.Error().Err(err).Msg("error creating http request") + return nil, err + } + + res, err := client.Do(req) + if err != nil { + log.Error().Err(err).Msg("eror doing http pong") + return nil, err + } + + defer res.Body.Close() + data, err := io.ReadAll(res.Body) + if err != nil { + log.Error().Err(err).Msg("error reading response body") + return nil, err + } + + return &proto.PingResponse{Info: string(data)}, nil +} + +func (s *service) Pong(ctx context.Context, _ *proto.PongRequest) (*proto.PongResponse, error) { + log := appctx.GetLogger(ctx) + + // we call the http Pong method + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + + client := httpclient.New(httpclient.RoundTripper(tr)) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.conf.Endpoint+"/pong", nil) + if err != nil { + log.Error().Err(err).Msg("error creating http request") + return nil, err + } + + res, err := client.Do(req) + if err != nil { + log.Error().Err(err).Msg("eror doing http pong") + return nil, err + } + + defer res.Body.Close() + data, err := io.ReadAll(res.Body) + if err != nil { + log.Error().Err(err).Msg("error reading response body") + return nil, err + } + + return &proto.PongResponse{Info: string(data)}, nil +} diff --git a/internal/grpc/services/pingpong/proto/pingpong.pb.go b/internal/grpc/services/pingpong/proto/pingpong.pb.go new file mode 100644 index 0000000000..bd2c4b37f8 --- /dev/null +++ b/internal/grpc/services/pingpong/proto/pingpong.pb.go @@ -0,0 +1,364 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.7.1 +// source: pingpong.proto + +package proto + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info string `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pingpong_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_pingpong_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_pingpong_proto_rawDescGZIP(), []int{0} +} + +func (x *PingRequest) GetInfo() string { + if x != nil { + return x.Info + } + return "" +} + +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info string `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pingpong_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingResponse) ProtoMessage() {} + +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_pingpong_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_pingpong_proto_rawDescGZIP(), []int{1} +} + +func (x *PingResponse) GetInfo() string { + if x != nil { + return x.Info + } + return "" +} + +type PongRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info string `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *PongRequest) Reset() { + *x = PongRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pingpong_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PongRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PongRequest) ProtoMessage() {} + +func (x *PongRequest) ProtoReflect() protoreflect.Message { + mi := &file_pingpong_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PongRequest.ProtoReflect.Descriptor instead. +func (*PongRequest) Descriptor() ([]byte, []int) { + return file_pingpong_proto_rawDescGZIP(), []int{2} +} + +func (x *PongRequest) GetInfo() string { + if x != nil { + return x.Info + } + return "" +} + +type PongResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info string `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *PongResponse) Reset() { + *x = PongResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pingpong_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PongResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PongResponse) ProtoMessage() {} + +func (x *PongResponse) ProtoReflect() protoreflect.Message { + mi := &file_pingpong_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PongResponse.ProtoReflect.Descriptor instead. +func (*PongResponse) Descriptor() ([]byte, []int) { + return file_pingpong_proto_rawDescGZIP(), []int{3} +} + +func (x *PongResponse) GetInfo() string { + if x != nil { + return x.Info + } + return "" +} + +var File_pingpong_proto protoreflect.FileDescriptor + +var file_pingpong_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x0e, 0x72, 0x65, 0x76, 0x61, 0x64, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, + 0x22, 0x21, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, + 0x6e, 0x66, 0x6f, 0x22, 0x22, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x21, 0x0a, 0x0b, 0x50, 0x6f, 0x6e, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x22, 0x0a, 0x0c, 0x50, 0x6f, + 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x32, 0x97, + 0x01, 0x0a, 0x0f, 0x50, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x76, + 0x61, 0x64, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, 0x65, 0x76, 0x61, 0x64, 0x2e, + 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, 0x12, 0x1b, 0x2e, + 0x72, 0x65, 0x76, 0x61, 0x64, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0x2e, 0x50, + 0x6f, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, 0x65, 0x76, + 0x61, 0x64, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x6e, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73, 0x33, 0x6f, 0x72, 0x67, 0x2f, 0x72, 0x65, + 0x76, 0x61, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x70, 0x6f, + 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pingpong_proto_rawDescOnce sync.Once + file_pingpong_proto_rawDescData = file_pingpong_proto_rawDesc +) + +func file_pingpong_proto_rawDescGZIP() []byte { + file_pingpong_proto_rawDescOnce.Do(func() { + file_pingpong_proto_rawDescData = protoimpl.X.CompressGZIP(file_pingpong_proto_rawDescData) + }) + return file_pingpong_proto_rawDescData +} + +var file_pingpong_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_pingpong_proto_goTypes = []interface{}{ + (*PingRequest)(nil), // 0: revad.pingpong.PingRequest + (*PingResponse)(nil), // 1: revad.pingpong.PingResponse + (*PongRequest)(nil), // 2: revad.pingpong.PongRequest + (*PongResponse)(nil), // 3: revad.pingpong.PongResponse +} +var file_pingpong_proto_depIdxs = []int32{ + 0, // 0: revad.pingpong.PingPongService.Ping:input_type -> revad.pingpong.PingRequest + 2, // 1: revad.pingpong.PingPongService.Pong:input_type -> revad.pingpong.PongRequest + 1, // 2: revad.pingpong.PingPongService.Ping:output_type -> revad.pingpong.PingResponse + 3, // 3: revad.pingpong.PingPongService.Pong:output_type -> revad.pingpong.PongResponse + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pingpong_proto_init() } +func file_pingpong_proto_init() { + if File_pingpong_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pingpong_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pingpong_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pingpong_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PongRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pingpong_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PongResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pingpong_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_pingpong_proto_goTypes, + DependencyIndexes: file_pingpong_proto_depIdxs, + MessageInfos: file_pingpong_proto_msgTypes, + }.Build() + File_pingpong_proto = out.File + file_pingpong_proto_rawDesc = nil + file_pingpong_proto_goTypes = nil + file_pingpong_proto_depIdxs = nil +} diff --git a/internal/grpc/services/pingpong/proto/pingpong.proto b/internal/grpc/services/pingpong/proto/pingpong.proto new file mode 100644 index 0000000000..176800aa94 --- /dev/null +++ b/internal/grpc/services/pingpong/proto/pingpong.proto @@ -0,0 +1,46 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +syntax = "proto3"; + +package revad.pingpong; + +option go_package = "github.com/cs3org/reva/grpc/internal/services/pingpong/proto"; + +service PingPongService { + rpc Ping(PingRequest) returns (PingResponse); + rpc Pong(PongRequest) returns (PongResponse); +} + +message PingRequest { + string info = 1; +} + +message PingResponse { + string info = 1; +} +message PongRequest { + string info = 1; +} + +message PongResponse { + string info = 1; +} + +// to compile this into grpc, cd in the directory where this file lives and execute: +// protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative pingpong.proto diff --git a/internal/grpc/services/pingpong/proto/pingpong_grpc.pb.go b/internal/grpc/services/pingpong/proto/pingpong_grpc.pb.go new file mode 100644 index 0000000000..31a0f3c7ab --- /dev/null +++ b/internal/grpc/services/pingpong/proto/pingpong_grpc.pb.go @@ -0,0 +1,142 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.7.1 +// source: pingpong.proto + +package proto + +import ( + context "context" + + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// PingPongServiceClient is the client API for PingPongService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PingPongServiceClient interface { + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) + Pong(ctx context.Context, in *PongRequest, opts ...grpc.CallOption) (*PongResponse, error) +} + +type pingPongServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPingPongServiceClient(cc grpc.ClientConnInterface) PingPongServiceClient { + return &pingPongServiceClient{cc} +} + +func (c *pingPongServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, "/revad.pingpong.PingPongService/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pingPongServiceClient) Pong(ctx context.Context, in *PongRequest, opts ...grpc.CallOption) (*PongResponse, error) { + out := new(PongResponse) + err := c.cc.Invoke(ctx, "/revad.pingpong.PingPongService/Pong", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PingPongServiceServer is the server API for PingPongService service. +// All implementations must embed UnimplementedPingPongServiceServer +// for forward compatibility +type PingPongServiceServer interface { + Ping(context.Context, *PingRequest) (*PingResponse, error) + Pong(context.Context, *PongRequest) (*PongResponse, error) + mustEmbedUnimplementedPingPongServiceServer() +} + +// UnimplementedPingPongServiceServer must be embedded to have forward compatible implementations. +type UnimplementedPingPongServiceServer struct { +} + +func (UnimplementedPingPongServiceServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedPingPongServiceServer) Pong(context.Context, *PongRequest) (*PongResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Pong not implemented") +} +func (UnimplementedPingPongServiceServer) mustEmbedUnimplementedPingPongServiceServer() {} + +// UnsafePingPongServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PingPongServiceServer will +// result in compilation errors. +type UnsafePingPongServiceServer interface { + mustEmbedUnimplementedPingPongServiceServer() +} + +func RegisterPingPongServiceServer(s grpc.ServiceRegistrar, srv PingPongServiceServer) { + s.RegisterService(&PingPongService_ServiceDesc, srv) +} + +func _PingPongService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PingPongServiceServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/revad.pingpong.PingPongService/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PingPongServiceServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PingPongService_Pong_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PongRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PingPongServiceServer).Pong(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/revad.pingpong.PingPongService/Pong", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PingPongServiceServer).Pong(ctx, req.(*PongRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// PingPongService_ServiceDesc is the grpc.ServiceDesc for PingPongService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PingPongService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "revad.pingpong.PingPongService", + HandlerType: (*PingPongServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _PingPongService_Ping_Handler, + }, + { + MethodName: "Pong", + Handler: _PingPongService_Pong_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pingpong.proto", +} diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index ef2d3977ae..30a8e037f2 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -25,7 +25,6 @@ import ( link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/plugin" "github.com/cs3org/reva/pkg/publicshare" @@ -136,7 +135,7 @@ func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicS }, nil } - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { log.Error().Msg("error getting user from context") } @@ -167,7 +166,7 @@ func (s *service) RemovePublicShare(ctx context.Context, req *link.RemovePublicS log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "remove").Msg("remove public share") - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) err := s.sm.RevokePublicShare(ctx, user, req.Ref) switch err.(type) { case nil: @@ -216,7 +215,7 @@ func (s *service) GetPublicShare(ctx context.Context, req *link.GetPublicShareRe log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "get").Msg("get public share") - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { log.Error().Msg("error getting user from context") } @@ -242,11 +241,11 @@ func (s *service) GetPublicShare(ctx context.Context, req *link.GetPublicShareRe func (s *service) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRequest) (*link.ListPublicSharesResponse, error) { log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "list").Msg("list public share") - user, _ := ctxpkg.ContextGetUser(ctx) + user, _ := appctx.ContextGetUser(ctx) if req.Opaque != nil { - if v, ok := req.Opaque.Map[ctxpkg.ResoucePathCtx]; ok { - ctx = ctxpkg.ContextSetResourcePath(ctx, string(v.Value)) + if v, ok := req.Opaque.Map[appctx.ResoucePathCtx]; ok { + ctx = appctx.ContextSetResourcePath(ctx, string(v.Value)) } } @@ -269,7 +268,7 @@ func (s *service) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicS log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "update").Msg("update public share") - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { log.Error().Msg("error getting user from context") } diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 5b1c059824..3ac863731e 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -35,11 +35,9 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/sharedconf" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" "google.golang.org/grpc/codes" gstatus "google.golang.org/grpc/status" @@ -344,14 +342,6 @@ func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteSt } func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "CreateContainer") - defer span.End() - - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -397,14 +387,6 @@ func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) } func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Delete") - defer span.End() - - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) switch { case err != nil: @@ -437,20 +419,6 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro } func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Move") - defer span.End() - - span.SetAttributes( - attribute.KeyValue{ - Key: "source", - Value: attribute.StringValue(req.Source.String()), - }, - attribute.KeyValue{ - Key: "destination", - Value: attribute.StringValue(req.Destination.String()), - }, - ) - cs3RefSource, tknSource, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Source) switch { case err != nil: @@ -500,15 +468,6 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide } func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { - ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Stat") - defer span.End() - - span.SetAttributes( - attribute.KeyValue{ - Key: "source", - Value: attribute.StringValue(req.Ref.String()), - }) - var ( tkn string relativePath string diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index ac20f7fcf8..b8efbdc83c 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -41,12 +41,10 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/google/uuid" "github.com/pkg/errors" - "go.opentelemetry.io/otel/attribute" "google.golang.org/grpc" ) @@ -715,15 +713,6 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro }, nil } - // check DeleteRequest for any known opaque properties. - if req.Opaque != nil { - _, ok := req.Opaque.Map["deleting_shared_resource"] - if ok { - // it is a binary key; its existence signals true. Although, do not assume. - ctx = context.WithValue(ctx, appctx.DeletingSharedResource, true) - } - } - if err := s.storage.Delete(ctx, newRef); err != nil { var st *rpc.Status switch err.(type) { @@ -781,14 +770,6 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide } func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "stat") - defer span.End() - - span.SetAttributes(attribute.KeyValue{ - Key: "reference", - Value: attribute.StringValue(req.Ref.String()), - }) - newRef, err := s.unwrap(ctx, req.Ref) if err != nil { // The path might be a virtual view; handle that case diff --git a/internal/grpc/services/usershareprovider/usershareprovider.go b/internal/grpc/services/usershareprovider/usershareprovider.go index d60beece84..5fb9651fb4 100644 --- a/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/internal/grpc/services/usershareprovider/usershareprovider.go @@ -26,7 +26,6 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/plugin" "github.com/cs3org/reva/pkg/rgrpc" @@ -128,7 +127,7 @@ func (s *service) isPathAllowed(path string) bool { } func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShareRequest) (*collaboration.CreateShareResponse, error) { - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_USER && req.Grant.Grantee.GetUserId().Idp == "" { // use logged in user Idp as default. g := &userpb.UserId{OpaqueId: req.Grant.Grantee.GetUserId().OpaqueId, Idp: u.Id.Idp, Type: userpb.UserType_USER_TYPE_PRIMARY} @@ -184,8 +183,8 @@ func (s *service) GetShare(ctx context.Context, req *collaboration.GetShareReque func (s *service) ListShares(ctx context.Context, req *collaboration.ListSharesRequest) (*collaboration.ListSharesResponse, error) { if req.Opaque != nil { - if v, ok := req.Opaque.Map[ctxpkg.ResoucePathCtx]; ok { - ctx = ctxpkg.ContextSetResourcePath(ctx, string(v.Value)) + if v, ok := req.Opaque.Map[appctx.ResoucePathCtx]; ok { + ctx = appctx.ContextSetResourcePath(ctx, string(v.Value)) } } diff --git a/internal/http/interceptors/appctx/appctx.go b/internal/http/interceptors/appctx/appctx.go index a5eac9c3c7..6dd2511d3c 100644 --- a/internal/http/interceptors/appctx/appctx.go +++ b/internal/http/interceptors/appctx/appctx.go @@ -25,9 +25,8 @@ import ( "net/http" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/trace" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/trace" ) // New returns a new HTTP middleware that stores the log @@ -42,14 +41,9 @@ func New(log zerolog.Logger) func(http.Handler) http.Handler { func handler(log zerolog.Logger, h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - span := trace.SpanFromContext(ctx) - defer span.End() - if !span.SpanContext().HasTraceID() { - ctx, span = rtrace.Provider.Tracer("http").Start(ctx, "http interceptor") - } - - sub := log.With().Str("traceid", span.SpanContext().TraceID().String()).Logger() - ctx = appctx.WithLogger(ctx, &sub) + traceID := trace.Get(ctx) + log := log.With().Str("traceid", traceID).Logger() + ctx = appctx.WithLogger(ctx, &log) r = r.WithContext(ctx) h.ServeHTTP(w, r) }) diff --git a/internal/http/interceptors/auth/auth.go b/internal/http/interceptors/auth/auth.go index c664c232f4..6062c52397 100644 --- a/internal/http/interceptors/auth/auth.go +++ b/internal/http/interceptors/auth/auth.go @@ -33,9 +33,9 @@ import ( tokenregistry "github.com/cs3org/reva/internal/http/interceptors/auth/token/registry" tokenwriterregistry "github.com/cs3org/reva/internal/http/interceptors/auth/tokenwriter/registry" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -167,23 +167,19 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err } log := appctx.GetLogger(r.Context()) - isUnprotectedEndpoint := false // For unprotected URLs, we try to authenticate the request in case some service needs it, // but don't return any errors if it fails. if utils.Skip(r.URL.Path, unprotected) { log.Info().Msg("skipping auth check for: " + r.URL.Path) - isUnprotectedEndpoint = true - } - - ctx, err := authenticateUser(w, r, conf, tokenStrategyChain, tokenManager, tokenWriter, credChain, isUnprotectedEndpoint) - if err != nil { - if !isUnprotectedEndpoint { + } else { + ctx, err := authenticateUser(w, r, conf, tokenStrategyChain, tokenManager, tokenWriter, credChain, false) + if err != nil { return } - } else { r = r.WithContext(ctx) } + h.ServeHTTP(w, r) }) } @@ -195,7 +191,7 @@ func authenticateUser(w http.ResponseWriter, r *http.Request, conf *config, toke log := appctx.GetLogger(ctx) // Add the request user-agent to the ctx - ctx = metadata.NewIncomingContext(ctx, metadata.New(map[string]string{ctxpkg.UserAgentHeader: r.UserAgent()})) + ctx = metadata.NewIncomingContext(ctx, metadata.New(map[string]string{appctx.UserAgentHeader: r.UserAgent()})) client, err := pool.GetGatewayServiceClient(pool.Endpoint(conf.GatewaySvc)) if err != nil { @@ -301,10 +297,10 @@ func authenticateUser(w http.ResponseWriter, r *http.Request, conf *config, toke } func ctxWithUserInfo(ctx context.Context, r *http.Request, user *userpb.User, token string) context.Context { - ctx = ctxpkg.ContextSetUser(ctx, user) - ctx = ctxpkg.ContextSetToken(ctx, token) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, token) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.UserAgentHeader, r.UserAgent()) + ctx = appctx.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, token) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, token) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.UserAgentHeader, r.UserAgent()) return ctx } diff --git a/internal/http/interceptors/auth/token/strategy/header/header.go b/internal/http/interceptors/auth/token/strategy/header/header.go index c0acb13e36..f25e55a8f6 100644 --- a/internal/http/interceptors/auth/token/strategy/header/header.go +++ b/internal/http/interceptors/auth/token/strategy/header/header.go @@ -22,8 +22,9 @@ import ( "net/http" "github.com/cs3org/reva/internal/http/interceptors/auth/token/registry" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth" - ctxpkg "github.com/cs3org/reva/pkg/ctx" ) func init() { @@ -36,7 +37,7 @@ type strategy struct { // New returns a new auth strategy that checks for basic auth. func New(m map[string]interface{}) (auth.TokenStrategy, error) { - return &strategy{header: ctxpkg.TokenHeader}, nil + return &strategy{header: appctx.TokenHeader}, nil } func (s *strategy) GetToken(r *http.Request) string { diff --git a/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go b/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go index b5cd899510..24a3fc3551 100644 --- a/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go +++ b/internal/http/interceptors/auth/tokenwriter/strategy/header/header.go @@ -22,8 +22,9 @@ import ( "net/http" "github.com/cs3org/reva/internal/http/interceptors/auth/tokenwriter/registry" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth" - ctxpkg "github.com/cs3org/reva/pkg/ctx" ) func init() { @@ -36,7 +37,7 @@ type strategy struct { // New returns a new token writer strategy that stores token in a header. func New(m map[string]interface{}) (auth.TokenWriter, error) { - return &strategy{header: ctxpkg.TokenHeader}, nil + return &strategy{header: appctx.TokenHeader}, nil } func (s *strategy) WriteToken(token string, w http.ResponseWriter) { diff --git a/internal/http/interceptors/metrics/metrics.go b/internal/http/interceptors/metrics/metrics.go new file mode 100644 index 0000000000..023292d762 --- /dev/null +++ b/internal/http/interceptors/metrics/metrics.go @@ -0,0 +1,106 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Package appctx creates a context with useful +// components attached to the context like loggers and +// token managers. +package metrics + +import ( + "context" + "net/http" + + "github.com/cs3org/reva/pkg/prom/registry" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +var inFlightGauge = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "http_in_flight_requests", + Help: "A gauge of requests currently being served by the wrapped handler.", +}) + +var counter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "http_api_requests_total", + Help: "A counter for requests to the wrapped handler.", + }, + []string{"code", "method"}, +) + +// duration is partitioned by the HTTP method and handler. It uses custom +// buckets based on the expected request duration. +var duration = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "http_request_duration_seconds", + Help: "A histogram of latencies for requests.", + Buckets: []float64{.25, .5, 1, 2.5, 5, 10}, + }, + []string{"handler", "method"}, +) + +// responseSize has no labels, making it a zero-dimensional +// ObserverVec. +var responseSize = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "http_response_size_bytes", + Help: "A histogram of response sizes for requests.", + Buckets: []float64{200, 500, 900, 1500}, + }, + []string{}, +) + +// requestSize has no labels, making it a zero-dimensional +// ObserverVec. +var requestSize = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "http_request_size_bytes", + Help: "A histogram of request sizes for requests.", + Buckets: []float64{200, 500, 900, 1500}, + }, + []string{}, +) + +func init() { + registry.Register("http_metrics", NewPromCollectors) +} + +// New returns a prometheus collector. +func NewPromCollectors(_ context.Context, m map[string]interface{}) ([]prometheus.Collector, error) { + return []prometheus.Collector{inFlightGauge, counter, duration, responseSize}, nil +} + +// New returns a new HTTP middleware that stores the log +// in the context with request ID information. +func New() func(h http.Handler) http.Handler { + chain := func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h = promhttp.InstrumentHandlerDuration(duration.MustCurryWith(prometheus.Labels{"handler": r.URL.Path}), + promhttp.InstrumentHandlerCounter(counter, + promhttp.InstrumentHandlerResponseSize(responseSize, + promhttp.InstrumentHandlerRequestSize(requestSize, + promhttp.InstrumentHandlerInFlight(inFlightGauge, h), + ), + ), + ), + ) + h.ServeHTTP(w, r) + }) + } + return chain +} diff --git a/internal/http/interceptors/trace/trace.go b/internal/http/interceptors/trace/trace.go new file mode 100644 index 0000000000..710ead452f --- /dev/null +++ b/internal/http/interceptors/trace/trace.go @@ -0,0 +1,68 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Package appctx creates a context with useful +// components attached to the context like loggers and +// token managers. +package trace + +import ( + "context" + "net/http" + + "github.com/cs3org/reva/pkg/trace" + "google.golang.org/grpc/metadata" +) + +// New returns a new HTTP middleware that stores the log +// in the context with request ID information. +func New() func(http.Handler) http.Handler { + return handler +} + +func handler(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + traceID, ctx := getTraceID(r) + + // in case the http service will call a grpc service, + // we set the outgoing context so the trace information is + // passed through the two protocols. + ctx = metadata.AppendToOutgoingContext(ctx, "revad-grpc-trace-id", traceID) + + r = r.WithContext(ctx) + h.ServeHTTP(w, r) + }) +} + +func getTraceID(r *http.Request) (string, context.Context) { + ctx := r.Context() + // try to get trace from context + traceID := trace.Get(ctx) + if traceID == "" { + // check if traceID is coming from header + traceID = r.Header.Get("X-Trace-ID") + if traceID == "" { + traceID = r.Header.Get("X-Request-ID") + if traceID == "" { + traceID = trace.Generate() + } + } + ctx = trace.Set(ctx, traceID) + } + return traceID, ctx +} diff --git a/internal/http/interceptors/trace/trace_test.go b/internal/http/interceptors/trace/trace_test.go new file mode 100644 index 0000000000..3f54f0ef98 --- /dev/null +++ b/internal/http/interceptors/trace/trace_test.go @@ -0,0 +1,74 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package trace + +import ( + "context" + "net/http" + "testing" + + "github.com/cs3org/reva/pkg/trace" +) + +type testPair struct { + e string + r *http.Request +} + +func TestGetTrace(t *testing.T) { + pairs := []*testPair{ + { + r: newRequest(context.Background(), map[string]string{"X-Trace-ID": "def"}), + e: "def", + }, + { + r: newRequest(context.Background(), map[string]string{"X-Request-ID": "abc"}), + e: "abc", + }, + { + r: newRequest(trace.Set(context.Background(), "fgh"), nil), + e: "fgh", + }, + } + + for _, p := range pairs { + got, _ := getTraceID(p.r) + t.Logf("headers: %+v context: %+v got: %+v\n", p.r, p.r.Context(), got) + if got != p.e { + t.Fatal("expected: "+p.e, "got: "+got) + return + } + } +} + +func newRequest(ctx context.Context, headers map[string]string) *http.Request { + r, _ := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost", nil) + for k, v := range headers { + r.Header.Set(k, v) + } + return r +} + +func TestGenerateTrace(t *testing.T) { + got, _ := getTraceID(newRequest(context.Background(), nil)) + if len(got) != 36 { + t.Fatal("expected random generated UUID 36 chars trace ID but got:" + got) + return + } +} diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index 1fa32a63a6..de86c32753 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -20,6 +20,7 @@ package appprovider import ( "context" + "crypto/tls" "encoding/json" "net/http" "path" @@ -32,9 +33,9 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" @@ -234,17 +235,16 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { ep, token = p.UploadEndpoint, p.Token } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, ep, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, ep, nil) if err != nil { writeError(w, r, appErrorServerError, "failed to create the file", err) return } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := rhttp.GetHTTPClient( - rhttp.Context(ctx), - rhttp.Insecure(s.conf.Insecure), - ).Do(httpReq) + + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: s.conf.Insecure}} + httpRes, err := httpclient.New(httpclient.RoundTripper(tr)).Do(httpReq) if err != nil { writeError(w, r, appErrorServerError, "failed to create the file", err) return diff --git a/internal/http/services/archiver/handler.go b/internal/http/services/archiver/handler.go index 79d62bafe5..f286206708 100644 --- a/internal/http/services/archiver/handler.go +++ b/internal/http/services/archiver/handler.go @@ -20,6 +20,7 @@ package archiver import ( "context" + "crypto/tls" "errors" "fmt" "net/http" @@ -34,8 +35,8 @@ import ( "github.com/cs3org/reva/internal/http/services/archiver/manager" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/downloader" @@ -93,10 +94,13 @@ func New(ctx context.Context, conf map[string]interface{}) (global.Service, erro allowedFolderRegex = append(allowedFolderRegex, regex) } + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}} + hc := httpclient.New(httpclient.RoundTripper(tr), httpclient.Timeout(time.Duration(c.Timeout*int64(time.Second)))) + return &svc{ config: &c, gtwClient: gtw, - downloader: downloader.NewDownloader(gtw, rhttp.Insecure(c.Insecure), rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second)))), + downloader: downloader.NewDownloader(gtw, hc), walker: walker.NewWalker(gtw), allowedFolders: allowedFolderRegex, }, nil diff --git a/internal/http/services/datagateway/datagateway.go b/internal/http/services/datagateway/datagateway.go index a8e4a8065f..8e66217918 100644 --- a/internal/http/services/datagateway/datagateway.go +++ b/internal/http/services/datagateway/datagateway.go @@ -20,6 +20,7 @@ package datagateway import ( "context" + "crypto/tls" "io" "net/http" "net/url" @@ -29,7 +30,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils/cfg" @@ -72,7 +73,7 @@ func (c *config) ApplyDefaults() { type svc struct { conf *config handler http.Handler - client *http.Client + client *httpclient.Client } // New returns a new datagateway. @@ -82,11 +83,15 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) return nil, err } + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}, + } + s := &svc{ conf: &c, - client: rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), - rhttp.Insecure(c.Insecure), + client: httpclient.New( + httpclient.Timeout(time.Duration(c.Timeout*int64(time.Second))), + httpclient.RoundTripper(tr), ), } s.setHandler() @@ -181,7 +186,7 @@ func (s *svc) doHead(w http.ResponseWriter, r *http.Request) { log.Debug().Str("target", claims.Target).Msg("sending request to internal data server") httpClient := s.client - httpReq, err := rhttp.NewRequest(ctx, http.MethodHead, claims.Target, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodHead, claims.Target, nil) if err != nil { log.Error().Err(err).Msg("wrong request") w.WriteHeader(http.StatusInternalServerError) @@ -233,7 +238,7 @@ func (s *svc) doGet(w http.ResponseWriter, r *http.Request) { log.Debug().Str("target", claims.Target).Msg("sending request to internal data server") httpClient := s.client - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, claims.Target, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, claims.Target, nil) if err != nil { log.Error().Err(err).Msg("wrong request") w.WriteHeader(http.StatusInternalServerError) @@ -310,7 +315,7 @@ func (s *svc) doPut(w http.ResponseWriter, r *http.Request) { log.Debug().Str("target", claims.Target).Msg("sending request to internal data server") httpClient := s.client - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, target, r.Body) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, target, r.Body) if err != nil { log.Err(err).Msg("wrong request") w.WriteHeader(http.StatusInternalServerError) @@ -369,7 +374,7 @@ func (s *svc) doPatch(w http.ResponseWriter, r *http.Request) { log.Debug().Str("target", claims.Target).Msg("sending request to internal data server") httpClient := s.client - httpReq, err := rhttp.NewRequest(ctx, http.MethodPatch, target, r.Body) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPatch, target, r.Body) if err != nil { log.Err(err).Msg("wrong request") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/loader/loader.go b/internal/http/services/loader/loader.go index c15d96b68a..e680ad4e3a 100644 --- a/internal/http/services/loader/loader.go +++ b/internal/http/services/loader/loader.go @@ -32,6 +32,7 @@ import ( _ "github.com/cs3org/reva/internal/http/services/overleaf" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocdav" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocs" + _ "github.com/cs3org/reva/internal/http/services/pingpong" _ "github.com/cs3org/reva/internal/http/services/plugins" _ "github.com/cs3org/reva/internal/http/services/preferences" _ "github.com/cs3org/reva/internal/http/services/prometheus" diff --git a/internal/http/services/ocmd/shares.go b/internal/http/services/ocmd/shares.go index ea001b3af4..ae2a8686f9 100644 --- a/internal/http/services/ocmd/shares.go +++ b/internal/http/services/ocmd/shares.go @@ -43,8 +43,8 @@ import ( "github.com/cs3org/reva/internal/http/services/reqres" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/utils" "github.com/go-playground/validator/v10" ) @@ -282,12 +282,12 @@ func discoverOcmWebdavRoot(r *http.Request) (string, error) { log := appctx.GetLogger(ctx) log.Debug().Str("sender", r.Host).Msg("received OCM 1.0 share, attempting to discover sender endpoint") - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, r.Host+"/ocm-provider", nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, r.Host+"/ocm-provider", nil) if err != nil { return "", err } - httpClient := rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(10 * int64(time.Second))), + httpClient := httpclient.New( + httpclient.Timeout(time.Duration(10 * int64(time.Second))), ) httpRes, err := httpClient.Do(httpReq) if err != nil { diff --git a/internal/http/services/overleaf/overleaf.go b/internal/http/services/overleaf/overleaf.go index d3ea3f419f..e6916e81fd 100644 --- a/internal/http/services/overleaf/overleaf.go +++ b/internal/http/services/overleaf/overleaf.go @@ -35,10 +35,9 @@ import ( storagepb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/internal/http/services/reqres" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/token/manager/jwt" @@ -165,7 +164,7 @@ func (s *svc) handleExport(w http.ResponseWriter, r *http.Request) { return } - token, ok := ctxpkg.ContextGetToken(ctx) + token, ok := appctx.ContextGetToken(ctx) if !ok || token == "" { reqres.WriteError(w, r, reqres.APIErrorUnauthenticated, "Access token is invalid or empty", err) return @@ -196,7 +195,7 @@ func (s *svc) handleExport(w http.ResponseWriter, r *http.Request) { return } - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) scope, err := scope.AddResourceInfoScope(resource, authpb.Role_ROLE_VIEWER, nil) if err != nil { @@ -211,7 +210,7 @@ func (s *svc) handleExport(w http.ResponseWriter, r *http.Request) { } // Setting up archiver request - archHTTPReq, err := rhttp.NewRequest(ctx, http.MethodGet, s.conf.ArchiverURL, nil) + archHTTPReq, err := http.NewRequestWithContext(ctx, http.MethodGet, s.conf.ArchiverURL, nil) if err != nil { reqres.WriteError(w, r, reqres.APIErrorServerError, "overleaf: error setting up http request", nil) return @@ -227,7 +226,7 @@ func (s *svc) handleExport(w http.ResponseWriter, r *http.Request) { // Setting up Overleaf request appURL := s.conf.appURL + "/docs" - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, appURL, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, appURL, nil) if err != nil { reqres.WriteError(w, r, reqres.APIErrorServerError, "overleaf: error setting up http request", nil) return diff --git a/internal/http/services/owncloud/ocdav/copy.go b/internal/http/services/owncloud/ocdav/copy.go index 8277fa2370..e3bf05fda5 100644 --- a/internal/http/services/owncloud/ocdav/copy.go +++ b/internal/http/services/owncloud/ocdav/copy.go @@ -32,9 +32,7 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/rs/zerolog" ) @@ -49,9 +47,7 @@ type copy struct { type intermediateDirRefFunc func() (*provider.Reference, *rpc.Status, error) func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "copy") - defer span.End() - + ctx := r.Context() if s.c.EnableHTTPTpc { if r.Header.Get("Source") != "" { // HTTP Third-Party Copy Pull mode @@ -236,7 +232,7 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie // 3. do download - httpDownloadReq, err := rhttp.NewRequest(ctx, http.MethodGet, downloadEP, nil) + httpDownloadReq, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadEP, nil) if err != nil { return err } @@ -253,7 +249,7 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie // 4. do upload - httpUploadReq, err := rhttp.NewRequest(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) + httpUploadReq, err := http.NewRequestWithContext(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) if err != nil { return err } @@ -272,9 +268,7 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie } func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_copy") - defer span.End() - + ctx := r.Context() dst, err := extractDestination(r) if err != nil { w.WriteHeader(http.StatusBadRequest) @@ -452,7 +446,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie } // 3. do download - httpDownloadReq, err := rhttp.NewRequest(ctx, http.MethodGet, downloadEP, nil) + httpDownloadReq, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadEP, nil) if err != nil { return err } @@ -471,7 +465,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie // 4. do upload - httpUploadReq, err := rhttp.NewRequest(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) + httpUploadReq, err := http.NewRequestWithContext(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) if err != nil { return err } diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 65ba52e31a..a4ff90430b 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -30,7 +30,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/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" "google.golang.org/grpc/metadata" @@ -107,7 +107,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { // https://github.com/owncloud/core/blob/18475dac812064b21dabcc50f25ef3ffe55691a5/tests/acceptance/features/apiWebdavOperations/propfind.feature if r.URL.Path == "/files" { log.Debug().Str("path", r.URL.Path).Msg("method not allowed") - contextUser, ok := ctxpkg.ContextGetUser(ctx) + contextUser, ok := appctx.ContextGetUser(ctx) if ok { r.URL.Path = path.Join(r.URL.Path, contextUser.Username) } @@ -147,7 +147,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { requestUserID, r.URL.Path = router.ShiftPath(r.URL.Path) // note: some requests like OPTIONS don't forward the user - contextUser, ok := ctxpkg.ContextGetUser(ctx) + contextUser, ok := appctx.ContextGetUser(ctx) if ok && isOwner(requestUserID, contextUser) { // use home storage handler when user was detected base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "files", requestUserID) @@ -225,9 +225,9 @@ func (h *DavHandler) Handler(s *svc) http.Handler { return } - ctx = ctxpkg.ContextSetToken(ctx, authRes.Token) - ctx = ctxpkg.ContextSetUser(ctx, authRes.User) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, authRes.Token) + ctx = appctx.ContextSetToken(ctx, authRes.Token) + ctx = appctx.ContextSetUser(ctx, authRes.User) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, authRes.Token) log.Debug().Str("token", token).Interface("user", authRes.User).Msg("OCM user authenticated") @@ -274,9 +274,9 @@ func (h *DavHandler) Handler(s *svc) http.Handler { return } - ctx = ctxpkg.ContextSetToken(ctx, res.Token) - ctx = ctxpkg.ContextSetUser(ctx, res.User) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, res.Token) + ctx = appctx.ContextSetToken(ctx, res.Token) + ctx = appctx.ContextSetUser(ctx, res.User) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, res.Token) r = r.WithContext(ctx) diff --git a/internal/http/services/owncloud/ocdav/delete.go b/internal/http/services/owncloud/ocdav/delete.go index 8be2e37443..80bde692d9 100644 --- a/internal/http/services/owncloud/ocdav/delete.go +++ b/internal/http/services/owncloud/ocdav/delete.go @@ -27,7 +27,6 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/rs/zerolog" ) @@ -47,13 +46,9 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R return } - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "delete") - defer span.End() - req := &provider.DeleteRequest{Ref: ref} res, err := client.Delete(ctx, req) if err != nil { - span.RecordError(err) log.Error().Err(err).Msg("error performing delete grpc request") w.WriteHeader(http.StatusInternalServerError) return @@ -96,8 +91,6 @@ func (s *svc) handleDelete(ctx context.Context, w http.ResponseWriter, r *http.R func (s *svc) handleSpacesDelete(w http.ResponseWriter, r *http.Request, spaceID string) { ctx := r.Context() - ctx, span := rtrace.Provider.Tracer("reva").Start(ctx, "spaces_delete") - defer span.End() sublog := appctx.GetLogger(ctx).With().Logger() // retrieve a specific storage space diff --git a/internal/http/services/owncloud/ocdav/download.go b/internal/http/services/owncloud/ocdav/download.go index 2607c8148f..3f1623d500 100644 --- a/internal/http/services/owncloud/ocdav/download.go +++ b/internal/http/services/owncloud/ocdav/download.go @@ -20,10 +20,12 @@ package ocdav import ( "context" + "crypto/tls" "io" "net/http" "path" "strings" + "time" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -31,9 +33,8 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/internal/http/services/archiver/manager" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/storage/utils/downloader" "github.com/cs3org/reva/pkg/storage/utils/walker" "github.com/pkg/errors" @@ -84,8 +85,8 @@ func (s *svc) authenticate(ctx context.Context, token string) (context.Context, return nil, errors.New(res.Status.Message) } - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, res.Token) - ctx = ctxpkg.ContextSetToken(ctx, res.Token) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, res.Token) + ctx = appctx.ContextSetToken(ctx, res.Token) return ctx, nil } @@ -188,7 +189,11 @@ func (s *svc) downloadFile(ctx context.Context, w http.ResponseWriter, res *prov s.handleHTTPError(w, err, log) return } - d := downloader.NewDownloader(c) + + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: s.c.Insecure}} + hc := httpclient.New(httpclient.RoundTripper(tr), httpclient.Timeout(time.Duration(s.c.Timeout*int64(time.Second)))) + + d := downloader.NewDownloader(c, hc) r, err := d.Download(ctx, res.Path, "") if err != nil { s.handleHTTPError(w, err, log) @@ -226,7 +231,10 @@ func (s *svc) downloadArchive(ctx context.Context, w http.ResponseWriter, token return } - downloader := downloader.NewDownloader(gtw, rhttp.Context(ctx)) + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: s.c.Insecure}} + hc := httpclient.New(httpclient.RoundTripper(tr), httpclient.Timeout(time.Duration(s.c.Timeout*int64(time.Second)))) + + downloader := downloader.NewDownloader(gtw, hc) walker := walker.NewWalker(gtw) archiver, err := manager.NewArchiver(resources, walker, downloader, manager.Config{ diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index 338b7bc883..9343d1c85d 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -33,17 +33,13 @@ import ( "github.com/cs3org/reva/internal/grpc/services/storageprovider" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/rhttp" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func (s *svc) handlePathGet(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "get") - defer span.End() - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Str("svc", "ocdav").Str("handler", "get").Logger() @@ -94,7 +90,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, ep, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, ep, nil) if err != nil { log.Error().Err(err).Msg("error creating http request") w.WriteHeader(http.StatusInternalServerError) @@ -160,9 +156,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ } func (s *svc) handleSpacesGet(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_get") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Str("handler", "get").Logger() // retrieve a specific storage space diff --git a/internal/http/services/owncloud/ocdav/head.go b/internal/http/services/owncloud/ocdav/head.go index ff81eacef9..144eeebc0b 100644 --- a/internal/http/services/owncloud/ocdav/head.go +++ b/internal/http/services/owncloud/ocdav/head.go @@ -31,16 +31,13 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/internal/grpc/services/storageprovider" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func (s *svc) handlePathHead(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "head") - defer span.End() - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -90,9 +87,7 @@ func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Req } func (s *svc) handleSpacesHead(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_head") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Logger() spaceRef, status, err := s.lookUpStorageSpaceReference(ctx, spaceID, r.URL.Path) diff --git a/internal/http/services/owncloud/ocdav/mkcol.go b/internal/http/services/owncloud/ocdav/mkcol.go index 478778a515..02f35b5027 100644 --- a/internal/http/services/owncloud/ocdav/mkcol.go +++ b/internal/http/services/owncloud/ocdav/mkcol.go @@ -28,14 +28,11 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/rs/zerolog" ) func (s *svc) handlePathMkcol(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "mkcol") - defer span.End() - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) for _, r := range nameRules { if !r.Test(fn) { @@ -52,9 +49,7 @@ func (s *svc) handlePathMkcol(w http.ResponseWriter, r *http.Request, ns string) } func (s *svc) handleSpacesMkCol(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), "spaces_mkcol") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Str("handler", "mkcol").Logger() parentRef, rpcStatus, err := s.lookUpStorageSpaceReference(ctx, spaceID, path.Dir(r.URL.Path)) diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index c159c2a733..3c82ab36c4 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -29,15 +29,12 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "move") - defer span.End() - + ctx := r.Context() srcPath := path.Join(ns, r.URL.Path) dstPath, err := extractDestination(r) if err != nil { @@ -67,9 +64,7 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string) } func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_move") - defer span.End() - + ctx := r.Context() dst, err := extractDestination(r) if err != nil { w.WriteHeader(http.StatusBadRequest) diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 38dd3d8354..6606be76f5 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -20,6 +20,7 @@ package ocdav import ( "context" + "crypto/tls" "fmt" "net/http" "net/url" @@ -31,11 +32,11 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/notification/notificationhelper" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" @@ -139,7 +140,7 @@ type svc struct { webDavHandler *WebDavHandler davHandler *DavHandler favoritesManager favorite.Manager - client *http.Client + client *httpclient.Client notificationHelper *notificationhelper.NotificationHelper } @@ -163,13 +164,14 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) } log := appctx.GetLogger(ctx) + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}} s := &svc{ c: &c, webDavHandler: new(WebDavHandler), davHandler: new(DavHandler), - client: rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), - rhttp.Insecure(c.Insecure), + client: httpclient.New( + httpclient.Timeout(time.Duration(c.Timeout*int64(time.Second))), + httpclient.RoundTripper(tr), ), favoritesManager: fm, notificationHelper: notificationhelper.New("ocdav", c.Notifications, log), @@ -289,7 +291,7 @@ func applyLayout(ctx context.Context, ns string, useLoggedInUserNS bool, request // is not the same as the logged in user. In that case, we'll treat fileOwner // as the username whose files are to be accessed and use that in the // namespace template. - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok || !useLoggedInUserNS { requestUserID, _ := router.ShiftPath(requestPath) u = &userpb.User{ diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 1166cba30b..ab6e341623 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -42,16 +42,13 @@ import ( "github.com/cs3org/reva/internal/grpc/services/storageprovider" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/share" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" ) const ( @@ -71,11 +68,7 @@ const ( // ns is the namespace that is prefixed to the path in the cs3 namespace. func (s *svc) handlePathPropfind(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("reva").Start(r.Context(), fmt.Sprintf("%s %v", r.Method, r.URL.Path)) - defer span.End() - - span.SetAttributes(attribute.String("component", "ocdav")) - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -98,8 +91,7 @@ func (s *svc) handlePathPropfind(w http.ResponseWriter, r *http.Request, ns stri } func (s *svc) handleSpacesPropfind(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_propfind") - defer span.End() + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Logger() @@ -145,9 +137,6 @@ func (s *svc) handleSpacesPropfind(w http.ResponseWriter, r *http.Request, space } func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, namespace string, pf propfindXML, parentInfo *provider.ResourceInfo, resourceInfos []*provider.ResourceInfo, log zerolog.Logger) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(ctx, "propfind_response") - defer span.End() - linkFilters := make([]*link.ListPublicSharesRequest_Filter, 0, len(resourceInfos)) shareFilters := make([]*collaboration.Filter, 0, len(resourceInfos)) for i := range resourceInfos { @@ -166,7 +155,7 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht listResp, err := client.ListPublicShares(ctx, &link.ListPublicSharesRequest{ Opaque: &types.Opaque{ Map: map[string]*types.OpaqueEntry{ - ctxpkg.ResoucePathCtx: {Decoder: "plain", Value: []byte(parentInfo.Path)}, + appctx.ResoucePathCtx: {Decoder: "plain", Value: []byte(parentInfo.Path)}, }, }, Filters: linkFilters, @@ -178,7 +167,6 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht } } else { log.Error().Err(err).Msg("propfindResponse: couldn't list public shares") - span.SetStatus(codes.Error, err.Error()) } var usershares map[string]struct{} @@ -186,7 +174,7 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht Filters: shareFilters, Opaque: &types.Opaque{ Map: map[string]*types.OpaqueEntry{ - ctxpkg.ResoucePathCtx: {Decoder: "plain", Value: []byte(parentInfo.Path)}, + appctx.ResoucePathCtx: {Decoder: "plain", Value: []byte(parentInfo.Path)}, }, }, }) @@ -197,7 +185,6 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht } } else { log.Error().Err(err).Msg("propfindResponse: couldn't list user shares") - span.SetStatus(codes.Error, err.Error()) } propRes, err := s.multistatusResponse(ctx, &pf, resourceInfos, namespace, usershares, linkshares) @@ -747,10 +734,10 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide case "public-link-share-owner": if ls != nil && ls.Owner != nil { if isCurrentUserOwner(ctx, ls.Owner) { - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:public-link-share-owner", u.Username)) } else { - u, _ := ctxpkg.ContextGetUser(ctx) + u, _ := appctx.ContextGetUser(ctx) sublog.Error().Interface("share", ls).Interface("user", u).Msg("the current user in the context should be the owner of a public link share") propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:public-link-share-owner", "")) } @@ -779,7 +766,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide case "owner-id": // phoenix only if md.Owner != nil { if isCurrentUserOwner(ctx, md.Owner) { - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:owner-id", u.Username)) } else { sublog.Debug().Msg("TODO fetch user username") @@ -868,7 +855,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide case "owner-display-name": // phoenix only if md.Owner != nil { if isCurrentUserOwner(ctx, md.Owner) { - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:owner-display-name", u.DisplayName)) } else { sublog.Debug().Msg("TODO fetch user displayname") @@ -1049,7 +1036,7 @@ func quoteEtag(etag string) string { // a file is only yours if you are the owner. func isCurrentUserOwner(ctx context.Context, owner *userv1beta1.UserId) bool { - contextUser, ok := ctxpkg.ContextGetUser(ctx) + contextUser, ok := appctx.ContextGetUser(ctx) if ok && contextUser.Id != nil && owner != nil && contextUser.Id.Idp == owner.Idp && contextUser.Id.OpaqueId == owner.OpaqueId { diff --git a/internal/http/services/owncloud/ocdav/proppatch.go b/internal/http/services/owncloud/ocdav/proppatch.go index cd246f821e..abe928ede8 100644 --- a/internal/http/services/owncloud/ocdav/proppatch.go +++ b/internal/http/services/owncloud/ocdav/proppatch.go @@ -30,16 +30,13 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" - rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/pkg/errors" "github.com/rs/zerolog" ) func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "proppatch") - defer span.End() - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -104,9 +101,7 @@ func (s *svc) handlePathProppatch(w http.ResponseWriter, r *http.Request, ns str } func (s *svc) handleSpacesProppatch(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_proppatch") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("spaceid", spaceID).Logger() pp, status, err := readProppatch(r.Body) @@ -239,7 +234,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt w.WriteHeader(http.StatusInternalServerError) return nil, nil, false } - currentUser := ctxpkg.ContextMustGetUser(ctx) + currentUser := appctx.ContextMustGetUser(ctx) err = s.favoritesManager.UnsetFavorite(ctx, currentUser.Id, statRes.Info) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -280,7 +275,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt w.WriteHeader(http.StatusInternalServerError) return nil, nil, false } - currentUser := ctxpkg.ContextMustGetUser(ctx) + currentUser := appctx.ContextMustGetUser(ctx) err = s.favoritesManager.SetFavorite(ctx, currentUser.Id, statRes.Info) if err != nil { w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocdav/publicfile.go b/internal/http/services/owncloud/ocdav/publicfile.go index e25a82f1e3..b9b5fbb169 100644 --- a/internal/http/services/owncloud/ocdav/publicfile.go +++ b/internal/http/services/owncloud/ocdav/publicfile.go @@ -27,7 +27,6 @@ import ( typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" ) // PublicFileHandler handles requests on a shared file. it needs to be wrapped in a collection. @@ -86,9 +85,7 @@ func (h *PublicFileHandler) Handler(s *svc) http.Handler { } func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bool { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "adjustResourcePathInURL") - defer span.End() - + ctx := r.Context() // find actual file name tokenStatInfo := ctx.Value(tokenStatInfoKey{}).(*provider.ResourceInfo) sublog := appctx.GetLogger(ctx).With().Interface("tokenStatInfo", tokenStatInfo).Logger() @@ -125,9 +122,7 @@ func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bo // ns is the namespace that is prefixed to the path in the cs3 namespace. func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns string, onContainer bool) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "token_propfind") - defer span.End() - + ctx := r.Context() tokenStatInfo := ctx.Value(tokenStatInfoKey{}).(*provider.ResourceInfo) sublog := appctx.GetLogger(ctx).With().Interface("tokenStatInfo", tokenStatInfo).Logger() sublog.Debug().Msg("handlePropfindOnToken") diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index bc7a314292..cc846f5b5a 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -34,12 +34,9 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/notification/trigger" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage/utils/chunking" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" @@ -113,9 +110,7 @@ func isContentRange(r *http.Request) bool { } func (s *svc) handlePathPut(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "put") - defer span.End() - + ctx := r.Context() fn := path.Join(ns, r.URL.Path) sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger() @@ -270,7 +265,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, ep, r.Body) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, ep, r.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -406,7 +401,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } func userInCtxHasUploaderRole(ctx context.Context) bool { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { return false } @@ -436,9 +431,7 @@ func split(p string) (string, string) { } func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_put") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Logger() spaceRef, status, err := s.lookUpStorageSpaceReference(ctx, spaceID, r.URL.Path) diff --git a/internal/http/services/owncloud/ocdav/report.go b/internal/http/services/owncloud/ocdav/report.go index bedcad8c14..b77d967865 100644 --- a/internal/http/services/owncloud/ocdav/report.go +++ b/internal/http/services/owncloud/ocdav/report.go @@ -27,7 +27,6 @@ import ( rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" ) const ( @@ -79,7 +78,7 @@ func (s *svc) doFilterFiles(w http.ResponseWriter, r *http.Request, ff *reportFi if ff.Rules.Favorite { // List the users favorite resources. - currentUser := ctxpkg.ContextMustGetUser(ctx) + currentUser := appctx.ContextMustGetUser(ctx) favorites, err := s.favoritesManager.ListFavorites(ctx, currentUser.Id) if err != nil { log.Error().Err(err).Msg("error getting favorites") diff --git a/internal/http/services/owncloud/ocdav/tpc.go b/internal/http/services/owncloud/ocdav/tpc.go index f6922abf6e..8e1007e4c3 100644 --- a/internal/http/services/owncloud/ocdav/tpc.go +++ b/internal/http/services/owncloud/ocdav/tpc.go @@ -36,7 +36,6 @@ import ( "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" ) const ( @@ -240,7 +239,7 @@ func (s *svc) performHTTPPull(ctx context.Context, client gateway.GatewayAPIClie tempReader := io.TeeReader(httpDownloadRes.Body, &wc) // do Upload - httpUploadReq, err := rhttp.NewRequest(ctx, http.MethodPut, uploadEP, tempReader) + httpUploadReq, err := http.NewRequestWithContext(ctx, http.MethodPut, uploadEP, tempReader) if err != nil { w.WriteHeader(http.StatusInternalServerError) return err @@ -362,7 +361,7 @@ func (s *svc) performHTTPPush(ctx context.Context, client gateway.GatewayAPIClie } // do download - httpDownloadReq, err := rhttp.NewRequest(ctx, http.MethodGet, downloadEP, nil) + httpDownloadReq, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadEP, nil) if err != nil { w.WriteHeader(http.StatusInternalServerError) return err diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 315d613a32..bcc94cc7eb 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -33,10 +33,9 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" ) @@ -71,7 +70,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { return } - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { w.WriteHeader(http.StatusBadRequest) return @@ -163,9 +162,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler { } func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "list_trashbin") - defer span.End() - + ctx := r.Context() depth := r.Header.Get(HeaderDepth) if depth == "" { depth = "1" @@ -439,9 +436,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use } func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, dst, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "restore") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Logger() overwrite := r.Header.Get(HeaderOverwrite) @@ -587,9 +582,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc // delete has only a key. func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc, u *userpb.User, basePath, key, itemPath string) { - ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "erase") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Str("key", key).Logger() client, err := s.getClient() diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index bdc65cdff7..e533af289b 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -33,8 +33,6 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/rhttp" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" @@ -42,9 +40,7 @@ import ( ) func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "tus-post") - defer span.End() - + ctx := r.Context() // read filename from metadata meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata)) for _, r := range nameRules { @@ -65,9 +61,7 @@ func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns strin } func (s *svc) handleSpacesTusPost(w http.ResponseWriter, r *http.Request, spaceID string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces-tus-post") - defer span.End() - + ctx := r.Context() // read filename from metadata meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata)) if meta["filename"] == "" { @@ -226,7 +220,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. var httpRes *http.Response - httpReq, err := rhttp.NewRequest(ctx, http.MethodPatch, ep, r.Body) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPatch, ep, r.Body) if err != nil { log.Debug().Err(err).Msg("wrong request") w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocdav/versions.go b/internal/http/services/owncloud/ocdav/versions.go index 7c42d2900f..c8953444be 100644 --- a/internal/http/services/owncloud/ocdav/versions.go +++ b/internal/http/services/owncloud/ocdav/versions.go @@ -30,9 +30,9 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/storage/utils/downloader" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils/resourceid" ) @@ -88,9 +88,7 @@ func (h *VersionsHandler) Handler(s *svc, rid *provider.ResourceId) http.Handler } func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "listVersions") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Logger() pf, status, err := readPropfind(r.Body) @@ -189,9 +187,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request, } func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId, key string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "restore") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Str("key", key).Logger() client, err := s.getClient() @@ -220,9 +216,7 @@ func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *s } func (h *VersionsHandler) doDownload(w http.ResponseWriter, r *http.Request, s *svc, rid *provider.ResourceId, key string) { - ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "restore") - defer span.End() - + ctx := r.Context() sublog := appctx.GetLogger(ctx).With().Interface("resourceid", rid).Str("key", key).Logger() client, err := s.getClient() @@ -253,7 +247,7 @@ func (h *VersionsHandler) doDownload(w http.ResponseWriter, r *http.Request, s * w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fname)) w.Header().Set("Content-Transfer-Encoding", "binary") - down := downloader.NewDownloader(client) + down := downloader.NewDownloader(client, httpclient.New()) d, err := down.Download(ctx, resStat.Info.Path, key) if err != nil { w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/http/services/owncloud/ocs/cache.go b/internal/http/services/owncloud/ocs/cache.go index bfb9b35d49..ce231b1816 100644 --- a/internal/http/services/owncloud/ocs/cache.go +++ b/internal/http/services/owncloud/ocs/cache.go @@ -24,14 +24,14 @@ import ( "net/http/httptest" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "google.golang.org/grpc/metadata" ) func (s *svc) cacheWarmup(w http.ResponseWriter, r *http.Request) { if s.warmupCacheTracker != nil { - u, ok1 := ctxpkg.ContextGetUser(r.Context()) - tkn, ok2 := ctxpkg.ContextGetToken(r.Context()) + u, ok1 := appctx.ContextGetUser(r.Context()) + tkn, ok2 := appctx.ContextGetToken(r.Context()) if !ok1 || !ok2 { return } @@ -44,9 +44,9 @@ func (s *svc) cacheWarmup(w http.ResponseWriter, r *http.Request) { // TODO: Check if we can come up with a better solution, eg, https://stackoverflow.com/a/54132324 ctx := context.Background() ctx = appctx.WithLogger(ctx, log) - ctx = ctxpkg.ContextSetUser(ctx, u) - ctx = ctxpkg.ContextSetToken(ctx, tkn) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, tkn) + ctx = appctx.ContextSetUser(ctx, u) + ctx = appctx.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, tkn) req, _ := http.NewRequest(http.MethodGet, "", nil) req = req.WithContext(ctx) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go index 8041595938..f77febfbe2 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/group.go @@ -29,7 +29,8 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" ) @@ -85,7 +86,7 @@ func (h *Handler) createGroupShare(w http.ResponseWriter, r *http.Request, statI if shareID, ok := h.createCs3Share(ctx, w, r, c, createShareReq, statInfo); ok { notify, _ := strconv.ParseBool(r.FormValue("notify")) if notify { - granter, ok := ctxpkg.ContextGetUser(ctx) + granter, ok := appctx.ContextGetUser(ctx) if ok { h.SendShareNotification(shareID.OpaqueId, granter, groupRes.Group, statInfo) } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index feb340594a..f98169c05d 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -34,7 +34,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/notification" "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -421,7 +421,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar if ok { ok2 := permissionsStayUploader(before, newPermissions) - u, ok3 := ctxpkg.ContextGetUser(r.Context()) + u, ok3 := appctx.ContextGetUser(r.Context()) if ok2 && ok3 { notifyUploads, _ := strconv.ParseBool(newNotifyUploads[0]) @@ -451,7 +451,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar if ok { ok2 := permissionsStayUploader(before, newPermissions) - u, ok3 := ctxpkg.ContextGetUser(r.Context()) + u, ok3 := appctx.ContextGetUser(r.Context()) if ok2 && ok3 { notifyUploadsExtraRecipients := newNotifyUploadsExtraRecipients[0] diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 44a8309dd2..79ee760c23 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -48,7 +48,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/notification" "github.com/cs3org/reva/pkg/notification/notificationhelper" "github.com/cs3org/reva/pkg/notification/trigger" @@ -271,7 +271,7 @@ func (h *Handler) NotifyShare(w http.ResponseWriter, r *http.Request) { return } - granter, ok := ctxpkg.ContextGetUser(ctx) + granter, ok := appctx.ContextGetUser(ctx) if !ok { h.Log.Error().Err(err).Msgf("error getting granter data") response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting granter data", err) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go index 7b988ce0e8..ebccf1cd0d 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go @@ -34,7 +34,7 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" ) @@ -91,7 +91,7 @@ func (h *Handler) createUserShare(w http.ResponseWriter, r *http.Request, statIn if shareID, ok := h.createCs3Share(ctx, w, r, c, createShareReq, statInfo); ok { notify, _ := strconv.ParseBool(r.FormValue("notify")) if notify { - granter, ok := ctxpkg.ContextGetUser(ctx) + granter, ok := appctx.ContextGetUser(ctx) if ok { h.SendShareNotification(shareID.OpaqueId, granter, userRes.User, statInfo) } @@ -287,7 +287,7 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filte Filters: filters, Opaque: &types.Opaque{ Map: map[string]*types.OpaqueEntry{ - ctxpkg.ResoucePathCtx: {Decoder: "plain", Value: []byte(ctxPath)}, + appctx.ResoucePathCtx: {Decoder: "plain", Value: []byte(ctxPath)}, }, }, } diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go index 34772315ed..b717ca38e5 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/capabilities/uploads.go @@ -23,7 +23,8 @@ import ( "strings" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/data" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" + "github.com/juliangruber/go-intersect" ) @@ -58,7 +59,7 @@ func (h *Handler) getCapabilitiesForUserAgent(ctx context.Context, userAgent str } func ctxUserBelongsToGroups(ctx context.Context, groups []string) bool { - if user, ok := ctxpkg.ContextGetUser(ctx); ok { + if user, ok := appctx.ContextGetUser(ctx); ok { return len(intersect.Simple(groups, user.Groups)) > 0 } return false diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go b/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go index 05c0a7b71d..12ba0b013d 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/user/user.go @@ -30,7 +30,8 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/config" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" ) @@ -59,7 +60,7 @@ func (h *Handler) GetSelf(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // TODO move user to handler parameter? - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing user in context", fmt.Errorf("missing user in context")) return diff --git a/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go b/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go index 015905571f..b644ce2309 100644 --- a/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go +++ b/internal/http/services/owncloud/ocs/handlers/cloud/users/users.go @@ -31,7 +31,6 @@ import ( "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/go-chi/chi/v5" ) @@ -86,7 +85,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) { user := chi.URLParam(r, "userid") // FIXME use ldap to fetch user info - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing user in context", fmt.Errorf("missing user in context")) return diff --git a/internal/http/services/pingpong/pingpong.go b/internal/http/services/pingpong/pingpong.go new file mode 100644 index 0000000000..b88d933a99 --- /dev/null +++ b/internal/http/services/pingpong/pingpong.go @@ -0,0 +1,140 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package pingpong + +import ( + "context" + "net/http" + "strings" + + "github.com/cs3org/reva/internal/grpc/services/pingpong/proto" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/utils/cfg" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func init() { + global.Register("pingpong", New) +} + +// New returns a new helloworld service. +func New(ctx context.Context, m map[string]interface{}) (global.Service, error) { + var c config + if err := cfg.Decode(m, &c); err != nil { + return nil, err + } + + return &svc{conf: &c}, nil +} + +// Close performs cleanup. +func (s *svc) Close() error { + return nil +} + +type config struct { + Prefix string `mapstructure:"prefix"` + Endpoint string `mapstructure:"endpoint"` +} + +func (c *config) ApplyDefaults() { + if c.Prefix == "" { + c.Prefix = "pingpong" + } + + if c.Endpoint == "" { + c.Endpoint = "localhost:8081" + } +} + +type svc struct { + conf *config +} + +func (s *svc) Prefix() string { + return s.conf.Prefix +} + +func (s *svc) Unprotected() []string { + return []string{"/"} +} + +func (s *svc) Handler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + action := strings.TrimPrefix(r.URL.Path, s.conf.Prefix) + log := appctx.GetLogger(r.Context()) + log.Info().Msgf("action: %s", action) + switch action { + case "/ping": + s.doPing(w, r) + return + case "/pong": + s.doPong(w, r) + return + default: + w.WriteHeader(http.StatusBadRequest) + return + } + }) +} + +func (s *svc) getClient() (proto.PingPongServiceClient, error) { + conn, err := grpc.Dial( + s.conf.Endpoint, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + + if err != nil { + return nil, err + } + + client := proto.NewPingPongServiceClient(conn) + return client, nil +} + +// doPing will call the grpc Pong method. +func (s *svc) doPing(w http.ResponseWriter, r *http.Request) { + log := appctx.GetLogger(r.Context()) + client, err := s.getClient() + if err != nil { + log.Error().Err(err).Msg("error getting grpc client") + w.WriteHeader(http.StatusInternalServerError) + return + } + + pingRes, err := client.Pong(r.Context(), &proto.PongRequest{}) + if err != nil { + log.Error().Err(err).Msg("error doing grpc pong") + w.WriteHeader(http.StatusInternalServerError) + return + } + + log.Info().Msg("pinging from http to grpc") + _, err = w.Write([]byte(pingRes.Info)) + log.Error().Err(err).Msg("error writing res") +} + +// doPong will be (http) called from grpc Pong. +func (s *svc) doPong(w http.ResponseWriter, r *http.Request) { + log := appctx.GetLogger(r.Context()) + _, err := w.Write([]byte("pong")) + log.Error().Err(err).Msg("error writing res") +} diff --git a/internal/http/services/prometheus/prometheus.go b/internal/http/services/prometheus/prometheus.go index b458bffbd4..35b235eaec 100644 --- a/internal/http/services/prometheus/prometheus.go +++ b/internal/http/services/prometheus/prometheus.go @@ -22,11 +22,11 @@ import ( "context" "net/http" - "contrib.go.opencensus.io/exporter/prometheus" + "github.com/cs3org/reva/pkg/prom/registry" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/utils/cfg" - "github.com/pkg/errors" - "go.opencensus.io/stats/view" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" ) func init() { @@ -40,15 +40,28 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) return nil, err } - pe, err := prometheus.NewExporter(prometheus.Options{ - Namespace: "revad", - }) - if err != nil { - return nil, errors.Wrap(err, "prometheus: error creating exporter") + // instantiate and register all collectors + collectors := []prometheus.Collector{} + for _, f := range registry.NewFuncs { + cols, err := f(ctx, m) + if err != nil { + return nil, err + } + collectors = append(collectors, cols...) } - view.RegisterExporter(pe) - return &svc{prefix: c.Prefix, h: pe}, nil + // custom registry to avoid global prometheus registry that can be + // modified at global package level + reg := prometheus.NewRegistry() + reg.MustRegister(collectors...) + + handler := promhttp.HandlerFor( + reg, + promhttp.HandlerOpts{ + Registry: reg, + EnableOpenMetrics: true, + }) + return &svc{prefix: c.Prefix, h: handler}, nil } type config struct { diff --git a/internal/http/services/reverseproxy/reverseproxy.go b/internal/http/services/reverseproxy/reverseproxy.go index ae1c9300b1..96b513c659 100644 --- a/internal/http/services/reverseproxy/reverseproxy.go +++ b/internal/http/services/reverseproxy/reverseproxy.go @@ -26,7 +26,7 @@ import ( "net/url" "os" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/go-chi/chi/v5" @@ -85,8 +85,8 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error) proxy := httputil.NewSingleHostReverseProxy(remote) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.Host = remote.Host - if token, ok := ctxpkg.ContextGetToken(r.Context()); ok { - r.Header.Set(ctxpkg.TokenHeader, token) + if token, ok := appctx.ContextGetToken(r.Context()); ok { + r.Header.Set(appctx.TokenHeader, token) } proxy.ServeHTTP(w, r) }) diff --git a/internal/http/services/sciencemesh/token.go b/internal/http/services/sciencemesh/token.go index 4c519c038d..630c240203 100644 --- a/internal/http/services/sciencemesh/token.go +++ b/internal/http/services/sciencemesh/token.go @@ -32,7 +32,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/internal/http/services/reqres" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/smtpclient" "github.com/cs3org/reva/pkg/utils/list" @@ -94,7 +94,7 @@ func (h *tokenHandler) Generate(w http.ResponseWriter, r *http.Request) { return } - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) recipient := query.Get("recipient") if recipient != "" && h.smtpCredentials != nil { templObj := &emailParams{ diff --git a/pkg/app/provider/wopi/wopi.go b/pkg/app/provider/wopi/wopi.go index fbd092fcbf..6d146383e2 100644 --- a/pkg/app/provider/wopi/wopi.go +++ b/pkg/app/provider/wopi/wopi.go @@ -21,6 +21,7 @@ package wopi import ( "bytes" "context" + "crypto/tls" "encoding/json" "fmt" "io" @@ -44,11 +45,10 @@ import ( "github.com/cs3org/reva/pkg/app/provider/registry" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/mime" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" "github.com/cs3org/reva/pkg/utils/cfg" @@ -102,7 +102,7 @@ func (c *config) ApplyDefaults() { type wopiProvider struct { conf *config - wopiClient *http.Client + wopiClient *httpclient.Client appURLs map[string]map[string]string // map[viewMode]map[extension]appURL } @@ -119,14 +119,18 @@ func New(ctx context.Context, m map[string]interface{}) (app.Provider, error) { return nil, err } - wopiClient := rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(10*int64(time.Second))), - rhttp.Insecure(c.InsecureConnections), - ) - wopiClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureConnections}} + + cr := func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } + wopiClient := httpclient.New( + httpclient.Timeout(time.Duration(10*int64(time.Second))), + httpclient.RoundTripper(tr), + httpclient.CheckRedirect(cr), + ) + return &wopiProvider{ conf: &c, wopiClient: wopiClient, @@ -144,7 +148,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc } wopiurl.Path = path.Join(wopiurl.Path, "/wopi/iop/openinapp") - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, wopiurl.String(), nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, wopiurl.String(), nil) if err != nil { return nil, err } @@ -156,7 +160,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc q.Add("appname", p.conf.AppName) var ut = invalid - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { // we must have been authenticated return nil, errors.New("wopi: ContextGetUser failed") @@ -168,7 +172,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc q.Add("userid", u.Id.OpaqueId+"@"+u.Id.Idp) } - scopes, ok := ctxpkg.ContextGetScopes(ctx) + scopes, ok := appctx.ContextGetScopes(ctx) if !ok { // we must find at least one scope (as owner or sharee) return nil, errors.New("wopi: ContextGetScopes failed") @@ -365,9 +369,11 @@ func (p *wopiProvider) GetAppProviderInfo(ctx context.Context) (*appregistry.Pro func getAppURLs(c *config) (map[string]map[string]string, error) { // Initialize WOPI URLs by discovery - httpcl := rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(5*int64(time.Second))), - rhttp.Insecure(c.InsecureConnections), + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureConnections}} + + httpcl := httpclient.New( + httpclient.Timeout(time.Duration(5*int64(time.Second))), + httpclient.RoundTripper(tr), ) appurl, err := url.Parse(c.AppIntURL) @@ -435,7 +441,7 @@ func getAppURLs(c *config) (map[string]map[string]string, error) { } func (p *wopiProvider) getAccessTokenTTL(ctx context.Context) (string, error) { - tkn := ctxpkg.ContextMustGetToken(ctx) + tkn := appctx.ContextMustGetToken(ctx) token, err := jwt.ParseWithClaims(tkn, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(p.conf.JWTSecret), nil }) diff --git a/pkg/appauth/manager/json/json.go b/pkg/appauth/manager/json/json.go index 1ff1a667f9..0ec6f48e95 100644 --- a/pkg/appauth/manager/json/json.go +++ b/pkg/appauth/manager/json/json.go @@ -32,7 +32,8 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appauth" "github.com/cs3org/reva/pkg/appauth/manager/registry" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" @@ -127,7 +128,7 @@ func (mgr *jsonManager) GenerateAppPassword(ctx context.Context, scope map[strin if err != nil { return nil, errors.Wrap(err, "error creating new token") } - userID := ctxpkg.ContextMustGetUser(ctx).GetId() + userID := appctx.ContextMustGetUser(ctx).GetId() ctime := now() password := string(tokenHashed) @@ -161,7 +162,7 @@ func (mgr *jsonManager) GenerateAppPassword(ctx context.Context, scope map[strin } func (mgr *jsonManager) ListAppPasswords(ctx context.Context) ([]*apppb.AppPassword, error) { - userID := ctxpkg.ContextMustGetUser(ctx).GetId() + userID := appctx.ContextMustGetUser(ctx).GetId() mgr.Lock() defer mgr.Unlock() appPasswords := []*apppb.AppPassword{} @@ -172,7 +173,7 @@ func (mgr *jsonManager) ListAppPasswords(ctx context.Context) ([]*apppb.AppPassw } func (mgr *jsonManager) InvalidateAppPassword(ctx context.Context, password string) error { - userID := ctxpkg.ContextMustGetUser(ctx).GetId() + userID := appctx.ContextMustGetUser(ctx).GetId() mgr.Lock() defer mgr.Unlock() diff --git a/pkg/appauth/manager/json/json_test.go b/pkg/appauth/manager/json/json_test.go index e20d1cd585..d2050305d0 100644 --- a/pkg/appauth/manager/json/json_test.go +++ b/pkg/appauth/manager/json/json_test.go @@ -32,7 +32,8 @@ import ( apppb "github.com/cs3org/go-cs3apis/cs3/auth/applications/v1beta1" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" + "github.com/gdexlab/go-render/render" "github.com/sethvargo/go-password/password" "golang.org/x/crypto/bcrypt" @@ -140,7 +141,7 @@ func TestNewManager(t *testing.T) { func TestGenerateAppPassword(t *testing.T) { userTest := &userpb.User{Id: &userpb.UserId{Idp: "0"}, Username: "Test User"} - ctx := ctxpkg.ContextSetUser(context.Background(), userTest) + ctx := appctx.ContextSetUser(context.Background(), userTest) tempDir := createTempDir(t, "jsonappauth_test") defer os.RemoveAll(tempDir) @@ -290,7 +291,7 @@ func TestGenerateAppPassword(t *testing.T) { func TestListAppPasswords(t *testing.T) { user0Test := &userpb.User{Id: &userpb.UserId{Idp: "0"}} user1Test := &userpb.User{Id: &userpb.UserId{Idp: "1"}} - ctx := ctxpkg.ContextSetUser(context.Background(), user0Test) + ctx := appctx.ContextSetUser(context.Background(), user0Test) tempDir := createTempDir(t, "jsonappauth_test") defer os.RemoveAll(tempDir) @@ -415,7 +416,7 @@ func TestListAppPasswords(t *testing.T) { func TestInvalidateAppPassword(t *testing.T) { userTest := &userpb.User{Id: &userpb.UserId{Idp: "0"}} - ctx := ctxpkg.ContextSetUser(context.Background(), userTest) + ctx := appctx.ContextSetUser(context.Background(), userTest) tempDir := createTempDir(t, "jsonappauth_test") defer os.RemoveAll(tempDir) @@ -539,7 +540,7 @@ func TestInvalidateAppPassword(t *testing.T) { func TestGetAppPassword(t *testing.T) { userTest := &userpb.User{Id: &userpb.UserId{Idp: "0"}} - ctx := ctxpkg.ContextSetUser(context.Background(), userTest) + ctx := appctx.ContextSetUser(context.Background(), userTest) tempDir := createTempDir(t, "jsonappauth_test") defer os.RemoveAll(tempDir) diff --git a/pkg/ctx/agentctx.go b/pkg/appctx/agentctx.go similarity index 99% rename from pkg/ctx/agentctx.go rename to pkg/appctx/agentctx.go index 82e6376587..c349136319 100644 --- a/pkg/ctx/agentctx.go +++ b/pkg/appctx/agentctx.go @@ -16,7 +16,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package ctx +package appctx import ( "context" diff --git a/pkg/ctx/agentctx_test.go b/pkg/appctx/agentctx_test.go similarity index 99% rename from pkg/ctx/agentctx_test.go rename to pkg/appctx/agentctx_test.go index ad4e0c165f..e99112b4b1 100644 --- a/pkg/ctx/agentctx_test.go +++ b/pkg/appctx/agentctx_test.go @@ -16,7 +16,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package ctx +package appctx import ( "context" diff --git a/pkg/appctx/appctx.go b/pkg/appctx/logger.go similarity index 90% rename from pkg/appctx/appctx.go rename to pkg/appctx/logger.go index 3aad813443..8624725ea5 100644 --- a/pkg/appctx/appctx.go +++ b/pkg/appctx/logger.go @@ -24,9 +24,6 @@ import ( "github.com/rs/zerolog" ) -// DeletingSharedResource flags to a storage a shared resource is being deleted not by the owner. -var DeletingSharedResource struct{} - // WithLogger returns a context with an associated logger. func WithLogger(ctx context.Context, l *zerolog.Logger) context.Context { return l.WithContext(ctx) diff --git a/pkg/ctx/pathctx.go b/pkg/appctx/pathctx.go similarity index 97% rename from pkg/ctx/pathctx.go rename to pkg/appctx/pathctx.go index 944be416c6..4bcf1e7354 100644 --- a/pkg/ctx/pathctx.go +++ b/pkg/appctx/pathctx.go @@ -16,11 +16,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package ctx +package appctx -import ( - "context" -) +import "context" // ResoucePathCtx is the key used in the opaque id for passing the resource path. const ResoucePathCtx = "resource_path" diff --git a/pkg/ctx/tokenctx.go b/pkg/appctx/tokenctx.go similarity index 99% rename from pkg/ctx/tokenctx.go rename to pkg/appctx/tokenctx.go index e1b431bd12..b84866645e 100644 --- a/pkg/ctx/tokenctx.go +++ b/pkg/appctx/tokenctx.go @@ -16,7 +16,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package ctx +package appctx import ( "context" diff --git a/pkg/ctx/userctx.go b/pkg/appctx/userctx.go similarity index 99% rename from pkg/ctx/userctx.go rename to pkg/appctx/userctx.go index 5551987ae5..f9914e1f22 100644 --- a/pkg/ctx/userctx.go +++ b/pkg/appctx/userctx.go @@ -16,7 +16,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package ctx +package appctx import ( "context" diff --git a/pkg/auth/manager/nextcloud/nextcloud_test.go b/pkg/auth/manager/nextcloud/nextcloud_test.go index b1998d4106..a09879edba 100644 --- a/pkg/auth/manager/nextcloud/nextcloud_test.go +++ b/pkg/auth/manager/nextcloud/nextcloud_test.go @@ -26,9 +26,10 @@ import ( authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/manager/nextcloud" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -99,9 +100,9 @@ var _ = Describe("Nextcloud", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) }) AfterEach(func() { diff --git a/pkg/auth/manager/oidc/oidc.go b/pkg/auth/manager/oidc/oidc.go index 5b0afeff0b..09baa31faa 100644 --- a/pkg/auth/manager/oidc/oidc.go +++ b/pkg/auth/manager/oidc/oidc.go @@ -22,8 +22,10 @@ package oidc import ( "context" + "crypto/tls" "encoding/json" "fmt" + "net/http" "os" "strings" "time" @@ -37,9 +39,9 @@ import ( "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/auth/scope" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/golang-jwt/jwt" @@ -294,14 +296,16 @@ func (am *mgr) Authenticate(ctx context.Context, _, clientSecret string) (*user. } func (am *mgr) getOAuthCtx(ctx context.Context) context.Context { + tr := &http.Transport{ + DisableKeepAlives: true, + TLSClientConfig: &tls.Config{InsecureSkipVerify: am.c.Insecure}, + } + // Sometimes for testing we need to skip the TLS check, that's why we need a // custom HTTP client. - customHTTPClient := rhttp.GetHTTPClient( - rhttp.Context(ctx), - rhttp.Timeout(time.Second*10), - rhttp.Insecure(am.c.Insecure), - // Fixes connection fd leak which might be caused by provider-caching - rhttp.DisableKeepAlive(true), + customHTTPClient := httpclient.New( + httpclient.Timeout(time.Second*10), + httpclient.RoundTripper(tr), ) ctx = context.WithValue(ctx, oauth2.HTTPClient, customHTTPClient) return ctx diff --git a/pkg/cbox/utils/tokenmanagement.go b/pkg/cbox/utils/tokenmanagement.go index 6eea766d92..0dbc704113 100644 --- a/pkg/cbox/utils/tokenmanagement.go +++ b/pkg/cbox/utils/tokenmanagement.go @@ -20,6 +20,7 @@ package utils import ( "context" + "crypto/tls" "encoding/json" "errors" "io" @@ -29,7 +30,7 @@ import ( "sync" "time" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/mitchellh/mapstructure" ) @@ -37,7 +38,7 @@ import ( type APITokenManager struct { oidcToken OIDCToken conf *config - client *http.Client + client *httpclient.Client } // OIDCToken stores the OIDC token used to authenticate requests to the REST API service. @@ -63,11 +64,13 @@ func InitAPITokenManager(conf map[string]interface{}) (*APITokenManager, error) return nil, err } + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}} + return &APITokenManager{ conf: c, - client: rhttp.GetHTTPClient( - rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), - rhttp.Insecure(c.Insecure), + client: httpclient.New( + httpclient.Timeout(time.Duration(c.Timeout*int64(time.Second))), + httpclient.RoundTripper(tr), )}, nil } diff --git a/pkg/datatx/manager/rclone/rclone.go b/pkg/datatx/manager/rclone/rclone.go index ba97088096..e99c8ea70f 100644 --- a/pkg/datatx/manager/rclone/rclone.go +++ b/pkg/datatx/manager/rclone/rclone.go @@ -21,6 +21,7 @@ package rclone import ( "bytes" "context" + "crypto/tls" "encoding/json" "fmt" "net/http" @@ -37,7 +38,7 @@ import ( repoRegistry "github.com/cs3org/reva/pkg/datatx/manager/rclone/repository/registry" registry "github.com/cs3org/reva/pkg/datatx/manager/registry" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/google/uuid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" @@ -72,7 +73,7 @@ type config struct { type rclone struct { config *config - client *http.Client + client *httpclient.Client storage repository.Repository } @@ -109,7 +110,8 @@ func New(ctx context.Context, m map[string]interface{}) (txdriver.Manager, error } c.init(m) - client := rhttp.GetHTTPClient(rhttp.Insecure(c.Insecure)) + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}} + client := httpclient.New(httpclient.RoundTripper(tr)) storage, err := getStorageManager(ctx, c) if err != nil { diff --git a/pkg/eosclient/eosbinary/eosbinary.go b/pkg/eosclient/eosbinary/eosbinary.go index 48deb910a1..d2b056c16b 100644 --- a/pkg/eosclient/eosbinary/eosbinary.go +++ b/pkg/eosclient/eosbinary/eosbinary.go @@ -33,7 +33,7 @@ import ( "time" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/eosclient" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage/utils/acl" @@ -516,7 +516,7 @@ func (c *Client) setEOSAttr(ctx context.Context, auth eosclient.Authorization, a func (c *Client) handleFavAttr(ctx context.Context, auth eosclient.Authorization, attr *eosclient.Attribute, recursive bool, path string, info *eosclient.FileInfo, set bool) error { var err error - u := ctxpkg.ContextMustGetUser(ctx) + u := appctx.ContextMustGetUser(ctx) if info == nil { info, err = c.getRawFileInfoByPath(ctx, auth, path) if err != nil { @@ -1272,7 +1272,7 @@ func (c *Client) mapToFileInfo(ctx context.Context, kv, attrs map[string]string, func parseAndSetFavoriteAttr(ctx context.Context, attrs map[string]string) { // Read and correctly set the favorite attr - if user, ok := ctxpkg.ContextGetUser(ctx); ok { + if user, ok := appctx.ContextGetUser(ctx); ok { if favAttrStr, ok := attrs[favoritesKey]; ok { favUsers, err := acl.Parse(favAttrStr, acl.ShortTextForm) if err != nil { diff --git a/pkg/httpclient/httpclient.go b/pkg/httpclient/httpclient.go new file mode 100644 index 0000000000..2bef4051e2 --- /dev/null +++ b/pkg/httpclient/httpclient.go @@ -0,0 +1,135 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package httpclient + +import ( + "errors" + "net/http" + "time" + + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/trace" +) + +// TODO(labkode): harden it. +// https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779 +func New(opts ...Option) *Client { + options := newOptions(opts...) + + var tr http.RoundTripper + if options.RoundTripper == nil { + tr = &injectTransport{rt: http.DefaultTransport} + } else { + tr = &injectTransport{rt: options.RoundTripper} + } + + httpClient := &http.Client{ + Timeout: options.Timeout, + Transport: tr, + } + + return &Client{c: httpClient} +} + +// Option defines a single option function. +type Option func(o *Options) + +// Options defines the available options for this package. +type Options struct { + Jar http.CookieJar + CheckRedirect func(req *http.Request, via []*http.Request) error + Timeout time.Duration + RoundTripper http.RoundTripper +} + +// newOptions initializes the available default options. +func newOptions(opts ...Option) Options { + opt := Options{} + + for _, o := range opts { + o(&opt) + } + + return opt +} + +// Timeout provides a function to set the timeout option. +func Timeout(t time.Duration) Option { + return func(o *Options) { + o.Timeout = t + } +} + +// RoundTripper provides a function to set a custom RoundTripper. +func RoundTripper(rt http.RoundTripper) Option { + return func(o *Options) { + o.RoundTripper = rt + } +} + +// CheckRedirect provides a function to set a custom CheckRedirect. +func CheckRedirect(cr func(req *http.Request, via []*http.Request) error) Option { + return func(o *Options) { + o.CheckRedirect = cr + } +} + +// Jar provides a function to set a custom CookieJar. +func Jar(j http.CookieJar) Option { + return func(o *Options) { + o.Jar = j + } +} + +// Client wraps a http.Client but only exposes the Do method +// to force consumers to always create a request with http.NewRequestWithContext(). +type Client struct { + c *http.Client +} + +func (c *Client) Do(r *http.Request) (*http.Response, error) { + // bail out early if context is not set + if r.Context() == nil { + return nil, errors.New("error: request must have a context") + } + return c.c.Do(r) +} + +func (c *Client) GetNativeHTTP() *http.Client { + return c.c +} + +type injectTransport struct { + rt http.RoundTripper +} + +func (t injectTransport) RoundTrip(r *http.Request) (*http.Response, error) { + ctx := r.Context() + + traceID := trace.Get(ctx) + + r.Header.Set("X-Trace-ID", traceID) + + tkn, ok := appctx.ContextGetToken(ctx) + if ok { + r.Header.Set(appctx.TokenHeader, tkn) + } + + return t.rt.RoundTrip(r) +} diff --git a/pkg/ocm/client/client.go b/pkg/ocm/client/client.go index 651129bf5b..07c4e1265e 100644 --- a/pkg/ocm/client/client.go +++ b/pkg/ocm/client/client.go @@ -21,6 +21,7 @@ package client import ( "bytes" "context" + "crypto/tls" "encoding/json" "io" "net/http" @@ -30,7 +31,6 @@ import ( "github.com/cs3org/reva/internal/http/services/ocmd" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" "github.com/pkg/errors" ) @@ -67,11 +67,11 @@ type Config struct { // New returns a new OCMClient. func New(c *Config) *OCMClient { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}, + } return &OCMClient{ - client: rhttp.GetHTTPClient( - rhttp.Timeout(c.Timeout), - rhttp.Insecure(c.Insecure), - ), + client: &http.Client{Transport: tr}, } } diff --git a/pkg/ocm/provider/authorizer/mentix/mentix.go b/pkg/ocm/provider/authorizer/mentix/mentix.go index b89ee87482..e93edf0ac0 100644 --- a/pkg/ocm/provider/authorizer/mentix/mentix.go +++ b/pkg/ocm/provider/authorizer/mentix/mentix.go @@ -20,6 +20,7 @@ package mentix import ( "context" + "crypto/tls" "encoding/json" "fmt" "net" @@ -31,9 +32,9 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/ocm/provider" "github.com/cs3org/reva/pkg/ocm/provider/authorizer/registry" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/utils/cfg" "github.com/pkg/errors" ) @@ -45,7 +46,7 @@ func init() { // Client is a Mentix API client. type Client struct { BaseURL string - HTTPClient *http.Client + HTTPClient *httpclient.Client } // New returns a new authorizer object. @@ -55,12 +56,13 @@ func New(ctx context.Context, m map[string]interface{}) (provider.Authorizer, er return nil, err } + tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Insecure}} + client := &Client{ BaseURL: c.URL, - HTTPClient: rhttp.GetHTTPClient( - rhttp.Context(context.Background()), - rhttp.Timeout(time.Duration(c.Timeout*int64(time.Second))), - rhttp.Insecure(c.Insecure), + HTTPClient: httpclient.New( + httpclient.Timeout(time.Duration(c.Timeout*int64(time.Second))), + httpclient.RoundTripper(tr), ), } diff --git a/pkg/ocm/share/repository/nextcloud/nextcloud_test.go b/pkg/ocm/share/repository/nextcloud/nextcloud_test.go index 72533dbe2f..b04d1067c6 100644 --- a/pkg/ocm/share/repository/nextcloud/nextcloud_test.go +++ b/pkg/ocm/share/repository/nextcloud/nextcloud_test.go @@ -27,8 +27,9 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" masked_share "github.com/cs3org/reva/pkg/ocm/share" "github.com/cs3org/reva/pkg/ocm/share/repository/nextcloud" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" @@ -102,9 +103,9 @@ var _ = Describe("Nextcloud", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) }) AfterEach(func() { diff --git a/pkg/ocm/share/sender/sender.go b/pkg/ocm/share/sender/sender.go index 7cdb6222d5..4cd8e510b8 100644 --- a/pkg/ocm/share/sender/sender.go +++ b/pkg/ocm/share/sender/sender.go @@ -31,7 +31,7 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/pkg/errors" ) @@ -73,8 +73,8 @@ func Send(ctx context.Context, requestBodyMap map[string]interface{}, pi *ocmpro return errors.Wrap(err, "sender: error framing post request") } req.Header.Set("Content-Type", "application/json") - client := rhttp.GetHTTPClient( - rhttp.Timeout(5 * time.Second), + client := httpclient.New( + httpclient.Timeout(5 * time.Second), ) resp, err := client.Do(req) diff --git a/pkg/ocm/storage/outcoming/ocm.go b/pkg/ocm/storage/outcoming/ocm.go index dbc9573fc3..dda3ae1e54 100644 --- a/pkg/ocm/storage/outcoming/ocm.go +++ b/pkg/ocm/storage/outcoming/ocm.go @@ -34,10 +34,11 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage" @@ -248,9 +249,9 @@ func (d *driver) opFromUser(ctx context.Context, userID *userv1beta1.UserId, f f } ownerCtx := context.TODO() - ownerCtx = ctxpkg.ContextSetToken(ownerCtx, authRes.Token) - ownerCtx = ctxpkg.ContextSetUser(ownerCtx, authRes.User) - ownerCtx = metadata.AppendToOutgoingContext(ownerCtx, ctxpkg.TokenHeader, authRes.Token) + ownerCtx = appctx.ContextSetToken(ownerCtx, authRes.Token) + ownerCtx = appctx.ContextSetUser(ownerCtx, authRes.User) + ownerCtx = metadata.AppendToOutgoingContext(ownerCtx, appctx.TokenHeader, authRes.Token) return f(ownerCtx) } @@ -410,14 +411,14 @@ func (d *driver) Upload(ctx context.Context, ref *provider.Reference, content io return errtypes.InternalError("simple upload not supported") } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, endpoint, content) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, endpoint, content) if err != nil { return errors.Wrap(err, "error creating new request") } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) + httpRes, err := httpclient.New().Do(httpReq) if err != nil { return errors.Wrap(err, "error doing put request") } @@ -465,13 +466,13 @@ func (d *driver) Download(ctx context.Context, ref *provider.Reference) (io.Read return errtypes.InternalError("simple download not supported") } - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, endpoint, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) if err != nil { return err } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) //nolint:golint,bodyclose + httpRes, err := httpclient.New().Do(httpReq) //nolint:golint,bodyclose if err != nil { return err } diff --git a/pkg/preferences/memory/memory.go b/pkg/preferences/memory/memory.go index 10ff617fa3..90333ea318 100644 --- a/pkg/preferences/memory/memory.go +++ b/pkg/preferences/memory/memory.go @@ -22,7 +22,7 @@ import ( "context" "sync" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/preferences" "github.com/cs3org/reva/pkg/preferences/registry" @@ -43,7 +43,7 @@ func New(ctx context.Context, m map[string]interface{}) (preferences.Manager, er } func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { return errtypes.UserRequired("preferences: error getting user from ctx") } @@ -61,7 +61,7 @@ func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { } func (m *mgr) GetKey(ctx context.Context, key, namespace string) (string, error) { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { return "", errtypes.UserRequired("preferences: error getting user from ctx") } diff --git a/pkg/preferences/sql/sql.go b/pkg/preferences/sql/sql.go index 8e0b2afbd5..57f34878c4 100644 --- a/pkg/preferences/sql/sql.go +++ b/pkg/preferences/sql/sql.go @@ -23,7 +23,7 @@ import ( "database/sql" "fmt" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/preferences" "github.com/cs3org/reva/pkg/preferences/registry" @@ -66,7 +66,7 @@ func New(ctx context.Context, m map[string]interface{}) (preferences.Manager, er } func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { - user, ok := ctxpkg.ContextGetUser(ctx) + user, ok := appctx.ContextGetUser(ctx) if !ok { return errtypes.UserRequired("preferences: error getting user from ctx") } @@ -84,7 +84,7 @@ func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { } func (m *mgr) GetKey(ctx context.Context, key, namespace string) (string, error) { - user, ok := ctxpkg.ContextGetUser(ctx) + user, ok := appctx.ContextGetUser(ctx) if !ok { return "", errtypes.UserRequired("preferences: error getting user from ctx") } diff --git a/pkg/prom/base/base.go b/pkg/prom/base/base.go new file mode 100644 index 0000000000..eaae139c8d --- /dev/null +++ b/pkg/prom/base/base.go @@ -0,0 +1,39 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package base + +import ( + "context" + + "github.com/cs3org/reva/pkg/prom/registry" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/collectors" +) + +func init() { + registry.Register("base", New) +} + +// New returns a prometheus collector. +func New(_ context.Context, m map[string]interface{}) ([]prometheus.Collector, error) { + return []prometheus.Collector{ + collectors.NewBuildInfoCollector(), + collectors.NewGoCollector(), + collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})}, nil +} diff --git a/pkg/prom/loader/loader.go b/pkg/prom/loader/loader.go new file mode 100644 index 0000000000..d9406544a5 --- /dev/null +++ b/pkg/prom/loader/loader.go @@ -0,0 +1,27 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package loader + +import ( + // Load collectors. + _ "github.com/cs3org/reva/internal/grpc/interceptors/metrics" + _ "github.com/cs3org/reva/internal/http/interceptors/metrics" + _ "github.com/cs3org/reva/pkg/prom/base" + // Add your own here. +) diff --git a/pkg/prom/registry/registry.go b/pkg/prom/registry/registry.go new file mode 100644 index 0000000000..f41fd73813 --- /dev/null +++ b/pkg/prom/registry/registry.go @@ -0,0 +1,38 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package registry + +import ( + "context" + + "github.com/prometheus/client_golang/prometheus" +) + +// NewFunc is the function that custom prometheus collectors implement +// should register at init time. +type NewFunc func(context.Context, map[string]interface{}) ([]prometheus.Collector, error) + +// NewFuncs is a map containing all the registered collectors. +var NewFuncs = map[string]NewFunc{} + +// Register registers a new prometheus collector new function. +// Not safe for concurrent use. Safe for use from package init. +func Register(name string, f NewFunc) { + NewFuncs[name] = f +} diff --git a/pkg/rgrpc/status/status.go b/pkg/rgrpc/status/status.go index 27c285bcbc..64b7b4b718 100644 --- a/pkg/rgrpc/status/status.go +++ b/pkg/rgrpc/status/status.go @@ -28,7 +28,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "go.opentelemetry.io/otel/trace" + "github.com/cs3org/reva/pkg/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -216,6 +216,5 @@ func NewErrorFromCode(code rpc.Code, pkgname string) error { // internal function to attach the trace to a context. func getTrace(ctx context.Context) string { - span := trace.SpanFromContext(ctx) - return span.SpanContext().TraceID().String() + return trace.Get(ctx) } diff --git a/pkg/rgrpc/todo/pool/pool.go b/pkg/rgrpc/todo/pool/pool.go index 38092d44b6..e8f96129b4 100644 --- a/pkg/rgrpc/todo/pool/pool.go +++ b/pkg/rgrpc/todo/pool/pool.go @@ -40,8 +40,6 @@ import ( storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" storageregistry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" datatx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" - rtrace "github.com/cs3org/reva/pkg/trace" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) @@ -83,7 +81,6 @@ var ( ) // NewConn creates a new connection to a grpc server -// with open census tracing support. // TODO(labkode): make grpc tls configurable. func NewConn(options Options) (*grpc.ClientConn, error) { conn, err := grpc.Dial( @@ -92,24 +89,6 @@ func NewConn(options Options) (*grpc.ClientConn, error) { grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(options.MaxCallRecvMsgSize), ), - grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor( - otelgrpc.WithTracerProvider( - rtrace.Provider, - ), - otelgrpc.WithPropagators( - rtrace.Propagator, - ), - )), - grpc.WithUnaryInterceptor( - otelgrpc.UnaryClientInterceptor( - otelgrpc.WithTracerProvider( - rtrace.Provider, - ), - otelgrpc.WithPropagators( - rtrace.Propagator, - ), - ), - ), ) if err != nil { return nil, err diff --git a/pkg/rhttp/client.go b/pkg/rhttp/client.go deleted file mode 100644 index 2fc6662c67..0000000000 --- a/pkg/rhttp/client.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018-2023 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package rhttp - -import ( - "context" - "crypto/tls" - "io" - "net/http" - - ctxpkg "github.com/cs3org/reva/pkg/ctx" - "github.com/pkg/errors" - "go.opencensus.io/plugin/ochttp" -) - -// GetHTTPClient returns an http client with open census tracing support. -// TODO(labkode): harden it. -// https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779 -func GetHTTPClient(opts ...Option) *http.Client { - options := newOptions(opts...) - - tr := http.DefaultTransport.(*http.Transport).Clone() - tr.DisableKeepAlives = options.DisableKeepAlive - tr.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: options.Insecure, - } - - httpClient := &http.Client{ - Timeout: options.Timeout, - Transport: &ochttp.Transport{ - Base: tr, - }, - } - - return httpClient -} - -// NewRequest creates an HTTP request that sets the token if it is passed in ctx. -func NewRequest(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) { - httpReq, err := http.NewRequest(method, url, body) - if err != nil { - return nil, errors.Wrap(err, "utils: error creating request") - } - - // TODO(labkode): make header / auth configurable - tkn, ok := ctxpkg.ContextGetToken(ctx) - if ok { - httpReq.Header.Set(ctxpkg.TokenHeader, tkn) - } - - httpReq = httpReq.WithContext(ctx) - return httpReq, nil -} diff --git a/pkg/rhttp/option.go b/pkg/rhttp/option.go deleted file mode 100644 index c5d41ff8b9..0000000000 --- a/pkg/rhttp/option.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2018-2023 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package rhttp - -import ( - "context" - "time" -) - -// Option defines a single option function. -type Option func(o *Options) - -// Options defines the available options for this package. -type Options struct { - Context context.Context - Timeout time.Duration - Insecure bool - DisableKeepAlive bool -} - -// newOptions initializes the available default options. -func newOptions(opts ...Option) Options { - opt := Options{} - - for _, o := range opts { - o(&opt) - } - - return opt -} - -// Context provides a function to set the context option. -func Context(val context.Context) Option { - return func(o *Options) { - o.Context = val - } -} - -// Insecure provides a function to set the insecure option. -func Insecure(insecure bool) Option { - return func(o *Options) { - o.Insecure = insecure - } -} - -// Timeout provides a function to set the timeout option. -func Timeout(t time.Duration) Option { - return func(o *Options) { - o.Timeout = t - } -} - -// DisableKeepAlive provides a function to set the disablee keep alive option. -func DisableKeepAlive(disable bool) Option { - return func(o *Options) { - o.DisableKeepAlive = disable - } -} diff --git a/pkg/rhttp/rhttp.go b/pkg/rhttp/rhttp.go index 37fd52dd51..b516814a6e 100644 --- a/pkg/rhttp/rhttp.go +++ b/pkg/rhttp/rhttp.go @@ -30,10 +30,8 @@ import ( "github.com/cs3org/reva/cmd/revad/pkg/config" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/global" - rtrace "github.com/cs3org/reva/pkg/trace" "github.com/pkg/errors" "github.com/rs/zerolog" - "go.opentelemetry.io/otel/propagation" ) type Config func(*Server) @@ -181,8 +179,7 @@ func (s *Server) GracefulStop() error { func (s *Server) registerServices() { for name, svc := range s.Services { // instrument services with opencensus tracing. - h := traceHandler(name, svc.Handler()) - s.handlers[svc.Prefix()] = h + s.handlers[svc.Prefix()] = svc.Handler() s.svcs[svc.Prefix()] = svc s.unprotected = append(s.unprotected, getUnprotected(svc.Prefix(), svc.Unprotected())...) s.log.Info().Msgf("http service enabled: %s@/%s", name, svc.Prefix()) @@ -283,14 +280,14 @@ func (s *Server) getHandler() (http.Handler, error) { return handler, nil } -func traceHandler(name string, h http.Handler) http.Handler { +// prometheusMiddleware implements mux.MiddlewareFunc. +/* +func prometheusHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := rtrace.Propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header)) - t := rtrace.Provider.Tracer("reva") - ctx, span := t.Start(ctx, name) - defer span.End() - - rtrace.Propagator.Inject(ctx, propagation.HeaderCarrier(r.Header)) - h.ServeHTTP(w, r.WithContext(ctx)) + path := r.URL.Path + timer := prometheus.NewTimer(httpDuration.WithLabelValues(path)) + next.ServeHTTP(w, r) + timer.ObserveDuration() }) } +*/ diff --git a/pkg/sdk/common/net/net.go b/pkg/sdk/common/net/net.go index 2e73cf2d3d..38fab412b1 100644 --- a/pkg/sdk/common/net/net.go +++ b/pkg/sdk/common/net/net.go @@ -20,7 +20,7 @@ package net import ( "github.com/cs3org/reva/internal/http/services/datagateway" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" ) type ctxKey int @@ -29,7 +29,7 @@ const ( // AccessTokenIndex specifies the index of the Reva access token in a context. AccessTokenIndex ctxKey = iota // AccessTokenName specifies the name of the Reva access token used during requests. - AccessTokenName = ctxpkg.TokenHeader + AccessTokenName = appctx.TokenHeader // TransportTokenName specifies the name of the Reva transport token used during data transfers. TransportTokenName = datagateway.TokenTransportHeader ) diff --git a/pkg/share/cache/warmup/cbox/cbox.go b/pkg/share/cache/warmup/cbox/cbox.go index 0ff270565e..b1876cfa22 100644 --- a/pkg/share/cache/warmup/cbox/cbox.go +++ b/pkg/share/cache/warmup/cbox/cbox.go @@ -26,8 +26,9 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/share/cache" "github.com/cs3org/reva/pkg/share/cache/warmup/registry" @@ -117,7 +118,7 @@ func (m *manager) GetResourceInfos() ([]*provider.ResourceInfo, error) { if err != nil { return nil, err } - ctx := metadata.AppendToOutgoingContext(context.Background(), ctxpkg.TokenHeader, tkn) + ctx := metadata.AppendToOutgoingContext(context.Background(), appctx.TokenHeader, tkn) client, err := pool.GetGatewayServiceClient(pool.Endpoint(m.conf.GatewaySvc)) if err != nil { diff --git a/pkg/share/manager/json/json.go b/pkg/share/manager/json/json.go index a453b552cd..6f6c3a28cc 100644 --- a/pkg/share/manager/json/json.go +++ b/pkg/share/manager/json/json.go @@ -29,7 +29,8 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" @@ -166,7 +167,7 @@ func genID() string { func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { id := genID() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) now := time.Now().UnixNano() ts := &typespb.Timestamp{ Seconds: uint64(now / 1000000000), @@ -256,7 +257,7 @@ func (m *mgr) get(ctx context.Context, ref *collaboration.ShareReference) (s *co } // check if we are the owner - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if share.IsCreatedByUser(s, user) { return s, nil } @@ -282,7 +283,7 @@ func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) ( func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { m.Lock() defer m.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for i, s := range m.model.Shares { if sharesEqual(ref, s) { if share.IsCreatedByUser(s, user) { @@ -316,7 +317,7 @@ func sharesEqual(ref *collaboration.ShareReference, s *collaboration.Share) bool func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { m.Lock() defer m.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for i, s := range m.model.Shares { if sharesEqual(ref, s) { if share.IsCreatedByUser(s, user) { @@ -341,7 +342,7 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( var ss []*collaboration.Share m.Lock() defer m.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.model.Shares { if share.IsCreatedByUser(s, user) { // no filter we return earlier @@ -363,7 +364,7 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F var rss []*collaboration.ReceivedShare m.Lock() defer m.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.model.Shares { if share.IsCreatedByUser(s, user) || !share.IsGrantedToUser(s, user) { // omit shares created by the user or shares the user can't access @@ -390,7 +391,7 @@ func (m *mgr) convert(ctx context.Context, s *collaboration.Share) *collaboratio Share: s, State: collaboration.ShareState_SHARE_STATE_PENDING, } - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if v, ok := m.model.State[user.Id.String()]; ok { if state, ok := v[s.Id.String()]; ok { rs.State = state @@ -406,7 +407,7 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe func (m *mgr) getReceived(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { m.Lock() defer m.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.model.Shares { if sharesEqual(ref, s) { if share.IsGrantedToUser(s, user) { @@ -424,7 +425,7 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, receivedShare *collaborat return nil, err } - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) m.Lock() defer m.Unlock() diff --git a/pkg/share/manager/memory/memory.go b/pkg/share/manager/memory/memory.go index 2646744a74..844e69e686 100644 --- a/pkg/share/manager/memory/memory.go +++ b/pkg/share/manager/memory/memory.go @@ -29,7 +29,8 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" @@ -68,7 +69,7 @@ func (m *manager) add(ctx context.Context, s *collaboration.Share) { func (m *manager) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { id := atomic.AddUint64(&counter, 1) - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) now := time.Now().UnixNano() ts := &typespb.Timestamp{ Seconds: uint64(now / 1000000000), @@ -147,7 +148,7 @@ func (m *manager) get(ctx context.Context, ref *collaboration.ShareReference) (s } // check if we are the owner - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if share.IsCreatedByUser(s, user) { return s, nil } @@ -168,7 +169,7 @@ func (m *manager) GetShare(ctx context.Context, ref *collaboration.ShareReferenc func (m *manager) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { m.lock.Lock() defer m.lock.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for i, s := range m.shares { if sharesEqual(ref, s) { if share.IsCreatedByUser(s, user) { @@ -198,7 +199,7 @@ func sharesEqual(ref *collaboration.ShareReference, s *collaboration.Share) bool func (m *manager) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { m.lock.Lock() defer m.lock.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for i, s := range m.shares { if sharesEqual(ref, s) { if share.IsCreatedByUser(s, user) { @@ -219,7 +220,7 @@ func (m *manager) ListShares(ctx context.Context, filters []*collaboration.Filte var ss []*collaboration.Share m.lock.Lock() defer m.lock.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.shares { if share.IsCreatedByUser(s, user) { // no filter we return earlier @@ -241,7 +242,7 @@ func (m *manager) ListReceivedShares(ctx context.Context, filters []*collaborati var rss []*collaboration.ReceivedShare m.lock.Lock() defer m.lock.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.shares { if share.IsCreatedByUser(s, user) || !share.IsGrantedToUser(s, user) { // omit shares created by the user or shares the user can't access @@ -268,7 +269,7 @@ func (m *manager) convert(ctx context.Context, s *collaboration.Share) *collabor Share: s, State: collaboration.ShareState_SHARE_STATE_PENDING, } - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) if v, ok := m.shareState[user.Id.String()]; ok { if state, ok := v[s.Id]; ok { rs.State = state @@ -284,7 +285,7 @@ func (m *manager) GetReceivedShare(ctx context.Context, ref *collaboration.Share func (m *manager) getReceived(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { m.lock.Lock() defer m.lock.Unlock() - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) for _, s := range m.shares { if sharesEqual(ref, s) { if share.IsGrantedToUser(s, user) { @@ -302,7 +303,7 @@ func (m *manager) UpdateReceivedShare(ctx context.Context, receivedShare *collab return nil, err } - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) m.lock.Lock() defer m.lock.Unlock() diff --git a/pkg/share/manager/sql/conversions.go b/pkg/share/manager/sql/conversions.go new file mode 100644 index 0000000000..a09cae34e5 --- /dev/null +++ b/pkg/share/manager/sql/conversions.go @@ -0,0 +1,262 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sql + +import ( + "context" + + grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + conversions "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" + "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" +) + +//go:generate mockery -name UserConverter + +// DBShare stores information about user and public shares. +type DBShare struct { + ID string + UIDOwner string + UIDInitiator string + ItemStorage string + ItemSource string + ShareWith string + Token string + Expiration string + Permissions int + ShareType int + ShareName string + STime int + FileTarget string + RejectedBy string + State int +} + +// UserConverter describes an interface for converting user ids to names and back. +type UserConverter interface { + UserNameToUserID(ctx context.Context, username string) (*userpb.UserId, error) + UserIDToUserName(ctx context.Context, userid *userpb.UserId) (string, error) +} + +// GatewayUserConverter converts usernames and ids using the gateway. +type GatewayUserConverter struct { + gwAddr string +} + +// NewGatewayUserConverter returns a instance of GatewayUserConverter. +func NewGatewayUserConverter(gwAddr string) *GatewayUserConverter { + return &GatewayUserConverter{ + gwAddr: gwAddr, + } +} + +// UserIDToUserName converts a user ID to an username. +func (c *GatewayUserConverter) UserIDToUserName(ctx context.Context, userid *userpb.UserId) (string, error) { + gwConn, err := pool.GetGatewayServiceClient(pool.Endpoint(c.gwAddr)) + if err != nil { + return "", err + } + getUserResponse, err := gwConn.GetUser(ctx, &userpb.GetUserRequest{ + UserId: userid, + SkipFetchingUserGroups: true, + }) + if err != nil { + return "", err + } + if getUserResponse.Status.Code != rpc.Code_CODE_OK { + return "", status.NewErrorFromCode(getUserResponse.Status.Code, "gateway") + } + return getUserResponse.User.Username, nil +} + +// UserNameToUserID converts a username to an user ID. +func (c *GatewayUserConverter) UserNameToUserID(ctx context.Context, username string) (*userpb.UserId, error) { + gwConn, err := pool.GetGatewayServiceClient(pool.Endpoint(c.gwAddr)) + if err != nil { + return nil, err + } + getUserResponse, err := gwConn.GetUserByClaim(ctx, &userpb.GetUserByClaimRequest{ + Claim: "username", + Value: username, + SkipFetchingUserGroups: true, + }) + if err != nil { + return nil, err + } + if getUserResponse.Status.Code != rpc.Code_CODE_OK { + return nil, status.NewErrorFromCode(getUserResponse.Status.Code, "gateway") + } + return getUserResponse.User.Id, nil +} + +func (m *mgr) formatGrantee(ctx context.Context, g *provider.Grantee) (int, string, error) { + var granteeType int + var formattedID string + switch g.Type { + case provider.GranteeType_GRANTEE_TYPE_USER: + granteeType = 0 + var err error + formattedID, err = m.userConverter.UserIDToUserName(ctx, g.GetUserId()) + if err != nil { + return 0, "", err + } + case provider.GranteeType_GRANTEE_TYPE_GROUP: + granteeType = 1 + formattedID = formatGroupID(g.GetGroupId()) + default: + granteeType = -1 + } + return granteeType, formattedID, nil +} + +func (m *mgr) extractGrantee(ctx context.Context, t int, g string) (*provider.Grantee, error) { + var grantee provider.Grantee + switch t { + case 0: + userid, err := m.userConverter.UserNameToUserID(ctx, g) + if err != nil { + return nil, err + } + grantee.Type = provider.GranteeType_GRANTEE_TYPE_USER + grantee.Id = &provider.Grantee_UserId{UserId: userid} + case 1: + grantee.Type = provider.GranteeType_GRANTEE_TYPE_GROUP + grantee.Id = &provider.Grantee_GroupId{GroupId: extractGroupID(g)} + default: + grantee.Type = provider.GranteeType_GRANTEE_TYPE_INVALID + } + return &grantee, nil +} + +func resourceTypeToItem(r provider.ResourceType) string { + switch r { + case provider.ResourceType_RESOURCE_TYPE_FILE: + return "file" + case provider.ResourceType_RESOURCE_TYPE_CONTAINER: + return "folder" + case provider.ResourceType_RESOURCE_TYPE_REFERENCE: + return "reference" + case provider.ResourceType_RESOURCE_TYPE_SYMLINK: + return "symlink" + default: + return "" + } +} + +func sharePermToInt(p *provider.ResourcePermissions) int { + return int(conversions.RoleFromResourcePermissions(p).OCSPermissions()) +} + +func intTosharePerm(p int) (*provider.ResourcePermissions, error) { + perms, err := conversions.NewPermissions(p) + if err != nil { + return nil, err + } + + return conversions.RoleFromOCSPermissions(perms).CS3ResourcePermissions(), nil +} + +func intToShareState(g int) collaboration.ShareState { + switch g { + case 0: + return collaboration.ShareState_SHARE_STATE_ACCEPTED + case 1: + return collaboration.ShareState_SHARE_STATE_PENDING + case 2: + return collaboration.ShareState_SHARE_STATE_REJECTED + default: + return collaboration.ShareState_SHARE_STATE_INVALID + } +} + +func formatUserID(u *userpb.UserId) string { + return u.OpaqueId +} + +func formatGroupID(u *grouppb.GroupId) string { + return u.OpaqueId +} + +func extractGroupID(u string) *grouppb.GroupId { + return &grouppb.GroupId{OpaqueId: u} +} + +func (m *mgr) convertToCS3Share(ctx context.Context, s DBShare, storageMountID string) (*collaboration.Share, error) { + ts := &typespb.Timestamp{ + Seconds: uint64(s.STime), + } + permissions, err := intTosharePerm(s.Permissions) + if err != nil { + return nil, err + } + grantee, err := m.extractGrantee(ctx, s.ShareType, s.ShareWith) + if err != nil { + return nil, err + } + owner, err := m.userConverter.UserNameToUserID(ctx, s.UIDOwner) + if err != nil { + return nil, err + } + var creator *userpb.UserId + if s.UIDOwner == s.UIDInitiator { + creator = owner + } else { + creator, err = m.userConverter.UserNameToUserID(ctx, s.UIDOwner) + if err != nil { + return nil, err + } + } + return &collaboration.Share{ + Id: &collaboration.ShareId{ + OpaqueId: s.ID, + }, + ResourceId: &provider.ResourceId{ + StorageId: storageMountID + "!" + s.ItemStorage, + OpaqueId: s.ItemSource, + }, + Permissions: &collaboration.SharePermissions{Permissions: permissions}, + Grantee: grantee, + Owner: owner, + Creator: creator, + Ctime: ts, + Mtime: ts, + }, nil +} + +func (m *mgr) convertToCS3ReceivedShare(ctx context.Context, s DBShare, storageMountID string) (*collaboration.ReceivedShare, error) { + share, err := m.convertToCS3Share(ctx, s, storageMountID) + if err != nil { + return nil, err + } + var state collaboration.ShareState + if s.RejectedBy != "" { + state = collaboration.ShareState_SHARE_STATE_REJECTED + } else { + state = intToShareState(s.State) + } + return &collaboration.ReceivedShare{ + Share: share, + State: state, + }, nil +} diff --git a/pkg/share/manager/sql/mocks/UserConverter.go b/pkg/share/manager/sql/mocks/UserConverter.go new file mode 100644 index 0000000000..48da015a80 --- /dev/null +++ b/pkg/share/manager/sql/mocks/UserConverter.go @@ -0,0 +1,78 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" +) + +// UserConverter is an autogenerated mock type for the UserConverter type +type UserConverter struct { + mock.Mock +} + +// UserIDToUserName provides a mock function with given fields: ctx, userid +func (_m *UserConverter) UserIDToUserName(ctx context.Context, userid *userv1beta1.UserId) (string, error) { + ret := _m.Called(ctx, userid) + + var r0 string + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.UserId) string); ok { + r0 = rf(ctx, userid) + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *userv1beta1.UserId) error); ok { + r1 = rf(ctx, userid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UserNameToUserID provides a mock function with given fields: ctx, username +func (_m *UserConverter) UserNameToUserID(ctx context.Context, username string) (*userv1beta1.UserId, error) { + ret := _m.Called(ctx, username) + + var r0 *userv1beta1.UserId + if rf, ok := ret.Get(0).(func(context.Context, string) *userv1beta1.UserId); ok { + r0 = rf(ctx, username) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*userv1beta1.UserId) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, username) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/pkg/share/manager/sql/sql.go b/pkg/share/manager/sql/sql.go index ca06a838d9..2c156fd713 100644 --- a/pkg/share/manager/sql/sql.go +++ b/pkg/share/manager/sql/sql.go @@ -27,15 +27,11 @@ import ( "strings" "time" - gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" - rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - conversions "github.com/cs3org/reva/pkg/cbox/utils" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/share" "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/cs3org/reva/pkg/sharedconf" @@ -51,37 +47,35 @@ import ( const ( shareTypeUser = 0 shareTypeGroup = 1 - - projectInstancesPrefix = "newproject" - projectSpaceGroupsPrefix = "cernbox-project-" - projectSpaceAdminGroupsSuffix = "-admins" ) func init() { - registry.Register("sql", New) + registry.Register("oc10-sql", NewMysql) } type config struct { - DBUsername string `mapstructure:"db_username"` - DBPassword string `mapstructure:"db_password"` - DBHost string `mapstructure:"db_host"` - DBPort int `mapstructure:"db_port"` - DBName string `mapstructure:"db_name"` - GatewaySvc string `mapstructure:"gatewaysvc"` + GatewayAddr string `mapstructure:"gatewaysvc"` + StorageMountID string `mapstructure:"storage_mount_id"` + DBUsername string `mapstructure:"db_username"` + DBPassword string `mapstructure:"db_password"` + DBHost string `mapstructure:"db_host"` + DBPort int `mapstructure:"db_port"` + DBName string `mapstructure:"db_name"` } -type mgr struct { - c *config - db *sql.DB - client gatewayv1beta1.GatewayAPIClient +func (c *config) ApplyDefaults() { + c.GatewayAddr = sharedconf.GetGatewaySVC(c.GatewayAddr) } -func (c *config) ApplyDefaults() { - c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) +type mgr struct { + driver string + db *sql.DB + storageMountID string + userConverter UserConverter } -// New returns a new share manager. -func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { +// NewMysql returns a new share manager connection to a mysql database. +func NewMysql(ctx context.Context, m map[string]interface{}) (share.Manager, error) { var c config if err := cfg.Decode(m, &c); err != nil { return nil, err @@ -92,20 +86,23 @@ func New(ctx context.Context, m map[string]interface{}) (share.Manager, error) { return nil, err } - gw, err := pool.GetGatewayServiceClient(pool.Endpoint(c.GatewaySvc)) - if err != nil { - return nil, err - } + userConverter := NewGatewayUserConverter(c.GatewayAddr) + + return New("mysql", db, c.StorageMountID, userConverter) +} +// New returns a new Cache instance connecting to the given sql.DB. +func New(driver string, db *sql.DB, storageMountID string, userConverter UserConverter) (share.Manager, error) { return &mgr{ - c: &c, - db: db, - client: gw, + driver: driver, + db: db, + storageMountID: storageMountID, + userConverter: userConverter, }, nil } func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) // do not allow share to myself or the owner if share is for a user // TODO(labkode): should not this be caught already at the gw level? @@ -132,11 +129,17 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora Seconds: uint64(now), } - shareType, shareWith := conversions.FormatGrantee(g.Grantee) - itemType := conversions.ResourceTypeToItem(md.Type) + owner, err := m.userConverter.UserIDToUserName(ctx, md.Owner) + if err != nil { + return nil, err + } + shareType, shareWith, err := m.formatGrantee(ctx, g.Grantee) + if err != nil { + return nil, err + } + itemType := resourceTypeToItem(md.Type) targetPath := path.Join("/", path.Base(md.Path)) - permissions := conversions.SharePermToInt(g.Permissions.Permissions) - prefix := md.Id.StorageId + permissions := sharePermToInt(g.Permissions.Permissions) itemSource := md.Id.OpaqueId fileSource, err := strconv.ParseUint(itemSource, 10, 64) if err != nil { @@ -145,8 +148,8 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora fileSource = 0 } - stmtString := "insert into oc_share set share_type=?,uid_owner=?,uid_initiator=?,item_type=?,fileid_prefix=?,item_source=?,file_source=?,permissions=?,stime=?,share_with=?,file_target=?" - stmtValues := []interface{}{shareType, conversions.FormatUserID(md.Owner), conversions.FormatUserID(user.Id), itemType, prefix, itemSource, fileSource, permissions, now, shareWith, targetPath} + stmtString := "INSERT INTO oc_share (share_type,uid_owner,uid_initiator,item_type,item_source,file_source,permissions,stime,share_with,file_target) VALUES (?,?,?,?,?,?,?,?,?,?)" + stmtValues := []interface{}{shareType, owner, user.Username, itemType, itemSource, fileSource, permissions, now, shareWith, targetPath} stmt, err := m.db.Prepare(stmtString) if err != nil { @@ -175,35 +178,6 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabora }, nil } -func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) { - uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) - s := conversions.DBShare{ID: id.OpaqueId} - query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, stime, permissions, share_type FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND id=? AND (uid_owner=? or uid_initiator=?)" - if err := m.db.QueryRow(query, id.OpaqueId, uid, uid).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.STime, &s.Permissions, &s.ShareType); err != nil { - if err == sql.ErrNoRows { - return nil, errtypes.NotFound(id.OpaqueId) - } - return nil, err - } - return conversions.ConvertToCS3Share(s), nil -} - -func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) { - owner := conversions.FormatUserID(key.Owner) - uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) - - s := conversions.DBShare{} - shareType, shareWith := conversions.FormatGrantee(key.Grantee) - query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, id, stime, permissions, share_type FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND uid_owner=? AND fileid_prefix=? AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" - if err := m.db.QueryRow(query, owner, key.ResourceId.StorageId, key.ResourceId.OpaqueId, shareType, shareWith, uid, uid).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.ID, &s.STime, &s.Permissions, &s.ShareType); err != nil { - if err == sql.ErrNoRows { - return nil, errtypes.NotFound(key.String()) - } - return nil, err - } - return conversions.ConvertToCS3Share(s), nil -} - func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { var s *collaboration.Share var err error @@ -224,19 +198,22 @@ func (m *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) ( } func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { - uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) + uid := appctx.ContextMustGetUser(ctx).Username var query string params := []interface{}{} switch { case ref.GetId() != nil: - query = "delete from oc_share where id=? AND (uid_owner=? or uid_initiator=?)" + query = "DELETE FROM oc_share where id=? AND (uid_owner=? or uid_initiator=?)" params = append(params, ref.GetId().OpaqueId, uid, uid) case ref.GetKey() != nil: key := ref.GetKey() - shareType, shareWith := conversions.FormatGrantee(key.Grantee) - owner := conversions.FormatUserID(key.Owner) - query = "delete from oc_share where uid_owner=? AND fileid_prefix=? AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" - params = append(params, owner, key.ResourceId.StorageId, key.ResourceId.OpaqueId, shareType, shareWith, uid, uid) + shareType, shareWith, err := m.formatGrantee(ctx, key.Grantee) + if err != nil { + return err + } + owner := formatUserID(key.Owner) + query = "DELETE FROM oc_share WHERE uid_owner=? AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" + params = append(params, owner, key.ResourceId.StorageId, shareType, shareWith, uid, uid) default: return errtypes.NotFound(ref.String()) } @@ -261,8 +238,8 @@ func (m *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) er } func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { - permissions := conversions.SharePermToInt(p.Permissions) - uid := conversions.FormatUserID(ctxpkg.ContextMustGetUser(ctx).Id) + permissions := sharePermToInt(p.Permissions) + uid := appctx.ContextMustGetUser(ctx).Username var query string params := []interface{}{} @@ -272,10 +249,13 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference params = append(params, permissions, time.Now().Unix(), ref.GetId().OpaqueId, uid, uid) case ref.GetKey() != nil: key := ref.GetKey() - shareType, shareWith := conversions.FormatGrantee(key.Grantee) - owner := conversions.FormatUserID(key.Owner) - query = "update oc_share set permissions=?,stime=? where (uid_owner=? or uid_initiator=?) AND fileid_prefix=? AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" - params = append(params, permissions, time.Now().Unix(), owner, owner, key.ResourceId.StorageId, key.ResourceId.OpaqueId, shareType, shareWith, uid, uid) + shareType, shareWith, err := m.formatGrantee(ctx, key.Grantee) + if err != nil { + return nil, err + } + owner := formatUserID(key.Owner) + query = "update oc_share set permissions=?,stime=? where (uid_owner=? or uid_initiator=?) AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" + params = append(params, permissions, time.Now().Unix(), owner, owner, key.ResourceId.StorageId, shareType, shareWith, uid, uid) default: return nil, errtypes.NotFound(ref.String()) } @@ -292,31 +272,29 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { - query := `select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, - coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, - id, stime, permissions, share_type - FROM oc_share WHERE (orphan = 0 or orphan IS NULL) AND (share_type=? OR share_type=?)` - params := []interface{}{shareTypeUser, shareTypeGroup} + uid := appctx.ContextMustGetUser(ctx).Username + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, id, stime, permissions, share_type FROM oc_share WHERE (uid_owner=? or uid_initiator=?)" + params := []interface{}{uid, uid} - groupedFilters := share.GroupFiltersByType(filters) - if len(groupedFilters) > 0 { - filterQuery, filterParams, err := translateFilters(groupedFilters) + var ( + filterQuery string + filterParams []interface{} + err error + ) + if len(filters) == 0 { + filterQuery += "(share_type=? OR share_type=?)" + params = append(params, shareTypeUser) + params = append(params, shareTypeGroup) + } else { + filterQuery, filterParams, err = translateFilters(filters) if err != nil { return nil, err } params = append(params, filterParams...) - if filterQuery != "" { - query = fmt.Sprintf("%s AND (%s)", query, filterQuery) - } } - uidOwnersQuery, uidOwnersParams, err := m.uidOwnerFilters(ctx, groupedFilters) - if err != nil { - return nil, err - } - params = append(params, uidOwnersParams...) - if uidOwnersQuery != "" { - query = fmt.Sprintf("%s AND (%s)", query, uidOwnersQuery) + if filterQuery != "" { + query = fmt.Sprintf("%s AND (%s)", query, filterQuery) } rows, err := m.db.Query(query, params...) @@ -325,13 +303,17 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( } defer rows.Close() - var s conversions.DBShare + var s DBShare shares := []*collaboration.Share{} for rows.Next() { - if err := rows.Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.ID, &s.STime, &s.Permissions, &s.ShareType); err != nil { + if err := rows.Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.ID, &s.STime, &s.Permissions, &s.ShareType); err != nil { continue } - shares = append(shares, conversions.ConvertToCS3Share(s)) + share, err := m.convertToCS3Share(ctx, s, m.storageMountID) + if err != nil { + return nil, err + } + shares = append(shares, share) } if err = rows.Err(); err != nil { return nil, err @@ -342,27 +324,28 @@ func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ( // we list the shares that are targeted to the user in context or to the user groups. func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { - user := ctxpkg.ContextMustGetUser(ctx) - uid := conversions.FormatUserID(user.Id) + user := appctx.ContextMustGetUser(ctx) + uid := user.Username - params := []interface{}{uid, uid, uid, uid} + params := []interface{}{uid, uid, uid} for _, v := range user.Groups { params = append(params, v) } - query := `SELECT coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, - coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, - ts.id, stime, permissions, share_type, coalesce(tr.state, 0) as state - FROM oc_share ts LEFT JOIN oc_share_status tr ON (ts.id = tr.id AND tr.recipient = ?) - WHERE (orphan = 0 or orphan IS NULL) AND (uid_owner != ? AND uid_initiator != ?)` + homeConcat := "" + if m.driver == "mysql" { // mysql upsert + homeConcat = "storages.id = CONCAT('home::', ts.uid_owner)" + } else { // sqlite3 upsert + homeConcat = "storages.id = 'home::' || ts.uid_owner" + } + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, ts.id, stime, permissions, share_type, accepted, storages.numeric_id FROM oc_share ts LEFT JOIN oc_storages storages ON " + homeConcat + " WHERE (uid_owner != ? AND uid_initiator != ?) " if len(user.Groups) > 0 { - query += " AND ((share_with=? AND share_type = 0) OR (share_type = 1 AND share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + ")))" + query += "AND (share_with=? OR share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + "))" } else { - query += " AND (share_with=? AND share_type = 0)" + query += "AND (share_with=?)" } - groupedFilters := share.GroupFiltersByType(filters) - filterQuery, filterParams, err := translateFilters(groupedFilters) + filterQuery, filterParams, err := translateFilters(filters) if err != nil { return nil, err } @@ -378,13 +361,17 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F } defer rows.Close() - var s conversions.DBShare + var s DBShare shares := []*collaboration.ReceivedShare{} for rows.Next() { - if err := rows.Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.ID, &s.STime, &s.Permissions, &s.ShareType, &s.State); err != nil { + if err := rows.Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.ID, &s.STime, &s.Permissions, &s.ShareType, &s.State, &s.ItemStorage); err != nil { continue } - shares = append(shares, conversions.ConvertToCS3ReceivedShare(s)) + share, err := m.convertToCS3ReceivedShare(ctx, s, m.storageMountID) + if err != nil { + return nil, err + } + shares = append(shares, share) } if err = rows.Err(); err != nil { return nil, err @@ -393,67 +380,6 @@ func (m *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.F return shares, nil } -func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.ReceivedShare, error) { - user := ctxpkg.ContextMustGetUser(ctx) - uid := conversions.FormatUserID(user.Id) - - params := []interface{}{uid, id.OpaqueId, uid} - for _, v := range user.Groups { - params = append(params, v) - } - - s := conversions.DBShare{ID: id.OpaqueId} - query := `select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, - coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, - stime, permissions, share_type, coalesce(tr.state, 0) as state - FROM oc_share ts LEFT JOIN oc_share_status tr ON (ts.id = tr.id AND tr.recipient = ?) - WHERE (orphan = 0 or orphan IS NULL) AND ts.id=?` - if len(user.Groups) > 0 { - query += " AND ((share_with=? AND share_type = 0) OR (share_type = 1 AND share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + ")))" - } else { - query += " AND (share_with=? AND share_type = 0)" - } - if err := m.db.QueryRow(query, params...).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.STime, &s.Permissions, &s.ShareType, &s.State); err != nil { - if err == sql.ErrNoRows { - return nil, errtypes.NotFound(id.OpaqueId) - } - return nil, err - } - return conversions.ConvertToCS3ReceivedShare(s), nil -} - -func (m *mgr) getReceivedByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.ReceivedShare, error) { - user := ctxpkg.ContextMustGetUser(ctx) - uid := conversions.FormatUserID(user.Id) - - shareType, shareWith := conversions.FormatGrantee(key.Grantee) - params := []interface{}{uid, conversions.FormatUserID(key.Owner), key.ResourceId.StorageId, key.ResourceId.OpaqueId, shareType, shareWith, shareWith} - for _, v := range user.Groups { - params = append(params, v) - } - - s := conversions.DBShare{} - query := `select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, - coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source, coalesce(item_type, '') as item_type, - ts.id, stime, permissions, share_type, coalesce(tr.state, 0) as state - FROM oc_share ts LEFT JOIN oc_share_status tr ON (ts.id = tr.id AND tr.recipient = ?) - WHERE (orphan = 0 or orphan IS NULL) AND uid_owner=? AND fileid_prefix=? AND item_source=? AND share_type=? AND share_with=?` - if len(user.Groups) > 0 { - query += " AND ((share_with=? AND share_type = 0) OR (share_type = 1 AND share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + ")))" - } else { - query += " AND (share_with=? AND share_type = 0)" - } - - if err := m.db.QueryRow(query, params...).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.Prefix, &s.ItemSource, &s.ItemType, &s.ID, &s.STime, &s.Permissions, &s.ShareType, &s.State); err != nil { - if err == sql.ErrNoRows { - return nil, errtypes.NotFound(key.String()) - } - return nil, err - } - - return conversions.ConvertToCS3ReceivedShare(s), nil -} - func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { var s *collaboration.ReceivedShare var err error @@ -474,8 +400,6 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe } func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { - user := ctxpkg.ContextMustGetUser(ctx) - rs, err := m.GetReceivedShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: share.Share.Id}}) if err != nil { return nil, err @@ -485,82 +409,122 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.Rece switch fieldMask.Paths[i] { case "state": rs.State = share.State + // TODO case "mount_point": default: return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") } } - state := 0 + var queryAccept string switch rs.GetState() { case collaboration.ShareState_SHARE_STATE_REJECTED: - state = -1 + queryAccept = "update oc_share set accepted=2 where id=?" case collaboration.ShareState_SHARE_STATE_ACCEPTED: - state = 1 + queryAccept = "update oc_share set accepted=0 where id=?" } - params := []interface{}{rs.Share.Id.OpaqueId, conversions.FormatUserID(user.Id), state, state} - query := "insert into oc_share_status(id, recipient, state) values(?, ?, ?) ON DUPLICATE KEY UPDATE state = ?" + if queryAccept != "" { + stmt, err := m.db.Prepare(queryAccept) + if err != nil { + return nil, err + } + _, err = stmt.Exec(rs.Share.Id.OpaqueId) + if err != nil { + return nil, err + } + } - stmt, err := m.db.Prepare(query) - if err != nil { + return rs, nil +} + +func (m *mgr) getByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.Share, error) { + uid := appctx.ContextMustGetUser(ctx).Username + s := DBShare{ID: id.OpaqueId} + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, stime, permissions, share_type FROM oc_share WHERE id=? AND (uid_owner=? or uid_initiator=?)" + if err := m.db.QueryRow(query, id.OpaqueId, uid, uid).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.STime, &s.Permissions, &s.ShareType); err != nil { + if err == sql.ErrNoRows { + return nil, errtypes.NotFound(id.OpaqueId) + } return nil, err } - _, err = stmt.Exec(params...) + return m.convertToCS3Share(ctx, s, m.storageMountID) +} + +func (m *mgr) getByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.Share, error) { + owner, err := m.userConverter.UserIDToUserName(ctx, key.Owner) if err != nil { return nil, err } + uid := appctx.ContextMustGetUser(ctx).Username - return rs, nil + s := DBShare{} + shareType, shareWith, err := m.formatGrantee(ctx, key.Grantee) + if err != nil { + return nil, err + } + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, id, stime, permissions, share_type FROM oc_share WHERE uid_owner=? AND item_source=? AND share_type=? AND share_with=? AND (uid_owner=? or uid_initiator=?)" + if err = m.db.QueryRow(query, owner, key.ResourceId.StorageId, shareType, shareWith, uid, uid).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.ID, &s.STime, &s.Permissions, &s.ShareType); err != nil { + if err == sql.ErrNoRows { + return nil, errtypes.NotFound(key.String()) + } + return nil, err + } + return m.convertToCS3Share(ctx, s, m.storageMountID) } -func (m *mgr) uidOwnerFilters(ctx context.Context, filters map[collaboration.Filter_Type][]*collaboration.Filter) (string, []interface{}, error) { - user := ctxpkg.ContextMustGetUser(ctx) - uid := conversions.FormatUserID(user.Id) +func (m *mgr) getReceivedByID(ctx context.Context, id *collaboration.ShareId) (*collaboration.ReceivedShare, error) { + user := appctx.ContextMustGetUser(ctx) + uid := user.Username - query := "uid_owner=? or uid_initiator=?" - params := []interface{}{uid, uid} + params := []interface{}{id.OpaqueId, uid} + for _, v := range user.Groups { + params = append(params, v) + } - client, err := pool.GetGatewayServiceClient(pool.Endpoint(m.c.GatewaySvc)) - if err != nil { - return "", nil, err + s := DBShare{ID: id.OpaqueId} + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, stime, permissions, share_type, accepted FROM oc_share ts WHERE ts.id=? " + if len(user.Groups) > 0 { + query += "AND (share_with=? OR share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + "))" + } else { + query += "AND (share_with=?)" } + if err := m.db.QueryRow(query, params...).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.STime, &s.Permissions, &s.ShareType, &s.State); err != nil { + if err == sql.ErrNoRows { + return nil, errtypes.NotFound(id.OpaqueId) + } + return nil, err + } + return m.convertToCS3ReceivedShare(ctx, s, m.storageMountID) +} - if resourceFilters, ok := filters[collaboration.Filter_TYPE_RESOURCE_ID]; ok { - for _, f := range resourceFilters { - // For shares inside project spaces, if the user is an admin, we try to list all shares created by other admins - if strings.HasPrefix(f.GetResourceId().GetStorageId(), projectInstancesPrefix) { - res, err := client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: f.GetResourceId()}}) - if err != nil || res.Status.Code != rpc.Code_CODE_OK { - continue - } +func (m *mgr) getReceivedByKey(ctx context.Context, key *collaboration.ShareKey) (*collaboration.ReceivedShare, error) { + user := appctx.ContextMustGetUser(ctx) + uid := user.Username - // The path will look like /eos/project/c/cernbox, we need to extract the project name - parts := strings.SplitN(res.Info.Path, "/", 6) - if len(parts) < 5 { - continue - } + shareType, shareWith, err := m.formatGrantee(ctx, key.Grantee) + if err != nil { + return nil, err + } + params := []interface{}{uid, formatUserID(key.Owner), key.ResourceId.StorageId, key.ResourceId.OpaqueId, shareType, shareWith, shareWith} + for _, v := range user.Groups { + params = append(params, v) + } - adminGroup := projectSpaceGroupsPrefix + parts[4] + projectSpaceAdminGroupsSuffix - for _, g := range user.Groups { - if g == adminGroup { - // User belongs to the admin group, list all shares for the resource - - // TODO: this only works if shares for a single project are requested. - // If shares for multiple projects are requested, then we're not checking if the - // user is an admin for all of those. We can append the query ` or uid_owner=?` - // for all the project owners, which works fine for new reva - // but won't work for revaold since there, we store the uid of the share creator as uid_owner. - // For this to work across the two versions, this change would have to be made in revaold - // but it won't be straightforward as there, the storage provider doesn't return the - // resource owners. - return "", []interface{}{}, nil - } - } - } - } + s := DBShare{} + query := "select coalesce(uid_owner, '') as uid_owner, coalesce(uid_initiator, '') as uid_initiator, coalesce(share_with, '') as share_with, coalesce(item_source, '') as item_source, ts.id, stime, permissions, share_type, accepted FROM oc_share ts WHERE uid_owner=? AND item_source=? AND share_type=? AND share_with=? " + if len(user.Groups) > 0 { + query += "AND (share_with=? OR share_with in (?" + strings.Repeat(",?", len(user.Groups)-1) + "))" + } else { + query += "AND (share_with=?)" } - return query, params, nil + if err := m.db.QueryRow(query, params...).Scan(&s.UIDOwner, &s.UIDInitiator, &s.ShareWith, &s.ItemSource, &s.ID, &s.STime, &s.Permissions, &s.ShareType, &s.State); err != nil { + if err == sql.ErrNoRows { + return nil, errtypes.NotFound(key.String()) + } + return nil, err + } + return m.convertToCS3ReceivedShare(ctx, s, m.storageMountID) } func granteeTypeToShareType(granteeType provider.GranteeType) int { @@ -574,48 +538,49 @@ func granteeTypeToShareType(granteeType provider.GranteeType) int { } // translateFilters translates the filters to sql queries. -func translateFilters(filters map[collaboration.Filter_Type][]*collaboration.Filter) (string, []interface{}, error) { +func translateFilters(filters []*collaboration.Filter) (string, []interface{}, error) { var ( filterQuery string params []interface{} ) + groupedFilters := share.GroupFiltersByType(filters) // If multiple filters of the same type are passed to this function, they need to be combined with the `OR` operator. // That is why the filters got grouped by type. // For every given filter type, iterate over the filters and if there are more than one combine them. // Combine the different filter types using `AND` var filterCounter = 0 - for filterType, currFilters := range filters { + for filterType, filters := range groupedFilters { switch filterType { case collaboration.Filter_TYPE_RESOURCE_ID: filterQuery += "(" - for i, f := range currFilters { - filterQuery += "(fileid_prefix =? AND item_source=?)" - params = append(params, f.GetResourceId().StorageId, f.GetResourceId().OpaqueId) + for i, f := range filters { + filterQuery += "item_source=?" + params = append(params, f.GetResourceId().OpaqueId) - if i != len(currFilters)-1 { + if i != len(filters)-1 { filterQuery += " OR " } } filterQuery += ")" case collaboration.Filter_TYPE_GRANTEE_TYPE: filterQuery += "(" - for i, f := range currFilters { + for i, f := range filters { filterQuery += "share_type=?" params = append(params, granteeTypeToShareType(f.GetGranteeType())) - if i != len(currFilters)-1 { + if i != len(filters)-1 { filterQuery += " OR " } } filterQuery += ")" case collaboration.Filter_TYPE_EXCLUDE_DENIALS: // TODO this may change once the mapping of permission to share types is completed (cf. pkg/cbox/utils/conversions.go) - filterQuery += "(permissions > 0)" + filterQuery += "permissions > 0" default: return "", nil, fmt.Errorf("filter type is not supported") } - if filterCounter != len(filters)-1 { + if filterCounter != len(groupedFilters)-1 { filterQuery += " AND " } filterCounter++ diff --git a/pkg/storage/fs/s3/upload.go b/pkg/share/manager/sql/sql_suite_test.go similarity index 65% rename from pkg/storage/fs/s3/upload.go rename to pkg/share/manager/sql/sql_suite_test.go index e3343b38f9..e3c6fbd8e9 100644 --- a/pkg/storage/fs/s3/upload.go +++ b/pkg/share/manager/sql/sql_suite_test.go @@ -16,16 +16,16 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -package s3 +package sql_test import ( - "context" + "testing" - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - "github.com/cs3org/reva/pkg/errtypes" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) -// InitiateUpload returns upload ids corresponding to different protocols it supports. -func (fs *s3FS) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) { - return nil, errtypes.NotSupported("op not supported") +func TestSql(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Sql Suite") } diff --git a/pkg/share/manager/sql/sql_test.go b/pkg/share/manager/sql/sql_test.go new file mode 100644 index 0000000000..176e75eb66 --- /dev/null +++ b/pkg/share/manager/sql/sql_test.go @@ -0,0 +1,274 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sql_test + +import ( + "context" + "database/sql" + "os" + + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/share" + sqlmanager "github.com/cs3org/reva/pkg/share/manager/sql" + mocks "github.com/cs3org/reva/pkg/share/manager/sql/mocks" + _ "github.com/mattn/go-sqlite3" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/stretchr/testify/mock" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +var _ = Describe("SQL manager", func() { + var ( + mgr share.Manager + ctx context.Context + testDBFile *os.File + + loginAs = func(user *user.User) { + ctx = appctx.ContextSetUser(context.Background(), user) + } + admin = &user.User{ + Id: &user.UserId{ + Idp: "idp", + OpaqueId: "userid", + Type: user.UserType_USER_TYPE_PRIMARY, + }, + Username: "admin", + } + otherUser = &user.User{ + Id: &user.UserId{ + Idp: "idp", + OpaqueId: "userid", + Type: user.UserType_USER_TYPE_PRIMARY, + }, + Username: "einstein", + } + + shareRef = &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ + Id: &collaboration.ShareId{ + OpaqueId: "1", + }, + }} + ) + + AfterEach(func() { + os.Remove(testDBFile.Name()) + }) + + BeforeEach(func() { + var err error + testDBFile, err = os.CreateTemp("", "example") + Expect(err).ToNot(HaveOccurred()) + + dbData, err := os.ReadFile("test.db") + Expect(err).ToNot(HaveOccurred()) + + _, err = testDBFile.Write(dbData) + Expect(err).ToNot(HaveOccurred()) + err = testDBFile.Close() + Expect(err).ToNot(HaveOccurred()) + + sqldb, err := sql.Open("sqlite3", testDBFile.Name()) + Expect(err).ToNot(HaveOccurred()) + + userConverter := &mocks.UserConverter{} + userConverter.On("UserIDToUserName", mock.Anything, mock.Anything).Return("username", nil) + userConverter.On("UserNameToUserID", mock.Anything, mock.Anything).Return( + func(_ context.Context, username string) *user.UserId { + return &user.UserId{ + OpaqueId: username, + } + }, + func(_ context.Context, username string) error { return nil }) + mgr, err = sqlmanager.New("sqlite3", sqldb, "abcde", userConverter) + Expect(err).ToNot(HaveOccurred()) + + loginAs(admin) + }) + + It("creates manager instances", func() { + Expect(mgr).ToNot(BeNil()) + }) + + Describe("GetShare", func() { + It("returns the share", func() { + share, err := mgr.GetShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + }) + + It("returns an error if the share does not exis", func() { + share, err := mgr.GetShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ + Id: &collaboration.ShareId{ + OpaqueId: "2", + }, + }}) + Expect(err).To(HaveOccurred()) + Expect(share).To(BeNil()) + }) + }) + + Describe("Share", func() { + It("creates a share", func() { + grant := &collaboration.ShareGrant{ + Grantee: &provider.Grantee{ + Type: provider.GranteeType_GRANTEE_TYPE_USER, + Id: &provider.Grantee_UserId{UserId: &user.UserId{ + OpaqueId: "someone", + }}, + }, + Permissions: &collaboration.SharePermissions{ + Permissions: &provider.ResourcePermissions{ + GetPath: true, + InitiateFileDownload: true, + ListFileVersions: true, + ListContainer: true, + Stat: true, + }, + }, + } + info := &provider.ResourceInfo{ + Id: &provider.ResourceId{ + StorageId: "/", + OpaqueId: "something", + }, + } + share, err := mgr.Share(ctx, info, grant) + + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + Expect(share.Id.OpaqueId).To(Equal("2")) + }) + }) + + Describe("ListShares", func() { + It("lists shares", func() { + shares, err := mgr.ListShares(ctx, []*collaboration.Filter{}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(shares)).To(Equal(1)) + + shares, err = mgr.ListShares(ctx, []*collaboration.Filter{ + share.ResourceIDFilter(&provider.ResourceId{ + StorageId: "/", + OpaqueId: "somethingElse", + }), + }) + Expect(err).ToNot(HaveOccurred()) + Expect(len(shares)).To(Equal(0)) + }) + }) + + Describe("ListReceivedShares", func() { + It("lists received shares", func() { + loginAs(otherUser) + shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(shares)).To(Equal(1)) + }) + }) + + Describe("GetReceivedShare", func() { + It("returns the received share", func() { + loginAs(otherUser) + share, err := mgr.GetReceivedShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + }) + }) + + Describe("UpdateReceivedShare", func() { + It("returns an error when no valid field is set in the mask", func() { + loginAs(otherUser) + + share, err := mgr.GetReceivedShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) + + share.State = collaboration.ShareState_SHARE_STATE_REJECTED + _, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"foo"}}) + Expect(err).To(HaveOccurred()) + }) + + It("updates the state when the state is set in the mask", func() { + loginAs(otherUser) + + share, err := mgr.GetReceivedShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) + + share.State = collaboration.ShareState_SHARE_STATE_REJECTED + share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"state"}}) + Expect(err).ToNot(HaveOccurred()) + Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_REJECTED)) + + share, err = mgr.GetReceivedShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_REJECTED)) + }) + }) + + Describe("Unshare", func() { + It("deletes shares", func() { + loginAs(otherUser) + shares, err := mgr.ListReceivedShares(ctx, []*collaboration.Filter{}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(shares)).To(Equal(1)) + + loginAs(admin) + err = mgr.Unshare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ + Id: &collaboration.ShareId{ + OpaqueId: shares[0].Share.Id.OpaqueId, + }, + }}) + Expect(err).ToNot(HaveOccurred()) + + loginAs(otherUser) + shares, err = mgr.ListReceivedShares(ctx, []*collaboration.Filter{}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(shares)).To(Equal(0)) + }) + }) + + Describe("UpdateShare", func() { + It("updates permissions", func() { + share, err := mgr.GetShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share.Permissions.Permissions.Delete).To(BeTrue()) + + share, err = mgr.UpdateShare(ctx, shareRef, &collaboration.SharePermissions{ + Permissions: &provider.ResourcePermissions{ + InitiateFileUpload: true, + RestoreFileVersion: true, + RestoreRecycleItem: true, + }}) + Expect(err).ToNot(HaveOccurred()) + Expect(share.Permissions.Permissions.Delete).To(BeFalse()) + + share, err = mgr.GetShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share.Permissions.Permissions.Delete).To(BeFalse()) + }) + }) +}) diff --git a/pkg/share/manager/sql/test.db b/pkg/share/manager/sql/test.db new file mode 100644 index 0000000000000000000000000000000000000000..fba76fdcc4fc7816bf2b281f9c2074bf1955842c GIT binary patch literal 655360 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 literal 0 HcmV?d00001 diff --git a/pkg/storage/favorite/memory/memory_test.go b/pkg/storage/favorite/memory/memory_test.go index ac2f766497..7a19b5f401 100644 --- a/pkg/storage/favorite/memory/memory_test.go +++ b/pkg/storage/favorite/memory/memory_test.go @@ -24,7 +24,7 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" ) type environment struct { @@ -51,11 +51,11 @@ func createEnvironment() environment { return environment{ userOne: userOne, - userOneCtx: ctxpkg.ContextSetUser(context.Background(), userOne), + userOneCtx: appctx.ContextSetUser(context.Background(), userOne), userTwo: userTwo, - userTwoCtx: ctxpkg.ContextSetUser(context.Background(), userTwo), + userTwoCtx: appctx.ContextSetUser(context.Background(), userTwo), userThree: userThree, - userThreeCtx: ctxpkg.ContextSetUser(context.Background(), userThree), + userThreeCtx: appctx.ContextSetUser(context.Background(), userThree), resourceInfoOne: resourceInfoOne, resourceInfoTwo: resourceInfoTwo, diff --git a/pkg/storage/favorite/sql/sql.go b/pkg/storage/favorite/sql/sql.go index 5e2ef9b238..0adfa44a0b 100644 --- a/pkg/storage/favorite/sql/sql.go +++ b/pkg/storage/favorite/sql/sql.go @@ -25,8 +25,9 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/cbox/utils" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/storage/favorite" "github.com/cs3org/reva/pkg/storage/favorite/registry" "github.com/cs3org/reva/pkg/utils/cfg" @@ -68,7 +69,7 @@ func New(m map[string]interface{}) (favorite.Manager, error) { } func (m *mgr) ListFavorites(ctx context.Context, userID *user.UserId) ([]*provider.ResourceId, error) { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) infos := []*provider.ResourceId{} query := `SELECT fileid_prefix, fileid FROM cbox_metadata WHERE uid=? AND tag_key="fav"` rows, err := m.db.Query(query, user.Id.OpaqueId) @@ -92,7 +93,7 @@ func (m *mgr) ListFavorites(ctx context.Context, userID *user.UserId) ([]*provid } func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) // The primary key is just the ID in the table, it should ideally be (uid, fileid_prefix, fileid, tag_key) // For the time being, just check if the favorite already exists. If it does, return early @@ -117,7 +118,7 @@ func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo } func (m *mgr) UnsetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) stmt, err := m.db.Prepare(`DELETE FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"`) if err != nil { return err diff --git a/pkg/storage/fs/cback/cback.go b/pkg/storage/fs/cback/cback.go index a9ceb153e4..0233071839 100644 --- a/pkg/storage/fs/cback/cback.go +++ b/pkg/storage/fs/cback/cback.go @@ -29,10 +29,11 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" v1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/mime" - "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" "github.com/cs3org/reva/pkg/utils/cfg" @@ -40,7 +41,7 @@ import ( type cback struct { conf *Options - client *http.Client + client *httpclient.Client } func init() { @@ -55,8 +56,7 @@ func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err erro return nil, err } - httpClient := rhttp.GetHTTPClient() - + httpClient := httpclient.New() // Returns the storage.FS interface return &cback{conf: &o, client: httpClient}, nil } @@ -64,7 +64,7 @@ func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err erro func (fs *cback) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { var ssID, searchPath string - user, inContext := ctxpkg.ContextGetUser(ctx) + user, inContext := appctx.ContextGetUser(ctx) if !inContext { return nil, errtypes.UserRequired("user not found in context") @@ -152,7 +152,7 @@ func (fs *cback) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys var path = ref.GetPath() var ssID, searchPath string - user, inContext := ctxpkg.ContextGetUser(ctx) + user, inContext := appctx.ContextGetUser(ctx) if !inContext { return nil, errtypes.UserRequired("no user found in context") @@ -305,7 +305,7 @@ func (fs *cback) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys func (fs *cback) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { var path = ref.GetPath() var ssID, searchPath string - user, _ := ctxpkg.ContextGetUser(ctx) + user, _ := appctx.ContextGetUser(ctx) resp, err := fs.matchBackups(user.Username, path) diff --git a/pkg/storage/fs/cephfs/cephfs.go b/pkg/storage/fs/cephfs/cephfs.go index fc1828bc08..e9e175aff4 100644 --- a/pkg/storage/fs/cephfs/cephfs.go +++ b/pkg/storage/fs/cephfs/cephfs.go @@ -62,7 +62,7 @@ func init() { registry.Register("cephfs", New) } -// New returns an implementation to of the storage.FS interface that talks to +// New returns an implementation to of the storage.FS interface that talk to // a ceph filesystem. func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err error) { var o Options @@ -81,12 +81,9 @@ func New(ctx context.Context, m map[string]interface{}) (fs storage.FS, err erro } for _, dir := range []string{o.ShadowFolder, o.UploadFolder} { - _, err := adminConn.adminMount.Statx(dir, cephfs2.StatxMask(cephfs2.StatxIno), 0) - if err != nil { - err = adminConn.adminMount.MakeDir(dir, dirPermFull) - if err != nil && err.Error() != errFileExists { - return nil, errors.New("cephfs: can't initialise system dir " + dir + ":" + err.Error()) - } + err = adminConn.adminMount.MakeDir(dir, dirPermFull) + if err != nil && err.Error() != errFileExists { + return nil, errors.New("cephfs: can't initialise system dir " + dir + ":" + err.Error()) } } diff --git a/pkg/storage/fs/cephfs/chunking.go b/pkg/storage/fs/cephfs/chunking.go index 9929834132..fc9dbe0bbd 100644 --- a/pkg/storage/fs/cephfs/chunking.go +++ b/pkg/storage/fs/cephfs/chunking.go @@ -108,7 +108,9 @@ func (c *ChunkHandler) getChunkFolderName(i *ChunkBLOBInfo) (path string, err er } func (c *ChunkHandler) saveChunk(path string, r io.ReadCloser) (finish bool, chunk string, err error) { - chunkInfo, err := GetChunkBLOBInfo(path) + var chunkInfo *ChunkBLOBInfo + + chunkInfo, err = GetChunkBLOBInfo(path) if err != nil { err = fmt.Errorf("error getting chunk info from path: %s", path) return @@ -221,4 +223,122 @@ func (c *ChunkHandler) WriteChunk(fn string, r io.ReadCloser) (string, string, e } return chunkInfo.Path, chunk, nil + + // TODO(labkode): implement old chunking + + /* + req2 := &provider.StartWriteSessionRequest{} + res2, err := client.StartWriteSession(ctx, req2) + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if res2.Status.Code != rpc.Code_CODE_OK { + logger.Println(ctx, res2.Status) + w.WriteHeader(http.StatusInternalServerError) + return + } + + sessID := res2.SessionId + logger.Build().Str("sessID", sessID).Msg(ctx, "got write session id") + + stream, err := client.Write(ctx) + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + buffer := make([]byte, 1024*1024*3) + var offset uint64 + var numChunks uint64 + + for { + n, err := fd.Read(buffer) + if n > 0 { + req := &provider.WriteRequest{Data: buffer, Length: uint64(n), SessionId: sessID, Offset: offset} + err = stream.Send(req) + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + numChunks++ + offset += uint64(n) + } + + if err == io.EOF { + break + } + + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + } + + res3, err := stream.CloseAndRecv() + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if res3.Status.Code != rpc.Code_CODE_OK { + logger.Println(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + req4 := &provider.FinishWriteSessionRequest{Filename: chunkInfo.path, SessionId: sessID} + res4, err := client.FinishWriteSession(ctx, req4) + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if res4.Status.Code != rpc.Code_CODE_OK { + logger.Println(ctx, res4.Status) + w.WriteHeader(http.StatusInternalServerError) + return + } + + req.Filename = chunkInfo.path + res, err = client.Stat(ctx, req) + if err != nil { + logger.Error(ctx, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if res.Status.Code != rpc.Code_CODE_OK { + logger.Println(ctx, res.Status) + w.WriteHeader(http.StatusInternalServerError) + return + } + + md2 := res.Metadata + + w.Header().Add("Content-Type", md2.Mime) + w.Header().Set("ETag", md2.Etag) + w.Header().Set("OC-FileId", md2.Id) + w.Header().Set("OC-ETag", md2.Etag) + t := time.Unix(int64(md2.Mtime), 0) + lastModifiedString := t.Format(time.RFC1123Z) + w.Header().Set("Last-Modified", lastModifiedString) + w.Header().Set("X-OC-MTime", "accepted") + + if md == nil { + w.WriteHeader(http.StatusCreated) + return + } + + w.WriteHeader(http.StatusNoContent) + return + */ } diff --git a/pkg/storage/fs/cephfs/connections.go b/pkg/storage/fs/cephfs/connections.go index 8f35860eb1..6ffb0dbb7f 100644 --- a/pkg/storage/fs/cephfs/connections.go +++ b/pkg/storage/fs/cephfs/connections.go @@ -63,11 +63,10 @@ func newCache() (c *connections, err error) { MaxCost: usrLimit, BufferItems: 64, OnEvict: func(item *ristretto.Item) { - if v, ok := item.Value.(*cacheVal); ok { - v.perm.Destroy() - _ = v.mount.Unmount() - _ = v.mount.Release() - } + v := item.Value.(cacheVal) + v.perm.Destroy() + _ = v.mount.Unmount() + _ = v.mount.Release() }, }) if err != nil { @@ -213,7 +212,7 @@ func newConn(user *User) *cacheVal { return destroyCephConn(mount, perm) } - if user != nil && !user.fs.conf.DisableHome { + if user != nil { if err = mount.ChangeDir(user.fs.conf.Root); err != nil { return destroyCephConn(mount, perm) } diff --git a/pkg/storage/fs/cephfs/upload.go b/pkg/storage/fs/cephfs/upload.go index 2f330494a1..0f340e7515 100644 --- a/pkg/storage/fs/cephfs/upload.go +++ b/pkg/storage/fs/cephfs/upload.go @@ -22,19 +22,35 @@ package cephfs import ( + "bytes" "context" + "encoding/json" "io" "os" + "path/filepath" + cephfs2 "github.com/ceph/go-ceph/cephfs" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/appctx" + ctx2 "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/utils" + "github.com/google/uuid" "github.com/pkg/errors" + tusd "github.com/tus/tusd/pkg/handler" ) func (fs *cephfs) Upload(ctx context.Context, ref *provider.Reference, r io.ReadCloser) error { user := fs.makeUser(ctx) - p := ref.GetPath() + upload, err := fs.GetUpload(ctx, ref.GetPath()) + if err != nil { + return errors.Wrap(err, "cephfs: error retrieving upload") + } + + uploadInfo := upload.(*fileUpload) + p := uploadInfo.info.Storage["InternalDestination"] ok, err := IsChunked(p) if err != nil { return errors.Wrap(err, "cephfs: error checking path") @@ -46,8 +62,13 @@ func (fs *cephfs) Upload(ctx context.Context, ref *provider.Reference, r io.Read return err } if p == "" { + if err = uploadInfo.Terminate(ctx); err != nil { + return errors.Wrap(err, "cephfs: error removing auxiliary files") + } return errtypes.PartialContent(ref.String()) } + uploadInfo.info.Storage["InternalDestination"] = p + user.op(func(cv *cacheVal) { r, err = cv.mount.Open(assembledFile, os.O_RDONLY, 0) }) @@ -60,33 +81,318 @@ func (fs *cephfs) Upload(ctx context.Context, ref *provider.Reference, r io.Read }) } - var file io.WriteCloser + if _, err := uploadInfo.WriteChunk(ctx, 0, r); err != nil { + return errors.Wrap(err, "cephfs: error writing to binary file") + } + + return uploadInfo.FinishUpload(ctx) +} + +func (fs *cephfs) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) { + user := fs.makeUser(ctx) + np, err := user.resolveRef(ref) + if err != nil { + return nil, errors.Wrap(err, "cephfs: error resolving reference") + } + + info := tusd.FileInfo{ + MetaData: tusd.MetaData{ + "filename": filepath.Base(np), + "dir": filepath.Dir(np), + }, + Size: uploadLength, + } + + if metadata != nil { + if metadata["mtime"] != "" { + info.MetaData["mtime"] = metadata["mtime"] + } + if _, ok := metadata["sizedeferred"]; ok { + info.SizeIsDeferred = true + } + } + + upload, err := fs.NewUpload(ctx, info) + if err != nil { + return nil, err + } + + info, _ = upload.GetInfo(ctx) + + return map[string]string{ + "simple": info.ID, + "tus": info.ID, + }, nil +} + +// UseIn tells the tus upload middleware which extensions it supports. +func (fs *cephfs) UseIn(composer *tusd.StoreComposer) { + composer.UseCore(fs) + composer.UseTerminater(fs) +} + +func (fs *cephfs) NewUpload(ctx context.Context, info tusd.FileInfo) (upload tusd.Upload, err error) { + log := appctx.GetLogger(ctx) + log.Debug().Interface("info", info).Msg("cephfs: NewUpload") + + user := fs.makeUser(ctx) + + fn := info.MetaData["filename"] + if fn == "" { + return nil, errors.New("cephfs: missing filename in metadata") + } + info.MetaData["filename"] = filepath.Clean(info.MetaData["filename"]) + + dir := info.MetaData["dir"] + if dir == "" { + return nil, errors.New("cephfs: missing dir in metadata") + } + info.MetaData["dir"] = filepath.Clean(info.MetaData["dir"]) + + np := filepath.Join(info.MetaData["dir"], info.MetaData["filename"]) + + info.ID = uuid.New().String() + + binPath := fs.getUploadPath(info.ID) + + info.Storage = map[string]string{ + "Type": "Cephfs", + "BinPath": binPath, + "InternalDestination": np, + + "Idp": user.Id.Idp, + "UserId": user.Id.OpaqueId, + "UserName": user.Username, + "UserType": utils.UserTypeToString(user.Id.Type), + + "LogLevel": log.GetLevel().String(), + } + + // Create binary file with no content user.op(func(cv *cacheVal) { - file, err = cv.mount.Open(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fs.conf.FilePerms) + var f *cephfs2.File + defer closeFile(f) + f, err = cv.mount.Open(binPath, os.O_CREATE|os.O_WRONLY, fs.conf.FilePerms) if err != nil { - err = errors.Wrap(err, "cephfs: error opening binary file") return } - defer file.Close() + }) + //TODO: if we get two same upload ids, the second one can't upload at all + if err != nil { + return + } - _, err = io.Copy(file, r) - if err != nil { - err = errors.Wrap(err, "cephfs: error writing to binary file") + upload = &fileUpload{ + info: info, + binPath: binPath, + infoPath: binPath + ".info", + fs: fs, + ctx: ctx, + } + + // writeInfo creates the file by itself if necessary + err = upload.(*fileUpload).writeInfo() + + return +} + +func (fs *cephfs) getUploadPath(uploadID string) string { + return filepath.Join(fs.conf.UploadFolder, uploadID) +} + +// GetUpload returns the Upload for the given upload id +func (fs *cephfs) GetUpload(ctx context.Context, id string) (fup tusd.Upload, err error) { + binPath := fs.getUploadPath(id) + info := tusd.FileInfo{} + if err != nil { + return nil, errtypes.NotFound("bin path for upload " + id + " not found") + } + infoPath := binPath + ".info" + + var data bytes.Buffer + f, err := fs.adminConn.adminMount.Open(infoPath, os.O_RDONLY, 0) + if err != nil { + return + } + _, err = io.Copy(&data, f) + if err != nil { + return + } + if err = json.Unmarshal(data.Bytes(), &info); err != nil { + return + } + + u := &userpb.User{ + Id: &userpb.UserId{ + Idp: info.Storage["Idp"], + OpaqueId: info.Storage["UserId"], + }, + Username: info.Storage["UserName"], + } + ctx = ctx2.ContextSetUser(ctx, u) + user := fs.makeUser(ctx) + + var stat Statx + user.op(func(cv *cacheVal) { + stat, err = cv.mount.Statx(binPath, cephfs2.StatxSize, 0) + }) + if err != nil { + return + } + info.Offset = int64(stat.Size) + + return &fileUpload{ + info: info, + binPath: binPath, + infoPath: infoPath, + fs: fs, + ctx: ctx, + }, nil +} + +type fileUpload struct { + // info stores the current information about the upload + info tusd.FileInfo + // infoPath is the path to the .info file + infoPath string + // binPath is the path to the binary file (which has no extension) + binPath string + // only fs knows how to handle metadata and versions + fs *cephfs + // a context with a user + ctx context.Context +} + +// GetInfo returns the FileInfo +func (upload *fileUpload) GetInfo(ctx context.Context) (tusd.FileInfo, error) { + return upload.info, nil +} + +// GetReader returns an io.Reader for the upload +func (upload *fileUpload) GetReader(ctx context.Context) (file io.Reader, err error) { + user := upload.fs.makeUser(upload.ctx) + user.op(func(cv *cacheVal) { + file, err = cv.mount.Open(upload.binPath, os.O_RDONLY, 0) + }) + return +} + +// WriteChunk writes the stream from the reader to the given offset of the upload +func (upload *fileUpload) WriteChunk(ctx context.Context, offset int64, src io.Reader) (n int64, err error) { + var file io.WriteCloser + user := upload.fs.makeUser(upload.ctx) + user.op(func(cv *cacheVal) { + file, err = cv.mount.Open(upload.binPath, os.O_WRONLY|os.O_APPEND, 0) + }) + if err != nil { + return 0, err + } + defer file.Close() + + n, err = io.Copy(file, src) + + // If the HTTP PATCH request gets interrupted in the middle (e.g. because + // the user wants to pause the upload), Go's net/http returns an io.ErrUnexpectedEOF. + // However, for OwnCloudStore it's not important whether the stream has ended + // on purpose or accidentally. + if err != nil { + if err != io.ErrUnexpectedEOF { + return n, err + } + } + + upload.info.Offset += n + err = upload.writeInfo() + + return n, err +} + +// writeInfo updates the entire information. Everything will be overwritten. +func (upload *fileUpload) writeInfo() error { + data, err := json.Marshal(upload.info) + + if err != nil { + return err + } + user := upload.fs.makeUser(upload.ctx) + user.op(func(cv *cacheVal) { + var file io.WriteCloser + if file, err = cv.mount.Open(upload.infoPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, upload.fs.conf.FilePerms); err != nil { return } + defer file.Close() + + _, err = io.Copy(file, bytes.NewReader(data)) }) return err } -func (fs *cephfs) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) { - user := fs.makeUser(ctx) - np, err := user.resolveRef(ref) +// FinishUpload finishes an upload and moves the file to the internal destination +func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) { + + np := upload.info.Storage["InternalDestination"] + + // TODO check etag with If-Match header + // if destination exists + // if _, err := os.Stat(np); err == nil { + // the local storage does not store metadata + // the fileid is based on the path, so no we do not need to copy it to the new file + // the local storage does not track revisions + // } + + // if destination exists + // if _, err := os.Stat(np); err == nil { + // create revision + // if err := upload.fs.archiveRevision(upload.ctx, np); err != nil { + // return err + // } + // } + + user := upload.fs.makeUser(upload.ctx) + log := appctx.GetLogger(ctx) + + user.op(func(cv *cacheVal) { + err = cv.mount.Rename(upload.binPath, np) + }) if err != nil { - return nil, errors.Wrap(err, "cephfs: error resolving reference") + return errors.Wrap(err, upload.binPath) } - return map[string]string{ - "simple": np, - }, nil + // only delete the upload if it was successfully written to the fs + user.op(func(cv *cacheVal) { + err = cv.mount.Unlink(upload.infoPath) + }) + if err != nil { + if err.Error() != errNotFound { + log.Err(err).Interface("info", upload.info).Msg("cephfs: could not delete upload metadata") + } + } + + // TODO: set mtime if specified in metadata + + return +} + +// To implement the termination extension as specified in https://tus.io/protocols/resumable-upload.html#termination +// - the storage needs to implement AsTerminatableUpload +// - the upload needs to implement Terminate + +// AsTerminatableUpload returns a a TerminatableUpload +func (fs *cephfs) AsTerminatableUpload(upload tusd.Upload) tusd.TerminatableUpload { + return upload.(*fileUpload) +} + +// Terminate terminates the upload +func (upload *fileUpload) Terminate(ctx context.Context) (err error) { + user := upload.fs.makeUser(upload.ctx) + + user.op(func(cv *cacheVal) { + if err = cv.mount.Unlink(upload.infoPath); err != nil { + return + } + err = cv.mount.Unlink(upload.binPath) + }) + + return } diff --git a/pkg/storage/fs/cephfs/user.go b/pkg/storage/fs/cephfs/user.go index cb016fbc99..aa5a2723b2 100644 --- a/pkg/storage/fs/cephfs/user.go +++ b/pkg/storage/fs/cephfs/user.go @@ -35,7 +35,7 @@ import ( 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" - ctx2 "github.com/cs3org/reva/pkg/ctx" + ctx2 "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/mime" "github.com/cs3org/reva/pkg/storage/utils/templates" "github.com/pkg/errors" @@ -105,9 +105,6 @@ func (user *User) fileAsResourceInfo(cv *cacheVal, path string, stat *cephfs2.Ce _type = provider.ResourceType_RESOURCE_TYPE_CONTAINER if buf, err = cv.mount.GetXattr(path, "ceph.dir.rbytes"); err == nil { size, err = strconv.ParseUint(string(buf), 10, 64) - } else if err.Error() == errPermissionDenied { - // Ignore permission denied errors so ListFolder does not fail because of them. - err = nil } case syscall.S_IFLNK: _type = provider.ResourceType_RESOURCE_TYPE_SYMLINK @@ -119,6 +116,10 @@ func (user *User) fileAsResourceInfo(cv *cacheVal, path string, stat *cephfs2.Ce return nil, errors.New("cephfs: unknown entry type") } + if err != nil { + return + } + var xattrs []string keys := make(map[string]bool, len(mdKeys)) for _, key := range mdKeys { diff --git a/pkg/storage/fs/loader/loader.go b/pkg/storage/fs/loader/loader.go index 370ba393d4..488d5a8fe8 100644 --- a/pkg/storage/fs/loader/loader.go +++ b/pkg/storage/fs/loader/loader.go @@ -31,6 +31,5 @@ import ( _ "github.com/cs3org/reva/pkg/storage/fs/local" _ "github.com/cs3org/reva/pkg/storage/fs/localhome" _ "github.com/cs3org/reva/pkg/storage/fs/nextcloud" - _ "github.com/cs3org/reva/pkg/storage/fs/s3" // Add your own here. ) diff --git a/pkg/storage/fs/nextcloud/nextcloud.go b/pkg/storage/fs/nextcloud/nextcloud.go index 58c6a65508..e234a17d5e 100644 --- a/pkg/storage/fs/nextcloud/nextcloud.go +++ b/pkg/storage/fs/nextcloud/nextcloud.go @@ -33,7 +33,7 @@ import ( typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage" "github.com/cs3org/reva/pkg/storage/fs/registry" @@ -131,7 +131,7 @@ func NewStorageDriver(c *StorageDriverConfig) (*StorageDriver, error) { } func getUser(ctx context.Context) (*user.User, error) { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired(""), "nextcloud storage driver: error getting user from ctx") return nil, err diff --git a/pkg/storage/fs/nextcloud/nextcloud_test.go b/pkg/storage/fs/nextcloud/nextcloud_test.go index f388e8da27..8faac01079 100644 --- a/pkg/storage/fs/nextcloud/nextcloud_test.go +++ b/pkg/storage/fs/nextcloud/nextcloud_test.go @@ -30,8 +30,9 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/storage/fs/nextcloud" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" . "github.com/onsi/ginkgo" @@ -103,9 +104,9 @@ var _ = Describe("Nextcloud", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) }) AfterEach(func() { diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go deleted file mode 100644 index f07d5c74b5..0000000000 --- a/pkg/storage/fs/s3/s3.go +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright 2018-2023 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package s3 - -import ( - "context" - "fmt" - "io" - "net/http" - "net/url" - "path" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3manager" - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - "github.com/cs3org/reva/pkg/appctx" - "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/mime" - "github.com/cs3org/reva/pkg/storage" - "github.com/cs3org/reva/pkg/storage/fs/registry" - "github.com/cs3org/reva/pkg/utils/cfg" - "github.com/pkg/errors" -) - -func init() { - registry.Register("s3", New) -} - -type config struct { - Region string `mapstructure:"region"` - AccessKey string `mapstructure:"access_key"` - SecretKey string `mapstructure:"secret_key"` - Endpoint string `mapstructure:"endpoint"` - Bucket string `mapstructure:"bucket"` - Prefix string `mapstructure:"prefix"` -} - -// New returns an implementation to of the storage.FS interface that talk to -// a s3 api. -func New(ctx context.Context, m map[string]interface{}) (storage.FS, error) { - var c config - if err := cfg.Decode(m, &c); err != nil { - return nil, err - } - - awsConfig := aws.NewConfig(). - WithHTTPClient(http.DefaultClient). - WithMaxRetries(aws.UseServiceDefaultRetries). - WithLogger(aws.NewDefaultLogger()). - WithLogLevel(aws.LogOff). - WithSleepDelay(time.Sleep). - WithCredentials(credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, "")). - WithEndpoint(c.Endpoint). - WithS3ForcePathStyle(true). - WithDisableSSL(true) - - if c.Region != "" { - awsConfig.WithRegion(c.Region) - } else { - awsConfig.WithRegion("us-east-1") - } - - sess, err := session.NewSession(awsConfig) - if err != nil { - return nil, err - } - if sess == nil { - return nil, errors.New("creating the S3 session") - } - - s3Client := s3.New(sess) - - return &s3FS{client: s3Client, config: &c}, nil -} - -func (fs *s3FS) Shutdown(ctx context.Context) error { - return nil -} - -func (fs *s3FS) addRoot(p string) string { - np := path.Join(fs.config.Prefix, p) - return np -} - -func (fs *s3FS) resolve(ctx context.Context, ref *provider.Reference) (string, error) { - if strings.HasPrefix(ref.Path, "/") { - return fs.addRoot(ref.GetPath()), nil - } - - if ref.ResourceId != nil && ref.ResourceId.OpaqueId != "" { - fn := path.Join("/", strings.TrimPrefix(ref.ResourceId.OpaqueId, "fileid-")) - fn = fs.addRoot(fn) - return fn, nil - } - - // reference is invalid - return "", fmt.Errorf("invalid reference %+v", ref) -} - -func (fs *s3FS) removeRoot(np string) string { - p := strings.TrimPrefix(np, fs.config.Prefix) - if p == "" { - p = "/" - } - return p -} - -type s3FS struct { - client *s3.S3 - config *config -} - -// permissionSet returns the permission set for the current user. -func (fs *s3FS) permissionSet(ctx context.Context) *provider.ResourcePermissions { - // TODO fix permissions for share recipients by traversing reading acls up to the root? cache acls for the parent node and reuse it - return &provider.ResourcePermissions{ - // owner has all permissions - AddGrant: true, - CreateContainer: true, - Delete: true, - GetPath: true, - GetQuota: true, - InitiateFileDownload: true, - InitiateFileUpload: true, - ListContainer: true, - ListFileVersions: true, - ListGrants: true, - ListRecycle: true, - Move: true, - PurgeRecycle: true, - RemoveGrant: true, - RestoreFileVersion: true, - RestoreRecycleItem: true, - Stat: true, - UpdateGrant: true, - } -} - -func (fs *s3FS) normalizeObject(ctx context.Context, o *s3.Object, fn string) *provider.ResourceInfo { - fn = fs.removeRoot(path.Join("/", fn)) - isDir := strings.HasSuffix(*o.Key, "/") - md := &provider.ResourceInfo{ - Id: &provider.ResourceId{ - OpaqueId: "fileid-" + strings.TrimPrefix(fn, "/"), - }, - Path: fn, - Type: getResourceType(isDir), - Etag: *o.ETag, - MimeType: mime.Detect(isDir, fn), - PermissionSet: fs.permissionSet(ctx), - Size: uint64(*o.Size), - Mtime: &types.Timestamp{ - Seconds: uint64(o.LastModified.Unix()), - }, - } - appctx.GetLogger(ctx).Debug(). - Interface("object", o). - Interface("metadata", md). - Msg("normalized Object") - return md -} - -func getResourceType(isDir bool) provider.ResourceType { - if isDir { - return provider.ResourceType_RESOURCE_TYPE_CONTAINER - } - return provider.ResourceType_RESOURCE_TYPE_CONTAINER -} - -func (fs *s3FS) normalizeHead(ctx context.Context, o *s3.HeadObjectOutput, fn string) *provider.ResourceInfo { - fn = fs.removeRoot(path.Join("/", fn)) - isDir := strings.HasSuffix(fn, "/") - md := &provider.ResourceInfo{ - Id: &provider.ResourceId{OpaqueId: "fileid-" + strings.TrimPrefix(fn, "/")}, - Path: fn, - Type: getResourceType(isDir), - Etag: *o.ETag, - MimeType: mime.Detect(isDir, fn), - PermissionSet: fs.permissionSet(ctx), - Size: uint64(*o.ContentLength), - Mtime: &types.Timestamp{ - Seconds: uint64(o.LastModified.Unix()), - }, - } - appctx.GetLogger(ctx).Debug(). - Interface("head", o). - Interface("metadata", md). - Msg("normalized Head") - return md -} -func (fs *s3FS) normalizeCommonPrefix(ctx context.Context, p *s3.CommonPrefix) *provider.ResourceInfo { - fn := fs.removeRoot(path.Join("/", *p.Prefix)) - md := &provider.ResourceInfo{ - Id: &provider.ResourceId{OpaqueId: "fileid-" + strings.TrimPrefix(fn, "/")}, - Path: fn, - Type: getResourceType(true), - Etag: "TODO(labkode)", - MimeType: mime.Detect(true, fn), - PermissionSet: fs.permissionSet(ctx), - Size: 0, - Mtime: &types.Timestamp{ - Seconds: 0, - }, - } - appctx.GetLogger(ctx).Debug(). - Interface("prefix", p). - Interface("metadata", md). - Msg("normalized CommonPrefix") - return md -} - -// GetPathByID returns the path pointed by the file id -// In this implementation the file id is that path of the file without the first slash -// thus the file id always points to the filename. -func (fs *s3FS) GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) { - return path.Join("/", strings.TrimPrefix(id.OpaqueId, "fileid-")), nil -} - -func (fs *s3FS) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) { - return nil, errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) GetQuota(ctx context.Context, ref *provider.Reference) (uint64, uint64, error) { - return 0, 0, nil -} - -func (fs *s3FS) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error { - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error { - return errtypes.NotSupported("s3: operation not supported") -} - -// GetLock returns an existing lock on the given reference. -func (fs *s3FS) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) { - return nil, errtypes.NotSupported("unimplemented") -} - -// SetLock puts a lock on the given reference. -func (fs *s3FS) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { - return errtypes.NotSupported("unimplemented") -} - -// RefreshLock refreshes an existing lock on the given reference. -func (fs *s3FS) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { - return errtypes.NotSupported("unimplemented") -} - -// Unlock removes an existing lock from the given reference. -func (fs *s3FS) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { - return errtypes.NotSupported("unimplemented") -} - -func (fs *s3FS) CreateReference(ctx context.Context, path string, targetURI *url.URL) error { - // TODO(jfd):implement - return errtypes.NotSupported("s3: operation not supported") -} - -func (fs *s3FS) GetHome(ctx context.Context) (string, error) { - return "", errtypes.NotSupported("eos: not supported") -} - -func (fs *s3FS) CreateHome(ctx context.Context) error { - return errtypes.NotSupported("s3fs: not supported") -} - -func (fs *s3FS) CreateDir(ctx context.Context, ref *provider.Reference) error { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, ref) - if err != nil { - return nil - } - - fn = fs.addRoot(fn) + "/" // append / to indicate folder // TODO only if fn does not end in / - - input := &s3.PutObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - ContentType: aws.String("application/octet-stream"), - ContentLength: aws.Int64(0), - } - - result, err := fs.client.PutObject(input) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - if aerr.Code() == s3.ErrCodeNoSuchBucket { - return errtypes.NotFound(ref.Path) - } - } - // FIXME we also need already exists error, webdav expects 405 MethodNotAllowed - return errors.Wrap(err, "s3fs: error creating dir "+ref.Path) - } - - log.Debug().Interface("result", result).Send() // todo cache etag? - return nil -} - -// TouchFile as defined in the storage.FS interface. -func (fs *s3FS) TouchFile(ctx context.Context, ref *provider.Reference) error { - return fmt.Errorf("unimplemented: TouchFile") -} - -func (fs *s3FS) Delete(ctx context.Context, ref *provider.Reference) error { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, ref) - if err != nil { - return errors.Wrap(err, "error resolving ref") - } - - // first we need to find out if fn is a dir or a file - - _, err = fs.client.HeadObject(&s3.HeadObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - }) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return errtypes.NotFound(fn) - } - } - // it might be a directory, so we can batch delete the prefix + / - iter := s3manager.NewDeleteListIterator(fs.client, &s3.ListObjectsInput{ - Bucket: aws.String(fs.config.Bucket), - Prefix: aws.String(fn + "/"), - }) - batcher := s3manager.NewBatchDeleteWithClient(fs.client) - if err := batcher.Delete(aws.BackgroundContext(), iter); err != nil { - return err - } - // ok, we are done - return nil - } - - // we found an object, let's get rid of it - result, err := fs.client.DeleteObject(&s3.DeleteObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - }) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return errtypes.NotFound(fn) - } - } - return errors.Wrap(err, "s3fs: error deleting "+fn) - } - - log.Debug().Interface("result", result).Send() - return nil -} - -// CreateStorageSpace creates a storage space. -func (fs *s3FS) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { - return nil, fmt.Errorf("unimplemented: CreateStorageSpace") -} - -func (fs *s3FS) moveObject(ctx context.Context, oldKey string, newKey string) error { - // Copy - // TODO double check CopyObject can deal with >5GB files. - // Docs say we need to use multipart upload: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html - _, err := fs.client.CopyObject(&s3.CopyObjectInput{ - Bucket: aws.String(fs.config.Bucket), - CopySource: aws.String("/" + fs.config.Bucket + oldKey), - Key: aws.String(newKey), - }) - if aerr, ok := err.(awserr.Error); ok { - if aerr.Code() == s3.ErrCodeNoSuchBucket { - return errtypes.NotFound(oldKey) - } - return err - } - // TODO cache etag and mtime? - - // Delete - _, err = fs.client.DeleteObject(&s3.DeleteObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(oldKey), - }) - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return errtypes.NotFound(oldKey) - } - return err - } - return nil -} - -func (fs *s3FS) Move(ctx context.Context, oldRef, newRef *provider.Reference) error { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, oldRef) - if err != nil { - return errors.Wrap(err, "error resolving ref") - } - - newName, err := fs.resolve(ctx, newRef) - if err != nil { - return errors.Wrap(err, "error resolving ref") - } - - // first we need to find out if fn is a dir or a file - - _, err = fs.client.HeadObject(&s3.HeadObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - }) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return errtypes.NotFound(fn) - } - } - - // move directory - input := &s3.ListObjectsV2Input{ - Bucket: aws.String(fs.config.Bucket), - Prefix: aws.String(fn + "/"), - } - isTruncated := true - - for isTruncated { - output, err := fs.client.ListObjectsV2(input) - if err != nil { - return errors.Wrap(err, "s3FS: error listing "+fn) - } - - for _, o := range output.Contents { - log.Debug(). - Interface("object", *o). - Str("fn", fn). - Msg("found Object") - - err := fs.moveObject(ctx, *o.Key, strings.Replace(*o.Key, fn+"/", newName+"/", 1)) - if err != nil { - return err - } - } - - input.ContinuationToken = output.NextContinuationToken - isTruncated = *output.IsTruncated - } - // ok, we are done - return nil - } - - // move single object - err = fs.moveObject(ctx, fn, newName) - if err != nil { - return err - } - return nil -} - -func (fs *s3FS) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, ref) - if err != nil { - return nil, errors.Wrap(err, "error resolving ref") - } - - // first try a head, works for files - log.Debug(). - Str("fn", fn). - Msg("trying HEAD") - - input := &s3.HeadObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - } - output, err := fs.client.HeadObject(input) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return nil, errtypes.NotFound(fn) - } - } - log.Debug(). - Str("fn", fn). - Msg("trying to list prefix") - // try by listing parent to find directory - input := &s3.ListObjectsV2Input{ - Bucket: aws.String(fs.config.Bucket), - Prefix: aws.String(fn), - Delimiter: aws.String("/"), // limit to a single directory - } - isTruncated := true - - for isTruncated { - output, err := fs.client.ListObjectsV2(input) - if err != nil { - return nil, errors.Wrap(err, "s3FS: error listing "+fn) - } - - for i := range output.CommonPrefixes { - log.Debug(). - Interface("object", output.CommonPrefixes[i]). - Str("fn", fn). - Msg("found CommonPrefix") - if *output.CommonPrefixes[i].Prefix == fn+"/" { - return fs.normalizeCommonPrefix(ctx, output.CommonPrefixes[i]), nil - } - } - - input.ContinuationToken = output.NextContinuationToken - isTruncated = *output.IsTruncated - } - return nil, errtypes.NotFound(fn) - } - - return fs.normalizeHead(ctx, output, fn), nil -} - -func (fs *s3FS) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) { - fn, err := fs.resolve(ctx, ref) - if err != nil { - return nil, errors.Wrap(err, "error resolving ref") - } - - input := &s3.ListObjectsV2Input{ - Bucket: aws.String(fs.config.Bucket), - Prefix: aws.String(fn + "/"), - Delimiter: aws.String("/"), // limit to a single directory - } - isTruncated := true - - finfos := []*provider.ResourceInfo{} - - for isTruncated { - output, err := fs.client.ListObjectsV2(input) - if err != nil { - return nil, errors.Wrap(err, "s3FS: error listing "+fn) - } - - for i := range output.CommonPrefixes { - finfos = append(finfos, fs.normalizeCommonPrefix(ctx, output.CommonPrefixes[i])) - } - - for i := range output.Contents { - finfos = append(finfos, fs.normalizeObject(ctx, output.Contents[i], *output.Contents[i].Key)) - } - - input.ContinuationToken = output.NextContinuationToken - isTruncated = *output.IsTruncated - } - // TODO sort fileinfos? - return finfos, nil -} - -func (fs *s3FS) Upload(ctx context.Context, ref *provider.Reference, r io.ReadCloser) error { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, ref) - if err != nil { - return errors.Wrap(err, "error resolving ref") - } - - upParams := &s3manager.UploadInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - Body: r, - } - uploader := s3manager.NewUploaderWithClient(fs.client) - result, err := uploader.Upload(upParams) - - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - if aerr.Code() == s3.ErrCodeNoSuchBucket { - return errtypes.NotFound(fn) - } - } - return errors.Wrap(err, "s3fs: error creating object "+fn) - } - - log.Debug().Interface("result", result).Send() // todo cache etag? - return nil -} - -func (fs *s3FS) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { - log := appctx.GetLogger(ctx) - - fn, err := fs.resolve(ctx, ref) - if err != nil { - return nil, errors.Wrap(err, "error resolving ref") - } - - // use GetObject instead of s3manager.Downloader: - // the result.Body is a ReadCloser, which allows streaming - // TODO double check we are not caching bytes in memory - r, err := fs.client.GetObject(&s3.GetObjectInput{ - Bucket: aws.String(fs.config.Bucket), - Key: aws.String(fn), - }) - if err != nil { - log.Error().Err(err).Send() - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - case s3.ErrCodeNoSuchKey: - return nil, errtypes.NotFound(fn) - } - } - return nil, errors.Wrap(err, "s3fs: error deleting "+fn) - } - return r.Body, nil -} - -func (fs *s3FS) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { - return nil, errtypes.NotSupported("list revisions") -} - -func (fs *s3FS) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { - return nil, errtypes.NotSupported("download revision") -} - -func (fs *s3FS) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { - return errtypes.NotSupported("restore revision") -} - -func (fs *s3FS) PurgeRecycleItem(ctx context.Context, kbasePath, key, relativePath string) error { - return errtypes.NotSupported("purge recycle item") -} - -func (fs *s3FS) EmptyRecycle(ctx context.Context) error { - return errtypes.NotSupported("empty recycle") -} - -func (fs *s3FS) ListRecycle(ctx context.Context, basePath, key, relativePath string) ([]*provider.RecycleItem, error) { - return nil, errtypes.NotSupported("list recycle") -} - -func (fs *s3FS) RestoreRecycleItem(ctx context.Context, basePath, key, relativePath string, restoreRef *provider.Reference) error { - return errtypes.NotSupported("restore recycle") -} - -func (fs *s3FS) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) { - return nil, errtypes.NotSupported("list storage spaces") -} - -// UpdateStorageSpace updates a storage space. -func (fs *s3FS) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { - return nil, errtypes.NotSupported("update storage space") -} diff --git a/pkg/storage/registry/dynamic/dynamic_test.go b/pkg/storage/registry/dynamic/dynamic_test.go index 3444441222..0336481d41 100644 --- a/pkg/storage/registry/dynamic/dynamic_test.go +++ b/pkg/storage/registry/dynamic/dynamic_test.go @@ -26,7 +26,7 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registryv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage" @@ -53,17 +53,17 @@ var _ = Describe("Dynamic storage provider", func() { s *server.Server m sync.Mutex - ctxAlice = ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + ctxAlice = appctx.ContextSetUser(context.Background(), &userpb.User{ Id: &userpb.UserId{ OpaqueId: "alice", }, }) - ctxBob = ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + ctxBob = appctx.ContextSetUser(context.Background(), &userpb.User{ Id: &userpb.UserId{ OpaqueId: "bob", }, }) - ctxCharlie = ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + ctxCharlie = appctx.ContextSetUser(context.Background(), &userpb.User{ Id: &userpb.UserId{ OpaqueId: "charlie", }, diff --git a/pkg/storage/registry/dynamic/rewriter/userrewriter.go b/pkg/storage/registry/dynamic/rewriter/userrewriter.go index 1be412051e..5e21ec78ae 100644 --- a/pkg/storage/registry/dynamic/rewriter/userrewriter.go +++ b/pkg/storage/registry/dynamic/rewriter/userrewriter.go @@ -24,7 +24,7 @@ import ( "errors" "strings" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/storage/utils/templates" ) @@ -51,7 +51,7 @@ func (ur UserRewriter) GetAlias(ctx context.Context, route string) string { return route } - if u, ok := ctxpkg.ContextGetUser(ctx); ok { + if u, ok := appctx.ContextGetUser(ctx); ok { return templates.WithUser(u, tpl) } diff --git a/pkg/storage/registry/static/static.go b/pkg/storage/registry/static/static.go index cef0ec69b1..02d2889a37 100644 --- a/pkg/storage/registry/static/static.go +++ b/pkg/storage/registry/static/static.go @@ -26,7 +26,8 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registrypb "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage" @@ -87,7 +88,7 @@ type reg struct { func getProviderAddr(ctx context.Context, r rule) string { addr := r.Address if addr == "" { - if u, ok := ctxpkg.ContextGetUser(ctx); ok { + if u, ok := appctx.ContextGetUser(ctx); ok { layout := templates.WithUser(u, r.Mapping) for k, v := range r.Aliases { if match, _ := regexp.MatchString("^"+k, layout); match { diff --git a/pkg/storage/registry/static/static_test.go b/pkg/storage/registry/static/static_test.go index 2f6639511e..6d5ffabeeb 100644 --- a/pkg/storage/registry/static/static_test.go +++ b/pkg/storage/registry/static/static_test.go @@ -24,7 +24,8 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registrypb "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/storage/registry/static" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -81,12 +82,12 @@ var _ = Describe("Static", func() { }) Expect(err).ToNot(HaveOccurred()) - ctxAlice := ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + ctxAlice := appctx.ContextSetUser(context.Background(), &userpb.User{ Id: &userpb.UserId{ OpaqueId: "alice", }, }) - ctxRobert := ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + ctxRobert := appctx.ContextSetUser(context.Background(), &userpb.User{ Id: &userpb.UserId{ OpaqueId: "robert", }, diff --git a/pkg/storage/utils/downloader/downloader.go b/pkg/storage/utils/downloader/downloader.go index badccd1201..4e1efe81c1 100644 --- a/pkg/storage/utils/downloader/downloader.go +++ b/pkg/storage/utils/downloader/downloader.go @@ -30,7 +30,7 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/errtypes" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" ) // Downloader is the interface implemented by the objects that are able to @@ -41,14 +41,14 @@ type Downloader interface { type revaDownloader struct { gtw gateway.GatewayAPIClient - httpClient *http.Client + httpClient *httpclient.Client } // NewDownloader creates a Downloader from the reva gateway. -func NewDownloader(gtw gateway.GatewayAPIClient, options ...rhttp.Option) Downloader { +func NewDownloader(gtw gateway.GatewayAPIClient, hc *httpclient.Client) Downloader { return &revaDownloader{ gtw: gtw, - httpClient: rhttp.GetHTTPClient(options...), + httpClient: hc, } } @@ -92,7 +92,7 @@ func (r *revaDownloader) Download(ctx context.Context, path, versionKey string) return nil, err } - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, p.DownloadEndpoint, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, p.DownloadEndpoint, nil) if err != nil { return nil, err } diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index bfe39c4807..b29ce5c76e 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -43,7 +43,7 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/eosclient" "github.com/cs3org/reva/pkg/eosclient/eosbinary" "github.com/cs3org/reva/pkg/eosclient/eosgrpc" @@ -271,7 +271,7 @@ func (fs *eosfs) Shutdown(ctx context.Context) error { } func getUser(ctx context.Context) (*userpb.User, error) { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired(""), "eosfs: error getting user from ctx") return nil, err @@ -842,7 +842,7 @@ func (fs *eosfs) getUserFromID(ctx context.Context, userID *userpb.UserId) (*use } func (fs *eosfs) userHasWriteAccess(ctx context.Context, user *userpb.User, ref *provider.Reference) (bool, error) { - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetUser(ctx, user) resInfo, err := fs.GetMD(ctx, ref, nil) if err != nil { return false, err @@ -859,7 +859,7 @@ func (fs *eosfs) userIDHasWriteAccess(ctx context.Context, userID *userpb.UserId } func (fs *eosfs) userHasReadAccess(ctx context.Context, user *userpb.User, ref *provider.Reference) (bool, error) { - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetUser(ctx, user) resInfo, err := fs.GetMD(ctx, ref, nil) if err != nil { return false, err @@ -1553,7 +1553,7 @@ func (fs *eosfs) CreateHome(ctx context.Context) error { } func (fs *eosfs) runPostCreateHomeHook(ctx context.Context) error { - user := ctxpkg.ContextMustGetUser(ctx) + user := appctx.ContextMustGetUser(ctx) return exec.Command(fs.conf.OnPostCreateHomeHook, user.Username).Run() } @@ -2091,7 +2091,7 @@ func (fs *eosfs) convertToFileReference(ctx context.Context, eosFileInfo *eoscli // permissionSet returns the permission set for the current user. func (fs *eosfs) permissionSet(ctx context.Context, eosFileInfo *eosclient.FileInfo, owner *userpb.UserId) *provider.ResourcePermissions { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok || u.Id == nil { return &provider.ResourcePermissions{ // no permissions diff --git a/pkg/storage/utils/eosfs/eosfs_test.go b/pkg/storage/utils/eosfs/eosfs_test.go index 9abd13a266..2f89638d69 100644 --- a/pkg/storage/utils/eosfs/eosfs_test.go +++ b/pkg/storage/utils/eosfs/eosfs_test.go @@ -30,7 +30,8 @@ import ( userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/eosclient" "github.com/gdexlab/go-render/render" "github.com/thanhpk/randstr" @@ -258,7 +259,7 @@ func TestAddGrant(t *testing.T) { for _, test := range testCases { t.Run(test.description, func(t *testing.T) { - ctx := ctxpkg.ContextSetUser(context.TODO(), &userv1beta1.User{ + ctx := appctx.ContextSetUser(context.TODO(), &userv1beta1.User{ UidNumber: 138406, GidNumber: 2763, }) diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index 22dcaecaeb..fedc2353af 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -35,7 +35,8 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/mime" "github.com/cs3org/reva/pkg/storage" @@ -152,7 +153,7 @@ func (fs *localfs) resolve(ctx context.Context, ref *provider.Reference) (p stri } func getUser(ctx context.Context) (*userpb.User, error) { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired(""), "local: error getting user from ctx") return nil, err @@ -272,7 +273,7 @@ func (fs *localfs) isShareFolderChild(ctx context.Context, p string) bool { // permissionSet returns the permission set for the current user. func (fs *localfs) permissionSet(ctx context.Context, owner *userpb.UserId) *provider.ResourcePermissions { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { return &provider.ResourcePermissions{ // no permissions diff --git a/pkg/storage/utils/localfs/upload.go b/pkg/storage/utils/localfs/upload.go index e2021250b6..f4ba06e5e3 100644 --- a/pkg/storage/utils/localfs/upload.go +++ b/pkg/storage/utils/localfs/upload.go @@ -28,7 +28,7 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/utils" @@ -159,7 +159,7 @@ func (fs *localfs) NewUpload(ctx context.Context, info tusd.FileInfo) (upload tu if err != nil { return nil, errors.Wrap(err, "localfs: error resolving upload path") } - usr := ctxpkg.ContextMustGetUser(ctx) + usr := appctx.ContextMustGetUser(ctx) info.Storage = map[string]string{ "Type": "LocalStore", "BinPath": binPath, @@ -236,7 +236,7 @@ func (fs *localfs) GetUpload(ctx context.Context, id string) (tusd.Upload, error Username: info.Storage["UserName"], } - ctx = ctxpkg.ContextSetUser(ctx, u) + ctx = appctx.ContextSetUser(ctx, u) return &fileUpload{ info: info, diff --git a/pkg/trace/trace.go b/pkg/trace/trace.go index 93aa760059..aff75a4c3d 100644 --- a/pkg/trace/trace.go +++ b/pkg/trace/trace.go @@ -19,92 +19,23 @@ package trace import ( - "fmt" - "net/url" - "strings" + "context" - "go.opentelemetry.io/otel/exporters/jaeger" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - "go.opentelemetry.io/otel/trace" + "github.com/gofrs/uuid" ) -var ( - // Propagator is the default Reva propagator. - Propagator = propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}) +type key struct{} - // Provider is the default Reva tracer provider. - Provider = trace.NewNoopTracerProvider() -) - -// SetTraceProvider sets the TracerProvider at a package level. -func SetTraceProvider(collectorEndpoint string, agentEndpoint, serviceName string) { - // default to 'reva' as service name if not set - if serviceName == "" { - serviceName = "reva" - } - - var exp *jaeger.Exporter - var err error - - if agentEndpoint != "" { - var agentHost string - var agentPort string - - agentHost, agentPort, err = parseAgentConfig(agentEndpoint) - if err != nil { - panic(err) - } - - exp, err = jaeger.New( - jaeger.WithAgentEndpoint( - jaeger.WithAgentHost(agentHost), - jaeger.WithAgentPort(agentPort), - ), - ) - if err != nil { - panic(err) - } - } - - if collectorEndpoint != "" { - exp, err = jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(collectorEndpoint))) - if err != nil { - panic(err) - } - } - - Provider = sdktrace.NewTracerProvider( - sdktrace.WithBatcher(exp), - sdktrace.WithResource(resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(serviceName), - )), - ) +func Get(ctx context.Context) (t string) { + t, _ = ctx.Value(key{}).(string) + return } -func parseAgentConfig(ae string) (string, string, error) { - u, err := url.Parse(ae) - // as per url.go: - // [...] Trying to parse a hostname and path - // without a scheme is invalid but may not necessarily return an - // error, due to parsing ambiguities. - if err == nil && u.Hostname() != "" && u.Port() != "" { - return u.Hostname(), u.Port(), nil - } - - p := strings.Split(ae, ":") - if len(p) != 2 { - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - } +func Generate() string { + return uuid.Must(uuid.NewV4()).String() +} - switch { - case p[0] == "" && p[1] == "": // case ae = ":" - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - case p[0] == "": - return "", "", fmt.Errorf(fmt.Sprintf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)) - } - return p[0], p[1], nil +// ContextSetTrace stores the trace in the context. +func Set(ctx context.Context, trace string) context.Context { + return context.WithValue(ctx, key{}, trace) } diff --git a/pkg/user/manager/nextcloud/nextcloud.go b/pkg/user/manager/nextcloud/nextcloud.go index acf385d9ff..0fbf221289 100644 --- a/pkg/user/manager/nextcloud/nextcloud.go +++ b/pkg/user/manager/nextcloud/nextcloud.go @@ -29,7 +29,6 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/pkg/appctx" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/user" "github.com/cs3org/reva/pkg/user/manager/registry" @@ -104,7 +103,7 @@ func (um *Manager) SetHTTPClient(c *http.Client) { } func getUser(ctx context.Context) (*userpb.User, error) { - u, ok := ctxpkg.ContextGetUser(ctx) + u, ok := appctx.ContextGetUser(ctx) if !ok { err := errors.Wrap(errtypes.UserRequired(""), "nextcloud user manager: error getting user from ctx") return nil, err diff --git a/pkg/user/manager/nextcloud/nextcloud_test.go b/pkg/user/manager/nextcloud/nextcloud_test.go index a9114abd68..b627aa4e17 100644 --- a/pkg/user/manager/nextcloud/nextcloud_test.go +++ b/pkg/user/manager/nextcloud/nextcloud_test.go @@ -23,8 +23,9 @@ import ( "os" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" "github.com/cs3org/reva/pkg/user/manager/nextcloud" "github.com/cs3org/reva/tests/helpers" @@ -100,9 +101,9 @@ var _ = Describe("Nextcloud", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) }) AfterEach(func() { diff --git a/tests/helpers/helpers.go b/tests/helpers/helpers.go index 7a7ab6f641..bf0d69804d 100644 --- a/tests/helpers/helpers.go +++ b/tests/helpers/helpers.go @@ -35,7 +35,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/internal/http/services/datagateway" - "github.com/cs3org/reva/pkg/rhttp" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/storage" "github.com/studio-b12/gowebdav" ) @@ -127,14 +127,14 @@ func UploadGateway(ctx context.Context, gw gatewayv1beta1.GatewayAPIClient, ref token, endpoint = p.Token, p.UploadEndpoint } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, endpoint, bytes.NewReader(content)) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, endpoint, bytes.NewReader(content)) if err != nil { return errors.Wrap(err, "error creating new request") } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) + httpRes, err := httpclient.New().Do(httpReq) if err != nil { return errors.Wrap(err, "error doing put request") } @@ -165,13 +165,13 @@ func Download(ctx context.Context, gw gatewayv1beta1.GatewayAPIClient, ref *prov token, endpoint = p.Token, p.DownloadEndpoint } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, endpoint, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) if err != nil { return nil, err } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) + httpRes, err := httpclient.New().Do(httpReq) if err != nil { return nil, err } @@ -236,14 +236,14 @@ func CreateFile(ctx context.Context, gw gatewayv1beta1.GatewayAPIClient, path st token, endpoint = p.Token, p.UploadEndpoint } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, endpoint, bytes.NewReader(content)) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, endpoint, bytes.NewReader(content)) if err != nil { return err } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) + httpRes, err := httpclient.New().Do(httpReq) if err != nil { return err } diff --git a/tests/integration/grpc/ocm_invitation_test.go b/tests/integration/grpc/ocm_invitation_test.go index c4addc6c79..f6da7f0e53 100644 --- a/tests/integration/grpc/ocm_invitation_test.go +++ b/tests/integration/grpc/ocm_invitation_test.go @@ -32,8 +32,9 @@ import ( ocmproviderpb "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" @@ -57,9 +58,9 @@ func ctxWithAuthToken(tokenManager token.Manager, user *userpb.User) context.Con Expect(err).ToNot(HaveOccurred()) tkn, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, tkn) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, tkn) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, tkn) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, tkn) + ctx = appctx.ContextSetUser(ctx, user) return ctx } @@ -307,9 +308,9 @@ var _ = Describe("ocm invitation workflow", func() { cernboxURL = revads["cernboxhttp"].GrpcAddress var ok bool - tknMarie, ok = ctxpkg.ContextGetToken(ctxMarie) + tknMarie, ok = appctx.ContextGetToken(ctxMarie) Expect(ok).To(BeTrue()) - tknEinstein, ok = ctxpkg.ContextGetToken(ctxEinstein) + tknEinstein, ok = appctx.ContextGetToken(ctxEinstein) Expect(ok).To(BeTrue()) tknRes, err := cernboxgw.GenerateInviteToken(ctxEinstein, &invitepb.GenerateInviteTokenRequest{}) diff --git a/tests/integration/grpc/ocm_share_test.go b/tests/integration/grpc/ocm_share_test.go index 614d26aef4..f34ddf2ff9 100644 --- a/tests/integration/grpc/ocm_share_test.go +++ b/tests/integration/grpc/ocm_share_test.go @@ -35,9 +35,9 @@ import ( "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/internal/http/services/owncloud/ocdav" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" + "github.com/cs3org/reva/pkg/httpclient" "github.com/cs3org/reva/pkg/ocm/share" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/cs3org/reva/pkg/rhttp" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" "github.com/cs3org/reva/tests/helpers" . "github.com/onsi/ginkgo" @@ -700,14 +700,14 @@ func download(ctx context.Context, gw gatewaypb.GatewayAPIClient, ref *provider. token, endpoint = p.Token, p.DownloadEndpoint } } - httpReq, err := rhttp.NewRequest(ctx, http.MethodGet, endpoint, nil) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) if err != nil { return nil, err } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := http.DefaultClient.Do(httpReq) + httpRes, err := httpclient.New().Do(httpReq) if err != nil { return nil, err } diff --git a/tests/integration/grpc/storageprovider_test.go b/tests/integration/grpc/storageprovider_test.go index 392b8528d4..3435453055 100644 --- a/tests/integration/grpc/storageprovider_test.go +++ b/tests/integration/grpc/storageprovider_test.go @@ -24,8 +24,8 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" storagep "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" . "github.com/onsi/ginkgo" @@ -79,9 +79,9 @@ var _ = Describe("storage providers", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) revads, err = startRevads(dependencies, nil, nil, variables) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/grpc/userprovider_test.go b/tests/integration/grpc/userprovider_test.go index 5e9eda0818..cf08782594 100644 --- a/tests/integration/grpc/userprovider_test.go +++ b/tests/integration/grpc/userprovider_test.go @@ -23,8 +23,9 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/auth/scope" - ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" . "github.com/onsi/ginkgo" @@ -61,9 +62,9 @@ var _ = Describe("user providers", func() { Expect(err).ToNot(HaveOccurred()) t, err := tokenManager.MintToken(ctx, user, scope) Expect(err).ToNot(HaveOccurred()) - ctx = ctxpkg.ContextSetToken(ctx, t) - ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) - ctx = ctxpkg.ContextSetUser(ctx, user) + ctx = appctx.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, appctx.TokenHeader, t) + ctx = appctx.ContextSetUser(ctx, user) revads, err = startRevads(dependencies, nil, nil, map[string]string{}) Expect(err).ToNot(HaveOccurred())