Skip to content

Commit

Permalink
Feature/import etag and mtime (#299)
Browse files Browse the repository at this point in the history
* move share import implementation to pkg

* import file metadata

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
  • Loading branch information
butonic authored and labkode committed Oct 17, 2019
1 parent 7a3577d commit 175435f
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 137 deletions.
142 changes: 6 additions & 136 deletions cmd/reva/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,13 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"log"
"os"
"path"

rpcpb "github.com/cs3org/go-cs3apis/cs3/rpc"
typespb "github.com/cs3org/go-cs3apis/cs3/types"

storageproviderv0alphapb "github.com/cs3org/go-cs3apis/cs3/storageprovider/v0alpha"
usershareproviderv0alphapb "github.com/cs3org/go-cs3apis/cs3/usershareprovider/v0alpha"
"github.com/cs3org/reva/pkg/storage/migrate"
)

// share representation in the import metadata
type share struct {
Path string `json:"path"`
ShareType string `json:"shareType"`
Type string `json:"type"`
Owner string `json:"owner"`
SharedBy string `json:"sharedBy"`
SharedWith string `json:"sharedWith"`
Permissions int `json:"permissions"`
ExpirationDate string `json:"expirationDate"`
Password string `json:"password"`
Name string `json:"name"`
Token string `json:"token"`
}

// Maps oc10 permissions to roles
var ocPermToRole = map[int]string{
1: "viewer",
15: "co-owner",
31: "editor",
}

func importCommand() *command {
cmd := newCommand("import")
cmd.Description = func() string { return "import metadata" }
Expand All @@ -66,118 +37,17 @@ func importCommand() *command {
}
exportPath := cmd.Args()[0]

err := importShares(exportPath)
ctx := getAuthContext()
client, err := getClient()
if err != nil {
log.Fatal(err)
}

return err
}
return cmd
}

