use location from request

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2023-03-29 11:46:29 +02:00
parent 442c53f796
commit ebd730c778
2 changed files with 69 additions and 32 deletions

View File

@@ -9,7 +9,6 @@ import (
"strings"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/go-chi/chi/v5"
"github.com/jellydator/ttlcache/v3"
@@ -21,12 +20,14 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
"go-micro.dev/v4/client"
mevents "go-micro.dev/v4/events"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"
)
//go:generate make -C ../../.. generate
type GatewayClient = gateway.GatewayAPIClient
/*
// GatewayClient is the subset of the gateway.GatewayAPIClient that is being used to interact with the gateway
type GatewayClient interface {
//gateway.GatewayAPIClient
@@ -67,6 +68,7 @@ type GatewayClient interface {
GetQuota(ctx context.Context, in *gateway.GetQuotaRequest, opts ...grpc.CallOption) (*provider.GetQuotaResponse, error)
SetArbitraryMetadata(ctx context.Context, request *provider.SetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.SetArbitraryMetadataResponse, error)
}
*/
// Publisher is the interface for events publisher
type Publisher interface {

View File

@@ -6,9 +6,10 @@ import (
"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"
@@ -25,6 +26,9 @@ var (
TokenTransportHeader = "X-Reva-Transfer"
)
// Marshaller is the common interface for a marshaller
type Marshaller func(any) ([]byte, error)
// ExportPersonalDataRequest is the body of the request
type ExportPersonalDataRequest struct {
StorageLocation string `json:"storageLocation"`
@@ -35,9 +39,18 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
u := revactx.ContextMustGetUser(ctx)
// Get location from request
loc := ""
if loc == "" {
loc = _backupFileName
loc := getLocation(r)
// prepare marshaller
var marsh Marshaller
switch filepath.Ext(loc) {
default:
g.logger.Info().Str("path", loc).Msg("invalid location")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("only json format is supported for personal data export"))
return
case ".json":
marsh = json.Marshal
}
ref := &provider.Reference{
@@ -58,35 +71,46 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
}
// go start gathering
go func() {
time.Sleep(10 * time.Second)
by, _ := json.Marshal(map[string]string{u.GetId().GetOpaqueId(): "no data stored"})
b := bytes.NewBuffer(by)
th := r.Header.Get(revaCtx.TokenHeader)
err := g.upload(u, b, ref, th)
fmt.Println("Upload error", err)
}()
go g.GatherPersonalData(u, ref, r.Header.Get(revaCtx.TokenHeader), marsh)
w.WriteHeader(http.StatusOK)
return
}
func (g Graph) upload(u *user.User, data io.Reader, ref *provider.Reference, th string) error {
// 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{})
// reva user
data["user"] = usr
// marshal
by, err := marsh(data)
if err != nil {
g.logger.Error().Err(err).Msg("cannot marshal personal user data")
return
}
// upload
if err := g.upload(usr, by, ref, token); err != nil {
g.logger.Error().Err(err).Msg("failed uploading personal data export")
}
}
func (g Graph) upload(u *user.User, data []byte, ref *provider.Reference, th string) error {
uReq := &provider.InitiateFileUploadRequest{
Ref: ref,
//Opaque: &typespb.Opaque{
//Map: map[string]*typespb.OpaqueEntry{
//"Upload-Length": {
//Decoder: "plain",
//// TODO: handle case where size is not known in advance
//Value: []byte(strconv.FormatUint(cp.sourceInfo.GetSize(), 10)),
//},
//},
//},
Ref: ref,
Opaque: utils.AppendPlainToOpaque(nil, "Upload-Length", strconv.FormatUint(uint64(len(data)), 10)),
}
gwc := g.GetGatewayClient()
ctx, _, err := utils.Impersonate(u.GetId(), gwc.(gateway.GatewayAPIClient), g.config.MachineAuthAPIKey)
ctx, err := utils.ImpersonateUser(u, gwc, g.config.MachineAuthAPIKey)
if err != nil {
return err
}
ctx = revaCtx.ContextSetToken(ctx, th)
uRes, err := gwc.InitiateFileUpload(ctx, uReq)
if err != nil {
@@ -104,16 +128,13 @@ func (g Graph) upload(u *user.User, data io.Reader, ref *provider.Reference, th
}
}
httpUploadReq, err := rhttp.NewRequest(ctx, "PUT", uploadEP, data)
httpUploadReq, err := rhttp.NewRequest(ctx, "PUT", uploadEP, bytes.NewBuffer(data))
if err != nil {
return err
}
httpUploadReq.Header.Set(TokenTransportHeader, uploadToken)
httpUploadRes, err := rhttp.GetHTTPClient(
// rhttp.Timeout(time.Duration(conf.Timeout*int64(time.Second))),
rhttp.Insecure(true),
).Do(httpUploadReq)
httpUploadRes, err := rhttp.GetHTTPClient(rhttp.Insecure(true)).Do(httpUploadReq)
if err != nil {
return err
}
@@ -124,3 +145,17 @@ func (g Graph) upload(u *user.User, data io.Reader, ref *provider.Reference, th
return nil
}
func getLocation(r *http.Request) string {
// from body
var req ExportPersonalDataRequest
if b, err := io.ReadAll(r.Body); err == nil {
if err := json.Unmarshal(b, &req); err == nil && req.StorageLocation != "" {
return req.StorageLocation
}
}
// from header?
return _backupFileName
}