Skip to content

Commit

Permalink
[wip] graph sharing: UpdatePermissions
Browse files Browse the repository at this point in the history
  • Loading branch information
rhafer committed Nov 30, 2023
1 parent 2cbb62e commit 211e98d
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 2 deletions.
78 changes: 78 additions & 0 deletions services/graph/pkg/service/v0/driveitems.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,55 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, &ListResponse{Value: value})
}

// UpdatePermission updates a Permission of a Drive item
func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) {
_, itemID, err := g.GetDriveAndItemIDParam(r)
if err != nil {
errorcode.RenderError(w, r, err)
return
}

permissionID, err := url.PathUnescape(chi.URLParam(r, "permissionID"))

if err != nil {
g.logger.Debug().Err(err).Msg("could not parse driveID")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "invalid driveID")
return
}

permission := &libregraph.Permission{}
if err := StrictJSONUnmarshal(r.Body, permission); err != nil {
g.logger.Debug().Err(err).Interface("Body", r.Body).Msg("failed unmarshalling request body")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "invalid request body")
return
}

ctx := r.Context()
if err := validate.StructCtx(ctx, permission); err != nil {
g.logger.Debug().Err(err).Interface("Body", r.Body).Msg("invalid request body")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}

_, sharedResourceId, err := g.getPermissionByID(ctx, permissionID)
if err != nil {
errorcode.RenderError(w, r, err)
return
}

// The resourceID of the shared resource need to match the item ID from the Request Path
// otherwise this is an invalid Request.
if !utils.ResourceIDEqual(sharedResourceId, &itemID) {
g.logger.Debug().Msg("resourceID of shared does not match itemID")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "permissionID and itemID do not match")
return
}

// TODO HERE the magic happens
render.Status(r, http.StatusNotImplemented)
return
}

// DeletePermission removes a Permission from a Drive item
func (g Graph) DeletePermission(w http.ResponseWriter, r *http.Request) {
_, itemID, err := g.GetDriveAndItemIDParam(r)
Expand Down Expand Up @@ -667,6 +716,35 @@ func (g Graph) DeletePermission(w http.ResponseWriter, r *http.Request) {
return
}

func (g Graph) getPermissionByID(ctx context.Context, permissionID string) (*libregraph.Permission, *storageprovider.ResourceId, error) {
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Debug().Err(err).Msg("selecting gatewaySelector failed")
return nil, nil, err
}

getShareResp, err := gatewayClient.GetShare(ctx,
&collaboration.GetShareRequest{
Ref: &collaboration.ShareReference{
Spec: &collaboration.ShareReference_Id{
Id: &collaboration.ShareId{
OpaqueId: permissionID,
},
},
},
})
var errcode *errorcode.Error
if errcode = errorcode.FromCS3Status(getShareResp.GetStatus(), err); errcode != nil {
return nil, nil, *errcode
}

permission, err := g.cs3UserShareToPermission(ctx, getShareResp.GetShare())
if err != nil {
return nil, nil, err
}
return permission, getShareResp.GetShare().GetResourceId(), nil
}

func (g Graph) getUserPermissionResourceID(ctx context.Context, permissionID string) (*storageprovider.ResourceId, error) {
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
Expand Down
82 changes: 82 additions & 0 deletions services/graph/pkg/service/v0/driveitems_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,88 @@ var _ = Describe("Driveitems", func() {
})
})