//Imports shares from a shares.jsonl file in exportPath. The files must already be present on the storage
func importShares(exportPath string) error {
storage, err := getClient()
if err != nil {
return err
}
sharing, err := getClient()
if err != nil {
return err
}
ctx := getAuthContext()
sharesJSONL, err := os.Open(path.Join(exportPath, "shares.jsonl"))
if err != nil {
return err
}
defer sharesJSONL.Close()
jsonLines := bufio.NewScanner(sharesJSONL)

for jsonLines.Scan() {
var shareData share
if err := json.Unmarshal(jsonLines.Bytes(), &shareData); err != nil {
log.Fatal(err)
return err
}

//Stat file, skip share creation if it does not exist on the target system
resourcePath := path.Join("/", path.Base(exportPath), shareData.Path)
statReq := &storageproviderv0alphapb.StatRequest{
Ref: &storageproviderv0alphapb.Reference{
Spec: &storageproviderv0alphapb.Reference_Path{Path: resourcePath},
},
}
statResp, err := storage.Stat(ctx, statReq)

if err != nil {
if err := migrate.ImportShares(ctx, client, exportPath); err != nil {
log.Fatal(err)
}

if statResp.Status.Code == rpcpb.Code_CODE_NOT_FOUND {
log.Print("File does not exist on target system, skipping share import: " + resourcePath)
continue
}

_, err = sharing.CreateShare(ctx, shareReq(statResp.Info, &shareData))
if err != nil {
return err
}
}
return nil
}

func shareReq(info *storageproviderv0alphapb.ResourceInfo, share *share) *usershareproviderv0alphapb.CreateShareRequest {
return &usershareproviderv0alphapb.CreateShareRequest{
ResourceInfo: info,
Grant: &usershareproviderv0alphapb.ShareGrant{
Grantee: &storageproviderv0alphapb.Grantee{
Type: storageproviderv0alphapb.GranteeType_GRANTEE_TYPE_USER,
Id: &typespb.UserId{
OpaqueId: share.SharedWith,
},
},
Permissions: &usershareproviderv0alphapb.SharePermissions{
Permissions: convertPermissions(share.Permissions),
},
},
return nil
}
}

// Create resource permission-set from ownCloud permissions int
func convertPermissions(ocPermissions int) *storageproviderv0alphapb.ResourcePermissions {
perms := &storageproviderv0alphapb.ResourcePermissions{}
switch ocPermToRole[ocPermissions] {
case "viewer":
perms.Stat = true
perms.ListContainer = true
perms.InitiateFileDownload = true
perms.ListGrants = true
case "editor":
perms.Stat = true
perms.ListContainer = true
perms.InitiateFileDownload = true

perms.CreateContainer = true
perms.InitiateFileUpload = true
perms.Delete = true
perms.Move = true
perms.ListGrants = true
case "co-owner":
perms.Stat = true
perms.ListContainer = true
perms.InitiateFileDownload = true

perms.CreateContainer = true
perms.InitiateFileUpload = true
perms.Delete = true
perms.Move = true

perms.ListGrants = true
perms.AddGrant = true
perms.RemoveGrant = true
perms.UpdateGrant = true
}

return perms
return cmd
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ require (
github.com/pkg/errors v0.8.1
github.com/pkg/xattr v0.4.1
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect
github.com/rs/cors v1.7.0
github.com/rs/zerolog v1.15.0
go.opencensus.io v0.22.1
Expand All @@ -37,3 +36,5 @@ require (
gopkg.in/ldap.v2 v2.5.1
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
)

go 1.13
95 changes: 95 additions & 0 deletions pkg/storage/migrate/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2018-2019 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 migrate

import (
"bufio"
"context"
"encoding/json"
"log"
"os"
"path"
"strconv"

gatewayv0alphapb "github.com/cs3org/go-cs3apis/cs3/gateway/v0alpha"
rpcpb "github.com/cs3org/go-cs3apis/cs3/rpc"
storageproviderv0alphapb "github.com/cs3org/go-cs3apis/cs3/storageprovider/v0alpha"
)

// metaData representation in the import data
type metaData struct {
Type string `json:"type"`
Path string `json:"path"`
Etag string `json:"eTag"`
Permissions int `json:"permissions"`
MTime int `json:"mtime"`
}

//ImportMetadata from a files.jsonl file in exportPath. The files must already be present on the storage
//Will set etag and mtime
func ImportMetadata(ctx context.Context, client gatewayv0alphapb.GatewayServiceClient, exportPath string) error {

filesJSONL, err := os.Open(path.Join(exportPath, "files.jsonl"))
if err != nil {
return err
}
defer filesJSONL.Close()
jsonLines := bufio.NewScanner(filesJSONL)

for jsonLines.Scan() {
var fileData metaData
if err := json.Unmarshal(jsonLines.Bytes(), &fileData); err != nil {
log.Fatal(err)
return err
}

m := make(map[string]string)
if fileData.Etag != "" {
// TODO sanitize etag? eg double quotes at beginning and end?
m["etag"] = fileData.Etag
}
if fileData.MTime != 0 {
m["mtime"] = strconv.Itoa(fileData.MTime)
}
//TODO permissions? is done via share? but this is owner permissions

if len(m) > 0 {
resourcePath := path.Join("/", path.Base(exportPath), fileData.Path)
samReq := &storageproviderv0alphapb.SetArbitraryMetadataRequest{
Ref: &storageproviderv0alphapb.Reference{
Spec: &storageproviderv0alphapb.Reference_Path{Path: resourcePath},
},
ArbitraryMetadata: &storageproviderv0alphapb.ArbitraryMetadata{
Metadata: m,
},
}
samResp, err := client.SetArbitraryMetadata(ctx, samReq)

if samResp.Status.Code == rpcpb.Code_CODE_NOT_FOUND {
log.Print("File does not exist on target system, skipping metadata import: " + resourcePath)
} else if err != nil {
log.Fatal(err)
}
} else {
log.Print("no etag or mtime for : " + fileData.Path)
}

}
return nil
}

0 comments on commit 175435f

Please sign in to comment.