Skip to content

Commit

Permalink
enhancement: add sharedWithMe graph beta endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
fschade committed Nov 7, 2023
1 parent cbfd894 commit 120fbba
Show file tree
Hide file tree
Showing 9 changed files with 684 additions and 11 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/enhancement-graph-beta-sharedWithMe-api
@@ -0,0 +1,7 @@
Enhancement: Add graph beta sharedWithMe API

Add graph beta api implementation for the sharedWithMe endpoint.
The implementation is a logical replication of the existing OCS API.

https://github.com/owncloud/ocis/pull/7633
https://github.com/owncloud/ocis/issues/7436
5 changes: 4 additions & 1 deletion go.mod
Expand Up @@ -65,7 +65,7 @@ require (
github.com/onsi/gomega v1.27.10
github.com/open-policy-agent/opa v0.51.0
github.com/orcaman/concurrent-map v1.0.0
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231019070917-17ae03ef40e4
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231107135330-011e9d4c45e3
github.com/pkg/errors v0.9.1
github.com/pkg/xattr v0.4.9
github.com/prometheus/client_golang v1.17.0
Expand All @@ -78,6 +78,7 @@ require (
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
github.com/thejerf/suture/v4 v4.0.2
github.com/tidwall/gjson v1.17.0
github.com/tus/tusd v1.13.0
github.com/urfave/cli/v2 v2.25.7
github.com/xhit/go-simple-mail/v2 v2.16.0
Expand Down Expand Up @@ -304,6 +305,8 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
github.com/trustelem/zxcvbn v1.0.1 // indirect
github.com/wk8/go-ordered-map v1.0.0 // indirect
Expand Down
11 changes: 9 additions & 2 deletions go.sum
Expand Up @@ -1771,8 +1771,8 @@ github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk
github.com/orcaman/concurrent-map v1.0.0 h1:I/2A2XPCb4IuQWcQhBhSwGfiuybl/J0ev9HDbW65HOY=
github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231019070917-17ae03ef40e4 h1:W2X4DGGEuNUeGCKOUK8c2NAC4kva8jq9knuv5ePLUiE=
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231019070917-17ae03ef40e4/go.mod h1:v2aAl5IwEI8t+GmcWvBd+bvJMYp9Vf1hekLuRf0UnEs=
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231107135330-011e9d4c45e3 h1:eUE3kNgr8PwcXeUKFkuEuz1+4hfCCmq+rKYQzk0OxtY=
github.com/owncloud/libre-graph-api-go v1.0.5-0.20231107135330-011e9d4c45e3/go.mod h1:v2aAl5IwEI8t+GmcWvBd+bvJMYp9Vf1hekLuRf0UnEs=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
Expand Down Expand Up @@ -1987,6 +1987,13 @@ github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
github.com/thejerf/suture/v4 v4.0.2 h1:VxIH/J8uYvqJY1+9fxi5GBfGRkRZ/jlSOP6x9HijFQc=
github.com/thejerf/suture/v4 v4.0.2/go.mod h1:g0e8vwskm9tI0jRjxrnA6lSr0q6OfPdWJVX7G5bVWRs=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 h1:PM5hJF7HVfNWmCjMdEfbuOBNXSVF2cMFGgQTPdKCbwM=
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns=
Expand Down
9 changes: 5 additions & 4 deletions services/graph/pkg/service/v0/graph.go
Expand Up @@ -16,6 +16,11 @@ import (
"github.com/go-chi/chi/v5"
"github.com/jellydator/ttlcache/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
"go-micro.dev/v4/client"
mevents "go-micro.dev/v4/events"
"go.opentelemetry.io/otel/trace"
"google.golang.org/protobuf/types/known/emptypb"

"github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
ehsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/eventhistory/v0"
Expand All @@ -24,10 +29,6 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/config"
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
"go-micro.dev/v4/client"
mevents "go-micro.dev/v4/events"
"go.opentelemetry.io/otel/trace"
"google.golang.org/protobuf/types/known/emptypb"
)

//go:generate make -C ../../.. generate
Expand Down
8 changes: 7 additions & 1 deletion services/graph/pkg/service/v0/service.go
Expand Up @@ -17,6 +17,8 @@ import (
ldapv3 "github.com/go-ldap/ldap/v3"
"github.com/jellydator/ttlcache/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
microstore "go-micro.dev/v4/store"

ocisldap "github.com/owncloud/ocis/v2/ocis-pkg/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/ocis-pkg/roles"
Expand All @@ -25,7 +27,6 @@ import (
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
"github.com/owncloud/ocis/v2/services/graph/pkg/identity/ldap"
graphm "github.com/owncloud/ocis/v2/services/graph/pkg/middleware"
microstore "go-micro.dev/v4/store"
)

const (
Expand Down Expand Up @@ -100,6 +101,8 @@ type Service interface {
UpdateDrive(w http.ResponseWriter, r *http.Request)
DeleteDrive(w http.ResponseWriter, r *http.Request)

ListSharedWithMe(w http.ResponseWriter, r *http.Request)

GetRootDriveChildren(w http.ResponseWriter, r *http.Request)
GetDriveItem(w http.ResponseWriter, r *http.Request)
GetDriveItemChildren(w http.ResponseWriter, r *http.Request)
Expand Down Expand Up @@ -199,6 +202,9 @@ func NewService(opts ...Option) (Graph, error) {

m.Route(options.Config.HTTP.Root, func(r chi.Router) {
r.Use(middleware.StripSlashes)
r.Route("/v1beta1", func(r chi.Router) {
r.Get("/me/drive/sharedWithMe", svc.ListSharedWithMe)
})
r.Route("/v1.0", func(r chi.Router) {
r.Route("/extensions/org.libregraph", func(r chi.Router) {
r.Get("/tags", svc.GetTags)
Expand Down
249 changes: 249 additions & 0 deletions services/graph/pkg/service/v0/sharedwithme.go
@@ -0,0 +1,249 @@
package svc

import (
"context"
"net/http"
"strings"

userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/go-chi/render"
libregraph "github.com/owncloud/libre-graph-api-go"

"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
)

// ListSharedWithMe lists the files shared with the current user.
func (g Graph) ListSharedWithMe(w http.ResponseWriter, r *http.Request) {
showHidden := r.URL.Query().Get("show-hidden") == "true"
ctx := r.Context()
driveItems, err := g.listSharedWithMe(ctx, showHidden)
if err != nil {
errorcode.RenderError(w, r, err)
return
}

render.Status(r, http.StatusOK)
render.JSON(w, r, &ListResponse{Value: driveItems})
}
func (g Graph) listSharedWithMe(ctx context.Context, showHidden bool) ([]libregraph.DriveItem, error) {
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
return nil, err
}

listReceivedSharesResponse, err := gatewayClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{})
if err != nil {
return nil, err
}

switch listReceivedSharesResponse.Status.Code {
case rpc.Code_CODE_NOT_FOUND:
return nil, identity.ErrNotFound
}

var driveItems []libregraph.DriveItem
for _, receivedShare := range listReceivedSharesResponse.GetShares() {
if receivedShare.GetHidden() && !showHidden {
continue
}

share := receivedShare.GetShare()
if share == nil {
// fixMe:
// - return error?
continue
}

statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: share.GetResourceId()}})
if err != nil {
// fixMe:
// - return error?
continue
}
if statResponse.GetStatus().GetCode() != rpc.Code_CODE_OK {
// fixMe:
// - return error?
continue
}

var driveOwner *libregraph.Identity
if user := statResponse.GetInfo().GetOwner(); user != nil {
if getUserResponse, err := gatewayClient.GetUser(ctx, &userpb.GetUserRequest{
UserId: &userpb.UserId{
OpaqueId: user.GetOpaqueId(),
},
SkipFetchingUserGroups: true,
}); err != nil {
// fixMe:
// - return error?
continue
} else {
driveOwner = &libregraph.Identity{
DisplayName: getUserResponse.GetUser().GetDisplayName(),
Id: libregraph.PtrString(getUserResponse.GetUser().GetId().GetOpaqueId()),
}
}
}

var shareCreator *libregraph.Identity
if user := share.GetCreator(); user != nil {
if getUserResponse, err := gatewayClient.GetUser(ctx, &userpb.GetUserRequest{
UserId: &userpb.UserId{
OpaqueId: user.GetOpaqueId(),
},
SkipFetchingUserGroups: true,
}); err != nil {
// fixMe:
// - return error?
continue
} else {
shareCreator = &libregraph.Identity{
DisplayName: getUserResponse.GetUser().GetDisplayName(),
Id: libregraph.PtrString(getUserResponse.GetUser().GetId().GetOpaqueId()),
}
}
}

resourceInfo := statResponse.GetInfo()
driveItem := &libregraph.DriveItem{}

if cTime := share.GetCtime(); cTime != nil {
driveItem.CreatedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime))
}

driveItem.ETag = libregraph.PtrString(strings.Trim(statResponse.GetInfo().GetEtag(), "\""))

if id := share.GetId().GetOpaqueId(); id != "" {
driveItem.Id = libregraph.PtrString(id)
}

if mTime := share.GetMtime(); mTime != nil {
driveItem.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime))
}

if name := resourceInfo.GetName(); name != "" {
driveItem.Name = libregraph.PtrString(name)
}

{
addParentReference := false
parentReference := &libregraph.ItemReference{}

if id := share.GetId().GetOpaqueId(); id != "" {
parentReference.DriveId = libregraph.PtrString(id)
addParentReference = true
}

if addParentReference {
driveItem.ParentReference = parentReference
}
}

{
remoteItem := &libregraph.RemoteItem{}

if id := resourceInfo.GetId(); id != nil {
remoteItem.Id = libregraph.PtrString(storagespace.FormatResourceID(*id))
}

if mTime := resourceInfo.GetMtime(); mTime != nil {
remoteItem.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime))
}

if name := resourceInfo.GetName(); name != "" {
remoteItem.Name = libregraph.PtrString(name)
}

// fixMe:
// - negative permission could distort the size, am i right?
remoteItem.Size = libregraph.PtrInt64(int64(resourceInfo.GetSize()))

remoteItem.CreatedBy = &libregraph.IdentitySet{
User: driveOwner,
}

{

addFileSystemInfo := false
fileSystemInfo := &libregraph.FileSystemInfo{}

if cTime := share.GetCtime(); cTime != nil {
// fixMe:
// - ms uses the root resource ctime for that,
// the stat response does not contain any information about this, use share instead?
fileSystemInfo.CreatedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime))
addFileSystemInfo = true
}

if mTime := resourceInfo.GetMtime(); mTime != nil {
fileSystemInfo.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime))
addFileSystemInfo = addFileSystemInfo
}

if addFileSystemInfo {
remoteItem.FileSystemInfo = fileSystemInfo
}
}