Describe("UpdatePermission", func() {
var (
driveItemPermission *libregraph.Permission
getShareMockResponse *collaboration.GetShareResponse
getPublicShareMockResponse *link.GetPublicShareResponse
// updateShareMockResponse *collaboration.UpdateShareResponse
)
BeforeEach(func() {
rctx := chi.NewRouteContext()
rctx.URLParams.Add("driveID", "1$2")
rctx.URLParams.Add("itemID", "1$2!3")
rctx.URLParams.Add("permissionID", "permissionid")

ctx = context.WithValue(ctx, chi.RouteCtxKey, rctx)
ctx = revactx.ContextSetUser(ctx, currentUser)

driveItemPermission = &libregraph.Permission{
Id: libregraph.PtrString("permissionid"),
}

getShareMock := gatewayClient.On("GetShare",
mock.Anything,
mock.MatchedBy(func(req *collaboration.GetShareRequest) bool {
return req.GetRef().GetId().GetOpaqueId() == "permissionid"
}),
)
getShareMockResponse = &collaboration.GetShareResponse{
Status: status.NewOK(ctx),
Share: &collaboration.Share{
Id: &collaboration.ShareId{
OpaqueId: "permissionid",
},
ResourceId: &provider.ResourceId{
StorageId: "1",
SpaceId: "2",
OpaqueId: "3",
},
},
}

getShareMock.Return(getShareMockResponse, nil)
getPublicShareMock := gatewayClient.On("GetPublicShare",
mock.Anything,
mock.MatchedBy(func(req *link.GetPublicShareRequest) bool {
return req.GetRef().GetId().GetOpaqueId() == "permissionid"
}),
)
getPublicShareMockResponse = &link.GetPublicShareResponse{
Status: status.NewOK(ctx),
Share: &link.PublicShare{
Id: &link.PublicShareId{
OpaqueId: "permissionid",
},
ResourceId: &provider.ResourceId{
StorageId: "1",
SpaceId: "2",
OpaqueId: "3",
},
},
}
getPublicShareMock.Return(getPublicShareMockResponse, nil)
})
It("fails when no share is found", func() {
expiratonTime := time.Now().Add(time.Hour)
driveItemPermission.ExpirationDateTime.Set(&expiratonTime)

getShareMockResponse.Share = nil
getShareMockResponse.Status = status.NewNotFound(ctx, "not found")
getPublicShareMockResponse.Share = nil
getPublicShareMockResponse.Status = status.NewNotFound(ctx, "not found")

body, err := driveItemPermission.MarshalJSON()
Expect(err).To(BeNil())
svc.UpdatePermission(
rr,
httptest.NewRequest(http.MethodPatch, "/", strings.NewReader(string(body))).
WithContext(ctx),
)
Expect(rr.Code).To(Equal(http.StatusNotFound))
})
})

Describe("Invite", func() {
var (
driveItemInvite *libregraph.DriveItemInvite
Expand Down
10 changes: 8 additions & 2 deletions services/graph/pkg/service/v0/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type Service interface {

Invite(w http.ResponseWriter, r *http.Request)
ListPermissions(w http.ResponseWriter, r *http.Request)
UpdatePermission(w http.ResponseWriter, r *http.Request)
DeletePermission(w http.ResponseWriter, r *http.Request)

CreateUploadSession(w http.ResponseWriter, r *http.Request)
Expand Down Expand Up @@ -205,8 +206,13 @@ func NewService(opts ...Option) (Graph, error) {
r.Get("/me/drive/sharedWithMe", svc.ListSharedWithMe)
r.Route("/drives/{driveID}/items/{itemID}", func(r chi.Router) {
r.Post("/invite", svc.Invite)
r.Get("/permissions", svc.ListPermissions)
r.Delete("/permissions/{permissionID}", svc.DeletePermission)
r.Route("/permissions", func(r chi.Router) {
r.Get("/", svc.ListPermissions)
r.Route("/{permissionID}", func(r chi.Router) {
r.Delete("/", svc.DeletePermission)
r.Patch("/", svc.UpdatePermission)
})
})
r.Post("/createLink", svc.CreateLink)
})
r.Route("/roleManagement/permissions/roleDefinitions", func(r chi.Router) {
Expand Down
10 changes: 10 additions & 0 deletions services/graph/pkg/validate/libregraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,13 @@ func driveItemInvite(v *validator.Validate) {

}, s)
}

// permission validates libregraph.Permission
func permission(v *validator.Validate) {
s := libregraph.Permission{}

v.RegisterStructValidationMapRules(map[string]string{
"Roles": "max=1",
"ExpirationDateTime": "omitnil,gt",
}, s)
}

0 comments on commit 211e98d

Please sign in to comment.