Skip to content

Commit

Permalink
use opaque as space props transport
Browse files Browse the repository at this point in the history
  • Loading branch information
micbar committed Feb 10, 2022
1 parent aebad4f commit 400858f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 140 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -257,4 +257,4 @@ require (
stash.kopano.io/kgol/oidc-go v0.3.2 // indirect
)

replace github.com/cs3org/reva => ../reva
replace github.com/cs3org/reva => github.com/micbar/reva v1.9.1-0.20220210130539-d274bcbe266c
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,6 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ=
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/reva v1.16.1-0.20220208091630-7660ee26dce7 h1:6U5hiLJ1vl3J8aoscg6qZLrpFvp5/Y4RnxZ2xS4RQWA=
github.com/cs3org/reva v1.16.1-0.20220208091630-7660ee26dce7/go.mod h1:EAKoGXYmyIKmUSq/fgmAsTGHgrgwSb1PffGiA/AmgSo=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
Expand Down Expand Up @@ -985,6 +983,8 @@ github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 h1:Z/i1e+gTZrmcGeZy
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103/go.mod h1:o9YPB5aGP8ob35Vy6+vyq3P3bWe7NQWzf+JLiXCiMaE=
github.com/mennanov/fieldmask-utils v0.5.0 h1:8em4akN0NM3hmmrg8VbvOPfdS4SSBdbFd53m9VtfOg0=
github.com/mennanov/fieldmask-utils v0.5.0/go.mod h1:lah2lHczE2ff+7SqnNKpB+YzaO7M3h5iNO4LgPTJheM=
github.com/micbar/reva v1.9.1-0.20220210130539-d274bcbe266c h1:wHd+DF2ZWUmoNCeBVNjsx23rJUkW67+0sPa07QaOxMk=
github.com/micbar/reva v1.9.1-0.20220210130539-d274bcbe266c/go.mod h1:EAKoGXYmyIKmUSq/fgmAsTGHgrgwSb1PffGiA/AmgSo=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
Expand Down
128 changes: 48 additions & 80 deletions graph/pkg/service/v0/driveitems.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/utils"
"github.com/go-chi/render"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/graph/pkg/service/v0/errorcode"
Expand Down Expand Up @@ -77,14 +76,11 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, &listResponse{Value: files})
}

