From 940bfe5d65b076225ced527dd00f218c3739abb0 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 15 Apr 2026 08:00:35 +0200 Subject: [PATCH] fix: use libregraph client --- services/collaboration/pkg/command/server.go | 3 +- .../pkg/connector/fileconnector.go | 66 +++++++++++-------- .../pkg/connector/fileconnector_test.go | 2 +- .../pkg/connector/httpadapter.go | 5 +- 4 files changed, 46 insertions(+), 30 deletions(-) diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index 92e14c0972..afbd1ebf7f 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -23,6 +23,7 @@ import ( "github.com/opencloud-eu/reva/v2/pkg/store" "github.com/spf13/cobra" + "go-micro.dev/v4/selector" microstore "go-micro.dev/v4/store" ) @@ -138,7 +139,7 @@ func Server(cfg *config.Config) *cobra.Command { // start HTTP server httpServer, err := http.Server( - http.Adapter(connector.NewHttpAdapter(gatewaySelector, cfg, st)), + http.Adapter(connector.NewHttpAdapter(gatewaySelector, cfg, st, selector.NewSelector(selector.Registry(registry.GetRegistry())))), http.Logger(logger), http.Config(cfg), http.Context(ctx), diff --git a/services/collaboration/pkg/connector/fileconnector.go b/services/collaboration/pkg/connector/fileconnector.go index 1b6dcd9ba7..2325342b99 100644 --- a/services/collaboration/pkg/connector/fileconnector.go +++ b/services/collaboration/pkg/connector/fileconnector.go @@ -14,6 +14,9 @@ import ( "strings" "time" + libregraph "github.com/opencloud-eu/libre-graph-api-go" + "go-micro.dev/v4/selector" + appproviderv1beta1 "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1" auth "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" @@ -105,17 +108,19 @@ type FileConnectorService interface { // Currently, it handles file locks and getting the file info. // Note that operations might return any kind of error, not just ConnectorError type FileConnector struct { - gws pool.Selectable[gatewayv1beta1.GatewayAPIClient] - cfg *config.Config - store microstore.Store + gws pool.Selectable[gatewayv1beta1.GatewayAPIClient] + cfg *config.Config + store microstore.Store + graphSelector selector.Selector } // NewFileConnector creates a new file connector -func NewFileConnector(gws pool.Selectable[gatewayv1beta1.GatewayAPIClient], cfg *config.Config, st microstore.Store) *FileConnector { +func NewFileConnector(gws pool.Selectable[gatewayv1beta1.GatewayAPIClient], cfg *config.Config, st microstore.Store, graphSelector selector.Selector) *FileConnector { return &FileConnector{ - gws: gws, - cfg: cfg, - store: st, + gws: gws, + cfg: cfg, + store: st, + graphSelector: graphSelector, } } @@ -1557,28 +1562,23 @@ func (f *FileConnector) GetAvatar(ctx context.Context, userID string) (*Connecto return nil, NewConnectorError(http.StatusUnauthorized, "missing WOPI context") } - avatarURL := f.cfg.CS3Api.GraphEndpoint + "/v1.0/users/" + userID + "/photo/$value" - - httpReq, err := http.NewRequestWithContext(ctx, http.MethodGet, avatarURL, nil) + lgClient, err := f.setupLibregraphClient(ctx, wopiContext.AccessToken) if err != nil { - logger.Error().Err(err).Msg("GetAvatar: failed to create request") - return nil, NewConnectorError(http.StatusInternalServerError, "failed to create request") + logger.Error().Err(err).Msg("GetAvatar: failed to setup libregraph client") + return nil, NewConnectorError(http.StatusInternalServerError, "failed to setup libregraph client") } - httpReq.Header.Set(ctxpkg.TokenHeader, wopiContext.AccessToken) - httpResp, err := http.DefaultClient.Do(httpReq) + photoFile, httpResp, err := lgClient.UserPhotoApi.GetUserPhoto(ctx, userID).Execute() if err != nil { logger.Error().Err(err).Msg("GetAvatar: failed to fetch avatar from Graph API") + if httpResp != nil { + return nil, NewConnectorError(httpResp.StatusCode, http.StatusText(httpResp.StatusCode)) + } return nil, NewConnectorError(http.StatusBadGateway, "failed to fetch avatar") } - defer httpResp.Body.Close() + defer photoFile.Close() - if httpResp.StatusCode != http.StatusOK { - logger.Warn().Int("status", httpResp.StatusCode).Msg("GetAvatar: Graph API returned non-200") - return nil, NewConnectorError(httpResp.StatusCode, http.StatusText(httpResp.StatusCode)) - } - - data, err := io.ReadAll(httpResp.Body) + data, err := io.ReadAll(photoFile) if err != nil { logger.Error().Err(err).Msg("GetAvatar: failed to read avatar body") return nil, NewConnectorError(http.StatusInternalServerError, "failed to read avatar body") @@ -1587,18 +1587,32 @@ func (f *FileConnector) GetAvatar(ctx context.Context, userID string) (*Connecto headers := map[string]string{ "Cache-Control": "public, max-age=300", } - if ct := httpResp.Header.Get("Content-Type"); ct != "" { headers["Content-Type"] = ct } - if cl := httpResp.Header.Get("Content-Length"); cl != "" { - headers["Content-Length"] = cl - } - return &ConnectorResponse{ Status: http.StatusOK, Headers: headers, Body: data, }, nil } + +func (f *FileConnector) setupLibregraphClient(_ context.Context, cs3token string) (*libregraph.APIClient, error) { + next, err := f.graphSelector.Select("eu.opencloud.web.graph") + if err != nil { + return nil, err + } + node, err := next() + if err != nil { + return nil, err + } + lgconf := libregraph.NewConfiguration() + lgconf.Servers = libregraph.ServerConfigurations{ + { + URL: fmt.Sprintf("%s://%s/graph", node.Metadata["protocol"], node.Address), + }, + } + lgconf.DefaultHeader = map[string]string{ctxpkg.TokenHeader: cs3token} + return libregraph.NewAPIClient(lgconf), nil +} diff --git a/services/collaboration/pkg/connector/fileconnector_test.go b/services/collaboration/pkg/connector/fileconnector_test.go index c1cd3662cd..cdfe7e6c9e 100644 --- a/services/collaboration/pkg/connector/fileconnector_test.go +++ b/services/collaboration/pkg/connector/fileconnector_test.go @@ -65,7 +65,7 @@ var _ = Describe("FileConnector", func() { gatewaySelector = mocks.NewSelectable[gateway.GatewayAPIClient](GinkgoT()) gatewaySelector.On("Next").Return(gatewayClient, nil) - fc = connector.NewFileConnector(gatewaySelector, cfg, nil) + fc = connector.NewFileConnector(gatewaySelector, cfg, nil, nil) wopiCtx = middleware.WopiContext{ // a real token is needed for the PutRelativeFileSuggested tests diff --git a/services/collaboration/pkg/connector/httpadapter.go b/services/collaboration/pkg/connector/httpadapter.go index 454a664a6d..a983c2b6d9 100644 --- a/services/collaboration/pkg/connector/httpadapter.go +++ b/services/collaboration/pkg/connector/httpadapter.go @@ -14,6 +14,7 @@ import ( "github.com/opencloud-eu/opencloud/services/collaboration/pkg/locks" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" "github.com/rs/zerolog" + "go-micro.dev/v4/selector" microstore "go-micro.dev/v4/store" ) @@ -47,10 +48,10 @@ type HttpAdapter struct { // NewHttpAdapter will create a new HTTP adapter. A new connector using the // provided gateway API client and configuration will be used in the adapter -func NewHttpAdapter(gws pool.Selectable[gatewayv1beta1.GatewayAPIClient], cfg *config.Config, st microstore.Store) *HttpAdapter { +func NewHttpAdapter(gws pool.Selectable[gatewayv1beta1.GatewayAPIClient], cfg *config.Config, st microstore.Store, graphSelector selector.Selector) *HttpAdapter { httpAdapter := &HttpAdapter{ con: NewConnector( - NewFileConnector(gws, cfg, st), + NewFileConnector(gws, cfg, st, graphSelector), NewContentConnector(gws, cfg), ), }