use location from request
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
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/cs3org/reva/v2/pkg/events"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/jellydator/ttlcache/v3"
|
"github.com/jellydator/ttlcache/v3"
|
||||||
@@ -21,12 +20,14 @@ import (
|
|||||||
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
|
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
|
||||||
"go-micro.dev/v4/client"
|
"go-micro.dev/v4/client"
|
||||||
mevents "go-micro.dev/v4/events"
|
mevents "go-micro.dev/v4/events"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate make -C ../../.. generate
|
//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
|
// GatewayClient is the subset of the gateway.GatewayAPIClient that is being used to interact with the gateway
|
||||||
type GatewayClient interface {
|
type GatewayClient interface {
|
||||||
//gateway.GatewayAPIClient
|
//gateway.GatewayAPIClient
|
||||||
@@ -67,6 +68,7 @@ type GatewayClient interface {
|
|||||||
GetQuota(ctx context.Context, in *gateway.GetQuotaRequest, opts ...grpc.CallOption) (*provider.GetQuotaResponse, error)
|
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)
|
SetArbitraryMetadata(ctx context.Context, request *provider.SetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.SetArbitraryMetadataResponse, error)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Publisher is the interface for events publisher
|
// Publisher is the interface for events publisher
|
||||||
type Publisher interface {
|
type Publisher interface {
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
|
||||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||||
@@ -25,6 +26,9 @@ var (
|
|||||||
TokenTransportHeader = "X-Reva-Transfer"
|
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
|
// ExportPersonalDataRequest is the body of the request
|
||||||
type ExportPersonalDataRequest struct {
|
type ExportPersonalDataRequest struct {
|
||||||
StorageLocation string `json:"storageLocation"`
|
StorageLocation string `json:"storageLocation"`
|
||||||
@@ -35,9 +39,18 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
u := revactx.ContextMustGetUser(ctx)
|
u := revactx.ContextMustGetUser(ctx)
|
||||||
// Get location from request
|
// Get location from request
|
||||||
loc := ""
|
loc := getLocation(r)
|
||||||
if loc == "" {
|
|
||||||
loc = _backupFileName
|
// 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{
|
ref := &provider.Reference{
|
||||||
@@ -58,35 +71,46 @@ func (g Graph) ExportPersonalData(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// go start gathering
|
// go start gathering
|
||||||
go func() {
|
go g.GatherPersonalData(u, ref, r.Header.Get(revaCtx.TokenHeader), marsh)
|
||||||
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)
|
|
||||||
}()
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
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{
|
uReq := &provider.InitiateFileUploadRequest{
|
||||||
Ref: ref,
|
Ref: ref,
|
||||||
//Opaque: &typespb.Opaque{
|
Opaque: utils.AppendPlainToOpaque(nil, "Upload-Length", strconv.FormatUint(uint64(len(data)), 10)),
|
||||||
//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)),
|
|
||||||
//},
|
|
||||||
//},
|
|
||||||
//},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gwc := g.GetGatewayClient()
|
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)
|
ctx = revaCtx.ContextSetToken(ctx, th)
|
||||||
uRes, err := gwc.InitiateFileUpload(ctx, uReq)
|
uRes, err := gwc.InitiateFileUpload(ctx, uReq)
|
||||||
if err != nil {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
httpUploadReq.Header.Set(TokenTransportHeader, uploadToken)
|
httpUploadReq.Header.Set(TokenTransportHeader, uploadToken)
|
||||||
|
|
||||||
httpUploadRes, err := rhttp.GetHTTPClient(
|
httpUploadRes, err := rhttp.GetHTTPClient(rhttp.Insecure(true)).Do(httpUploadReq)
|
||||||
// rhttp.Timeout(time.Duration(conf.Timeout*int64(time.Second))),
|
|
||||||
rhttp.Insecure(true),
|
|
||||||
).Do(httpUploadReq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -124,3 +145,17 @@ func (g Graph) upload(u *user.User, data io.Reader, ref *provider.Reference, th
|
|||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user