From 25d1347a76e890e05ca516b20fc149366991931d Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 29 Mar 2023 15:49:33 +0200 Subject: [PATCH] create folders if they are not existing Signed-off-by: jkoberg --- services/graph/pkg/server/http/server.go | 3 +- services/graph/pkg/service/v0/personaldata.go | 71 +++++++++++++++---- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/services/graph/pkg/server/http/server.go b/services/graph/pkg/server/http/server.go index 6f6965630..c7d520842 100644 --- a/services/graph/pkg/server/http/server.go +++ b/services/graph/pkg/server/http/server.go @@ -7,6 +7,7 @@ import ( stdhttp "net/http" "os" + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" "github.com/cs3org/reva/v2/pkg/events/stream" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" chimiddleware "github.com/go-chi/chi/v5/middleware" @@ -101,7 +102,7 @@ func Server(opts ...Option) (http.Service, error) { // how do we secure the api? var requireAdminMiddleware func(stdhttp.Handler) stdhttp.Handler var roleService svc.RoleService - var gatewayClient svc.GatewayClient + var gatewayClient gateway.GatewayAPIClient if options.Config.HTTP.APIToken == "" { middlewares = append(middlewares, graphMiddleware.Auth( diff --git a/services/graph/pkg/service/v0/personaldata.go b/services/graph/pkg/service/v0/personaldata.go index 5bb0f8c29..28a6310e5 100644 --- a/services/graph/pkg/service/v0/personaldata.go +++ b/services/graph/pkg/service/v0/personaldata.go @@ -2,18 +2,18 @@ package svc import ( "bytes" + "context" "encoding/json" "fmt" "io" "net/http" "path/filepath" "strconv" - "time" + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - revaCtx "github.com/cs3org/reva/v2/pkg/ctx" revactx "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/rhttp" "github.com/cs3org/reva/v2/pkg/utils" @@ -59,28 +59,20 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) { } // touch file - gwc := g.GetGatewayClient() - resp, err := gwc.TouchFile(ctx, &provider.TouchFileRequest{ - Opaque: utils.AppendPlainToOpaque(nil, "markprocessing", "true"), - Ref: ref, - }) - if err != nil || resp.GetStatus().GetCode() != rpc.Code_CODE_OK { - g.logger.Error().Err(err).Str("status", resp.GetStatus().GetMessage()).Msg("error touching file") + if err := mustTouchFile(ctx, ref, g.GetGatewayClient()); err != nil { + g.logger.Error().Err(err).Msg("error touching file") w.WriteHeader(http.StatusInternalServerError) return } // go start gathering - go g.GatherPersonalData(u, ref, r.Header.Get(revaCtx.TokenHeader), marsh) + go g.GatherPersonalData(u, ref, r.Header.Get(revactx.TokenHeader), marsh) w.WriteHeader(http.StatusOK) } // GatherPersonalData will all gather all personal data of the user and save it to a file in the users personal space func (g Graph) GatherPersonalData(usr *user.User, ref *provider.Reference, token string, marsh Marshaller) { - // TMP - Delay processing - comment if you read this on PR - time.Sleep(10 * time.Second) - // create data data := make(map[string]interface{}) @@ -111,7 +103,7 @@ func (g Graph) upload(u *user.User, data []byte, ref *provider.Reference, th str if err != nil { return err } - ctx = revaCtx.ContextSetToken(ctx, th) + ctx = revactx.ContextSetToken(ctx, th) uRes, err := gwc.InitiateFileUpload(ctx, uReq) if err != nil { return err @@ -146,6 +138,57 @@ func (g Graph) upload(u *user.User, data []byte, ref *provider.Reference, th str return nil } +// touches the file, creating folders if neccessary +func mustTouchFile(ctx context.Context, ref *provider.Reference, gwc gateway.GatewayAPIClient) error { + if err := touchFile(ctx, ref, gwc); err == nil { + return nil + } + + if err := createFolders(ctx, ref, gwc); err != nil { + return err + } + + return touchFile(ctx, ref, gwc) +} + +func touchFile(ctx context.Context, ref *provider.Reference, gwc gateway.GatewayAPIClient) error { + resp, err := gwc.TouchFile(ctx, &provider.TouchFileRequest{ + Opaque: utils.AppendPlainToOpaque(nil, "markprocessing", "true"), + Ref: ref, + }) + if err != nil { + return err + } + if resp.GetStatus().GetCode() != rpc.Code_CODE_OK { + return fmt.Errorf("unexpected statuscode while touching file: %d %s", resp.GetStatus().GetCode(), resp.GetStatus().GetMessage()) + } + return nil +} + +func createFolders(ctx context.Context, ref *provider.Reference, gwc gateway.GatewayAPIClient) error { + var pathes []string + p := filepath.Dir(ref.GetPath()) + for p != "." { + pathes = append([]string{p}, pathes...) + p = filepath.Dir(p) + } + + for _, p := range pathes { + r := &provider.Reference{ResourceId: ref.GetResourceId(), Path: p} + resp, err := gwc.CreateContainer(ctx, &provider.CreateContainerRequest{Ref: r}) + if err != nil { + return err + } + + code := resp.GetStatus().GetCode() + if code != rpc.Code_CODE_OK && code != rpc.Code_CODE_ALREADY_EXISTS { + return fmt.Errorf("unexpected statuscode while creating folder: %d %s", code, resp.GetStatus().GetMessage()) + } + } + return nil + +} + func getLocation(r *http.Request) string { // from body var req ExportPersonalDataRequest