switch resourceInfo.GetType() {
case storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER:
remoteItem.Folder = &libregraph.Folder{}
case storageprovider.ResourceType_RESOURCE_TYPE_FILE:
openGraphFile := &libregraph.OpenGraphFile{}

if mimeType := resourceInfo.GetMimeType(); mimeType != "" {
openGraphFile.MimeType = libregraph.PtrString(mimeType)
}

remoteItem.File = openGraphFile
case storageprovider.ResourceType_RESOURCE_TYPE_INVALID:
// fixMe:
// - return error?
continue
case storageprovider.ResourceType_RESOURCE_TYPE_REFERENCE:
case storageprovider.ResourceType_RESOURCE_TYPE_SYMLINK:
case storageprovider.ResourceType_RESOURCE_TYPE_INTERNAL:
// fixMe:
// - how to handle other types?
}

{
addShared := false
shared := &libregraph.Shared{
Owner: &libregraph.IdentitySet{
User: shareCreator,
},
SharedBy: &libregraph.IdentitySet{
User: shareCreator,
},
}

if cTime := share.GetCtime(); cTime != nil {
shared.SharedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime))
addShared = true
}

if shareCreator != nil {
shared.Owner.User = shareCreator
shared.SharedBy.User = shareCreator
addShared = true
}

if addShared {
remoteItem.Shared = shared
}
}

driveItem.RemoteItem = remoteItem
}

driveItems = append(driveItems, *driveItem)
}

return driveItems, nil
}

0 comments on commit 120fbba

Please sign in to comment.