Skip to content

Commit

Permalink
enhancement: add graph beta sharedWithMe API
Browse files Browse the repository at this point in the history
  • Loading branch information
fschade committed Nov 3, 2023
1 parent cbfd894 commit 0c80c9e
Show file tree
Hide file tree
Showing 8 changed files with 389 additions and 12 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
3 changes: 3 additions & 0 deletions go.mod
Expand Up @@ -304,6 +304,9 @@ 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/gjson v1.17.0 // 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
7 changes: 7 additions & 0 deletions go.sum
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
7 changes: 6 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,7 +202,9 @@ func NewService(opts ...Option) (Graph, error) {

m.Route(options.Config.HTTP.Root, func(r chi.Router) {
r.Use(middleware.StripSlashes)
// fixMe, add beta group to the libre graph api
r.Route("/v1.0", func(r chi.Router) {
r.Get("/me/drive/sharedWithMe", svc.ListSharedWithMe)
r.Route("/extensions/org.libregraph", func(r chi.Router) {
r.Get("/tags", svc.GetTags)
r.Put("/tags", svc.AssignTags)
Expand Down
147 changes: 147 additions & 0 deletions services/graph/pkg/service/v0/sharedwithme.go
@@ -0,0 +1,147 @@
package svc

import (
"context"
"net/http"
"path"

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/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 returns a list of all driveItems shared with the user
//
// urls:
// - https://host.docker.internal:9200/ocs/v1.php/apps/files_sharing/api/v1/shares?include_tags=false&state=all&show_hidden=true&shared_with_me=true
//
// todo:
// show-hidden or show_hidden
//
// ambiguity:
// include_tags query param -> web uses it, but what is it for?
// path query param -> web doesn't use it
// share_ref query param -> web doesn't use it
// share_types query param -> web doesn't use it
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 _, share := range listReceivedSharesResponse.GetShares() {
if share.Hidden && !showHidden {
continue
}

stat, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: share.Share.ResourceId}})
if err != nil {
// fixMe: return err!?
continue
}
if stat.Status.Code != rpc.Code_CODE_OK {
// fixMe: return err!?
continue
}

driveItem := &libregraph.DriveItem{
RemoteItem: &libregraph.RemoteItem{},
}

// driveItem.remoteItem
// ✅ createdBy IdentitySet Identity of the user, device, and application which created the item. Read-only.
// ✅ createdDateTime Timestamp Date and time of item creation. Read-only.
// ❌ file File Indicates that the remote item is a file. Read-only.
// ❌ fileSystemInfo FileSystemInfo Information about the remote item from the local file system. Read-only.
// ❌ folder Folder Indicates that the remote item is a folder. Read-only.
// ✅ id String Unique identifier for the remote item in its drive. Read-only.
// ❌ image Image Image metadata, if the item is an image. Read-only.
// ❌ lastModifiedBy IdentitySet Identity of the user, device, and application which last modified the item. Read-only.
// ✅ lastModifiedDateTime Timestamp Date and time the item was last modified. Read-only.
// ✅ name String Optional. Filename of the remote item. Read-only.
// ❌ package Package If present, indicates that this item is a package instead of a folder or file. Packages are treated like files in some contexts and folders in others. Read-only.
// ❌ parentReference ItemReference Properties of the parent of the remote item. Read-only.
// ❌ shared shared Indicates that the item has been shared with others and provides information about the shared state of the item. Read-only.
// ❌ sharepointIds SharepointIds Provides interop between items in OneDrive for Business and SharePoint with the full set of item identifiers. Read-only.
// ✅ size Int64 Size of the remote item. Read-only.
// ❌ specialFolder specialFolder If the current item is also available as a special folder, this facet is returned. Read-only.
// ❌ video Video Video metadata, if the item is a video. Read-only.
// ❌ webDavUrl Url DAV compatible URL for the item.
// ❌ webUrl Url URL that displays the resource in the browser. Read-only.

if share.Share.Id != nil {
driveItem.RemoteItem.Id = libregraph.PtrString(share.Share.Id.OpaqueId)
}

if share.Share.Creator != nil {
if getUserResponse, err := gatewayClient.GetUser(ctx, &userpb.GetUserRequest{
UserId: &userpb.UserId{
OpaqueId: share.Share.Creator.OpaqueId,
},
SkipFetchingUserGroups: true,
}); err != nil {
// fixMe: return err!?
continue
} else {
user := libregraph.NewIdentityWithDefaults()
user.SetId(getUserResponse.GetUser().GetId().GetOpaqueId())
user.SetDisplayName(getUserResponse.GetUser().GetDisplayName())

// fixMe:
// - IdentitySet Application
// - IdentitySet Device
// - IdentitySet Group
driveItem.RemoteItem.CreatedBy = &libregraph.IdentitySet{
User: user,
}
}
}

if share.Share.Ctime != nil {
driveItem.RemoteItem.CreatedDateTime = libregraph.PtrTime(cs3TimestampToTime(share.Share.Ctime))
}

if share.Share.Mtime != nil {
driveItem.RemoteItem.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(share.Share.Mtime))
}

driveItem.RemoteItem.Size = libregraph.PtrInt64(int64(stat.Info.Size))

if name := path.Base(stat.Info.Path); name != "" {
driveItem.RemoteItem.Name = libregraph.PtrString(name)
}

driveItems = append(driveItems, *driveItem)
}

return driveItems, nil
}

0 comments on commit 0c80c9e

Please sign in to comment.