Skip to content

Commit

Permalink
Import shares using share create instead of update and some refactori…
Browse files Browse the repository at this point in the history
…ng (#258)
  • Loading branch information
IljaN authored and labkode committed Sep 19, 2019
1 parent b022ebd commit 509cdba
Showing 1 changed file with 127 additions and 116 deletions.
243 changes: 127 additions & 116 deletions cmd/reva/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,42 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"io"
"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"
)

// 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 @@ -40,133 +64,120 @@ func importCommand() *command {
fmt.Println(cmd.Usage())
os.Exit(1)
}
f := cmd.Args()[0]
exportPath := cmd.Args()[0]

sClient, err := getStorageProviderClient()
err := importShares(exportPath)
if err != nil {
return err
}
uClient, err := getUserShareProviderClient()
if err != nil {
return err
log.Fatal(err)
}

ctx := getAuthContext()
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 := getStorageProviderClient()
if err != nil {
return err
}
sharing, err := getUserShareProviderClient()
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)

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

// open files.jsonl
// see https://github.com/owncloud/data_exporter/issues/77#issuecomment-507582067 for the import file layout
// the concrete format still needs to be determined
//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)

file, err := os.Open(path.Join(f, "files.jsonl"))
if err != nil {
log.Fatal(err)
}
defer file.Close()

dec := json.NewDecoder(file)

for {
var j map[string]interface{}
if err := dec.Decode(&j); err == io.EOF {
break
} else if err != nil {
// TODO write to error jsonl and continue?
log.Fatal(err)
return err
}
fn := path.Join("/", path.Base(f), j["path"].(string))

sReq := &storageproviderv0alphapb.StatRequest{
Ref: &storageproviderv0alphapb.Reference{
Spec: &storageproviderv0alphapb.Reference_Path{Path: fn},
},
}
sRes, err := sClient.Stat(ctx, sReq)
if err != nil {
// TODO log that a file does not exist
log.Fatal(err)
return err
}
if sRes.Status.Code == rpcpb.Code_CODE_NOT_FOUND {
// TODO log that a file does not exist
log.Print("file does not exist: " + fn)
continue
}

info := sRes.Info

if j["shares"] != nil {
// update shares
for _, s := range j["shares"].([]interface{}) {
share := s.(map[string]interface{})
role := share["role"].(string)
permissions := &storageproviderv0alphapb.ResourcePermissions{}

// TODO use roles mapping to map to permissions
switch role {
case "viewer":
permissions.Stat = true
permissions.ListContainer = true
permissions.InitiateFileDownload = true

permissions.ListGrants = true
case "editor":
permissions.Stat = true
permissions.ListContainer = true
permissions.InitiateFileDownload = true

permissions.CreateContainer = true
permissions.InitiateFileUpload = true
permissions.Delete = true
permissions.Move = true

permissions.ListGrants = true
case "co-owner":
permissions.Stat = true
permissions.ListContainer = true
permissions.InitiateFileDownload = true

permissions.CreateContainer = true
permissions.InitiateFileUpload = true
permissions.Delete = true
permissions.Move = true

permissions.ListGrants = true
permissions.AddGrant = true
permissions.RemoveGrant = true
permissions.UpdateGrant = true
}
user := share["user"].(string)
shareID := "u:" + user + "@" + info.GetId().OpaqueId
uReq := &usershareproviderv0alphapb.UpdateShareRequest{
Ref: &usershareproviderv0alphapb.ShareReference{
Spec: &usershareproviderv0alphapb.ShareReference_Id{
Id: &usershareproviderv0alphapb.ShareId{
OpaqueId: shareID,
},
},
},
Field: &usershareproviderv0alphapb.UpdateShareRequest_UpdateField{
Field: &usershareproviderv0alphapb.UpdateShareRequest_UpdateField_Permissions{
Permissions: &usershareproviderv0alphapb.SharePermissions{
// this completely overwrites the permissions for this user
Permissions: permissions,
},
},
},
}
_, err := uClient.UpdateShare(ctx, uReq)
if err != nil {
return err
}
}
}

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

return nil
_, err = sharing.CreateShare(ctx, shareReq(statResp.Info, &shareData))
if err != nil {
return err
}
}
return cmd
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),
},
},
}
}

// 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
}

0 comments on commit 509cdba

Please sign in to comment.