func (g Graph) getDriveItem(ctx context.Context, root *storageprovider.ResourceId, relativePath string) (*libregraph.DriveItem, error) {

func (g Graph) getDriveItem(ctx context.Context, root *storageprovider.ResourceId) (*libregraph.DriveItem, error) {
client := g.GetGatewayClient()

ref := &storageprovider.Reference{
ResourceId: root,
// the path is always relative to the root of the drive, not the location of the .config/ocis/space.yaml file
Path: utils.MakeRelativePath(relativePath),
}
res, err := client.Stat(ctx, &storageprovider.StatRequest{Ref: ref})
if err != nil {
Expand All @@ -93,10 +89,23 @@ func (g Graph) getDriveItem(ctx context.Context, root *storageprovider.ResourceI
if res.Status.Code != cs3rpc.Code_CODE_OK {
return nil, fmt.Errorf("could not stat %s: %s", ref, res.Status.Message)
}

return cs3ResourceToDriveItem(res.Info)
}

func (g Graph) getPathForDriveItem(ctx context.Context, ID *storageprovider.ResourceId) (*string, error) {
client := g.GetGatewayClient()
var path *string
res, err := client.GetPath(ctx, &storageprovider.GetPathRequest{ResourceId: ID})
if err != nil {
return nil, err
}
if res.Status.Code != cs3rpc.Code_CODE_OK {
return nil, fmt.Errorf("could not stat %s: %s", ID, res.Status.Message)
}
path = &res.Path
return path, err
}

func formatDriveItems(mds []*storageprovider.ResourceInfo) ([]*libregraph.DriveItem, error) {
responses := make([]*libregraph.DriveItem, 0, len(mds))
for i := range mds {
Expand Down Expand Up @@ -145,85 +154,44 @@ func cs3ResourceToDriveItem(res *storageprovider.ResourceInfo) (*libregraph.Driv
return driveItem, nil
}

func (g Graph) getDriveMetadata(ctx context.Context, space *storageprovider.StorageSpace) (map[string]string, error) {
client := g.GetGatewayClient()
sResp, err := client.Stat(
ctx,
&storageprovider.StatRequest{
Ref: &storageprovider.Reference{
ResourceId: &storageprovider.ResourceId{
StorageId: space.Root.StorageId,
OpaqueId: space.Root.OpaqueId,
},
},
},
)
if err != nil {
g.logger.Debug().Err(err).Interface("space", space).Msg("transport error")
return nil, err
}
if sResp.Status.Code != cs3rpc.Code_CODE_OK {
g.logger.Debug().Interface("space", space).Msg("space not found")
return nil, fmt.Errorf("space not found")
}
md := sResp.Info.ArbitraryMetadata.GetMetadata()
if md == nil {
g.logger.Error().Err(err).Interface("space", space).Msg("could not read metadata from space")
return nil, fmt.Errorf("could not read metadata from space")
}
return md, nil
}

func (g Graph) setSpaceMetadata(ctx context.Context, metadata map[string]string, resourceID *storageprovider.ResourceId) error {
if len(metadata) == 0 {
return nil
}
client := g.GetGatewayClient()
resMd, err := client.SetArbitraryMetadata(
ctx,
&storageprovider.SetArbitraryMetadataRequest{
ArbitraryMetadata: &storageprovider.ArbitraryMetadata{
Metadata: metadata,
},
Ref: &storageprovider.Reference{
ResourceId: resourceID,
},
},
)
if err != nil {
g.logger.Error().Msg("transport error, could not set metadata")
return err
}
if resMd.Status.Code != cs3rpc.Code_CODE_OK {
g.logger.Error().Msg("could not set metadata")
return fmt.Errorf("could not set metadata")
}
return nil
}

func (g Graph) GetSpecialSpaceItems(ctx context.Context, baseURL *url.URL, spaceRootID *storageprovider.ResourceId, metadata map[string]string) []libregraph.DriveItem {
func (g Graph) GetSpecialSpaceItems(ctx context.Context, baseURL *url.URL, space *storageprovider.StorageSpace) []libregraph.DriveItem {
var spaceItems []libregraph.DriveItem
if metadata == nil {
if space.Opaque == nil {
return spaceItems
}
if readmePath, ok := metadata[ReadmePathAttrName]; ok {
readmeItem, err := g.getDriveItem(ctx, spaceRootID, readmePath)
if err != nil {
g.logger.Error().Err(err).Str(ReadmePathAttrName, readmePath).Msg("Could not get readme Item")
} else {
readmeItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(ReadmePathSpecialFolderName)}
readmeItem.WebDavUrl = libregraph.PtrString(baseURL.String() + filepath.Join(spaceRootID.OpaqueId, readmePath))
spaceItems = append(spaceItems, *readmeItem)
metadata := space.Opaque.Map
if readmeAttr, ok := metadata[ReadmeSpecialFolderName]; ok {
readmeID := string(readmeAttr.Value)
if readmeID != "" {
readmeItem, err := g.getDriveItem(ctx, &storageprovider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: readmeID})
if err != nil {
g.logger.Error().Err(err).Str("ID", readmeID).Msg("Could not get readme Item")
}
readmePath, err := g.getPathForDriveItem(ctx, &storageprovider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: readmeID})
if err != nil {
g.logger.Error().Err(err).Str("ID", readmeID).Msg("Could not get readme path")
} else {
readmeItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(ReadmeSpecialFolderName)}
readmeItem.WebDavUrl = libregraph.PtrString(baseURL.String() + filepath.Join(space.Root.OpaqueId, *readmePath))
spaceItems = append(spaceItems, *readmeItem)
}
}
}
if imagePath, ok := metadata[SpaceImageAttrName]; ok {
imageItem, err := g.getDriveItem(ctx, spaceRootID, imagePath)
if err != nil {
g.logger.Error().Err(err).Str(SpaceImageAttrName, imagePath).Msg("Could not get image Item")
} else {
imageItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(SpaceImageSpecialFolderName)}
imageItem.WebDavUrl = libregraph.PtrString(baseURL.String() + filepath.Join(spaceRootID.OpaqueId, imagePath))
spaceItems = append(spaceItems, *imageItem)
if metadataAttr, ok := metadata[SpaceImageSpecialFolderName]; ok {
imageID := string(metadataAttr.Value)
if imageID != "" {
imageItem, err := g.getDriveItem(ctx, &storageprovider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: imageID})
if err != nil {
g.logger.Error().Err(err).Str("ID", imageID).Msg("Could not get image Item")
}
imagePath, err := g.getPathForDriveItem(ctx, &storageprovider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: imageID})
if err != nil {
g.logger.Error().Err(err).Str("ID", imageID).Msg("Could not get image path")
} else {
imageItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(SpaceImageSpecialFolderName)}
imageItem.WebDavUrl = libregraph.PtrString(baseURL.String() + filepath.Join(space.Root.OpaqueId, *imagePath))
spaceItems = append(spaceItems, *imageItem)
}
}
}
return spaceItems
Expand Down
92 changes: 41 additions & 51 deletions graph/pkg/service/v0/drives.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"math"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"

Expand Down Expand Up @@ -192,6 +191,18 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) {
Quota: getQuota(drive.Quota, g.config.Spaces.DefaultQuota),
}

spaceDescription := *drive.Description
if spaceDescription != "" {
csr.Opaque = &types.Opaque{
Map: map[string]*types.OpaqueEntry{
"permissions": {
Decoder: "plain",
Value: []byte(spaceDescription),
},
},
}
}

resp, err := client.CreateStorageSpace(r.Context(), &csr)
if err != nil {
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
Expand Down Expand Up @@ -265,6 +276,7 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
},
}

// Use the Opaque prop of the request
if restore, _ := strconv.ParseBool(r.Header.Get("restore")); restore {
updateSpaceRequest.Opaque = &types.Opaque{
Map: map[string]*types.OpaqueEntry{
Expand All @@ -276,37 +288,28 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
}
}

if drive.Name != nil {
updateSpaceRequest.StorageSpace.Name = *drive.Name
}
metadata := make(map[string]string)
for _, specialItem := range drive.Special {

baseUrl, err := url.Parse(g.config.Spaces.WebDavBase + g.config.Spaces.WebDavPath + driveID)
if err != nil {
g.logger.Error().Err(err)
}
newURL, err := filepath.Rel(baseUrl.String(), *specialItem.WebDavUrl)
if err != nil {
g.logger.Error().Err(err)
}
switch *specialItem.SpecialFolder.Name {
case SpaceImageSpecialFolderName:
metadata[SpaceImageAttrName] = newURL
case ReadmePathSpecialFolderName:
metadata[ReadmePathAttrName] = newURL
// Use the Opaque prop of the space
opaque := make(map[string]*types.OpaqueEntry)
spaceDescription := *drive.Description
if spaceDescription != "" {
opaque["description"] = &types.OpaqueEntry{
Decoder: "plain",
Value: []byte(spaceDescription),
}
}

if drive.Description != nil {
metadata[SpaceDescriptionAttrName] = *drive.Description
for _, special := range drive.Special {
if special.Id != nil {
opaque[*special.SpecialFolder.Name] = &types.OpaqueEntry{
Decoder: "plain",
Value: []byte(*special.Id),
}
}
}
updateSpaceRequest.StorageSpace.Opaque = &types.Opaque{Map: opaque}

if metadata != nil {
err = g.setSpaceMetadata(r.Context(), metadata, root)
if err != nil {
g.logger.Error().Err(err)
}
if drive.Name != nil {
updateSpaceRequest.StorageSpace.Name = *drive.Name
}

if drive.Quota.HasTotal() {
Expand Down Expand Up @@ -360,33 +363,15 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, spaces[0])
}

func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, mds []*storageprovider.StorageSpace) ([]*libregraph.Drive, error) {
responses := make([]*libregraph.Drive, 0, len(mds))
for i := range mds {
res, err := g.cs3StorageSpaceToDrive(baseURL, mds[i])
func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, storageSpaces []*storageprovider.StorageSpace) ([]*libregraph.Drive, error) {
responses := make([]*libregraph.Drive, 0, len(storageSpaces))
for _, storageSpace := range storageSpaces {
res, err := g.cs3StorageSpaceToDrive(baseURL, storageSpace)
if err != nil {
return nil, err
}
md, err := g.getDriveMetadata(ctx, mds[i])
if err != nil {
g.logger.Error().Err(err).Interface("space", mds[i]).Msg("error reading extendedSpaceProperties")
continue
}

if sd, ok := md[SpaceDescriptionAttrName]; ok {
res.Description = libregraph.PtrString(sd)
}
res.Special = g.GetSpecialSpaceItems(
ctx,
baseURL,
&storageprovider.ResourceId{
StorageId: mds[i].Root.StorageId,
OpaqueId: mds[i].Root.OpaqueId,
},
md,
)

res.Quota, err = g.getDriveQuota(ctx, mds[i])
res.Special = g.GetSpecialSpaceItems(ctx, baseURL, storageSpace)
res.Quota, err = g.getDriveQuota(ctx, storageSpace)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -502,6 +487,11 @@ func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.S
Permissions: permissions,
},
}
if space.Opaque != nil {
if description, ok := space.Opaque.Map["description"]; ok {
drive.Description = libregraph.PtrString(string(description.Value))
}
}

if space.Opaque != nil && space.Opaque.Map != nil {
v, ok := space.Opaque.Map["trashed"]
Expand Down
9 changes: 3 additions & 6 deletions graph/pkg/service/v0/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type GatewayClient interface {
// Returns the home path for the given authenticated user.
// When a user has access to multiple storage providers, one of them is the home.
GetHome(ctx context.Context, in *provider.GetHomeRequest, opts ...grpc.CallOption) (*provider.GetHomeResponse, error)
// GetPath does a path lookup for a resource by ID
GetPath(ctx context.Context, in *provider.GetPathRequest, opts ...grpc.CallOption) (*provider.GetPathResponse, error)
// Returns a list of resource information
// for the provided reference.
// MUST return CODE_NOT_FOUND if the reference does not exists.
Expand All @@ -39,8 +41,6 @@ type GatewayClient interface {
ListStorageSpaces(ctx context.Context, in *provider.ListStorageSpacesRequest, opts ...grpc.CallOption) (*provider.ListStorageSpacesResponse, error)
// Updates a storage space.
UpdateStorageSpace(ctx context.Context, in *provider.UpdateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.UpdateStorageSpaceResponse, error)
// SetArbitraryMetadata stores key value metadata
SetArbitraryMetadata(ctx context.Context, in *provider.SetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.SetArbitraryMetadataResponse, error)
// Deletes a storage space.
DeleteStorageSpace(ctx context.Context, in *provider.DeleteStorageSpaceRequest, opts ...grpc.CallOption) (*provider.DeleteStorageSpaceResponse, error)
// Returns the quota available under the provided
Expand Down Expand Up @@ -92,9 +92,6 @@ const (
NoSpaceFoundMessage = "space with id `%s` not found"
ListStorageSpacesTransportErr = "transport error sending list storage spaces grpc request"
ListStorageSpacesReturnsErr = "list storage spaces grpc request returns an errorcode in the response"
ReadmePathAttrName = "space.readme"
ReadmePathSpecialFolderName = "readme"
SpaceImageAttrName = "space.image"
ReadmeSpecialFolderName = "readme"
SpaceImageSpecialFolderName = "image"
SpaceDescriptionAttrName = "space.description"
)

0 comments on commit 400858f

Please sign in to comment.