Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ocm fixes #4333

Merged
merged 28 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d78f39c
Use the OCMStorageProvider for accessing ocm shares
aduffeck Nov 7, 2023
30b9513
Make ocm shares available via GetShare()
aduffeck Nov 8, 2023
c6f888e
Implement accepting/rejecting federated shares
aduffeck Nov 8, 2023
cfe2e91
Fix removing federated shares
aduffeck Nov 9, 2023
8cf10e4
Fix write permissions of ocm shares
aduffeck Nov 9, 2023
d92575d
Make the mesh directory URL optional
aduffeck Nov 9, 2023
4c4a47b
Omit empty invite links
aduffeck Nov 9, 2023
404b5f3
Fix typo
aduffeck Nov 10, 2023
caacf8e
Be more robust matching idps
aduffeck Nov 10, 2023
d3ab373
Add changelog
aduffeck Nov 13, 2023
00ff898
Fix wrong paths in path-based ocm propfinds
aduffeck Nov 13, 2023
8618805
Fix integration tests
aduffeck Nov 13, 2023
049bc1d
Fix logic when detecting expired tokens
aduffeck Nov 14, 2023
012e231
Use the actual fileids retrieved from the PROPFIND as the file ids
aduffeck Nov 17, 2023
b33b0d1
Use webdav client fork which supports retrieving custom props
aduffeck Nov 17, 2023
dcefdde
Change format of ocm share file ids to <ocmstorageproviderid>$<sharei…
aduffeck Nov 20, 2023
e79c140
Include remote users in the sharee response
aduffeck Nov 20, 2023
2b5d49c
Allow for disabling the certificate check for webdav connections
aduffeck Nov 21, 2023
2b7bbb3
Fix tests
aduffeck Nov 21, 2023
b6136ac
Include the displayname when requesting all Props
aduffeck Nov 21, 2023
f8e64e0
Fix rw permissions
aduffeck Nov 21, 2023
9011bc7
Change ocm fileids to a base64 representation of the path in the share
aduffeck Nov 22, 2023
fc9701c
Support id based requests
aduffeck Nov 22, 2023
91eec0d
Properly authenticate webdav requests, preventing double requests
aduffeck Nov 23, 2023
e7cb956
Bump gowebdav lib
aduffeck Nov 22, 2023
8644961
Add a flag for including ocm sharees
aduffeck Dec 12, 2023
30a3963
Fix test expectations
aduffeck Dec 12, 2023
9a0c421
Add changelog
aduffeck Dec 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/2.17.0_2023-12-12/ocm.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ Enhancement: Port OCM changes from master

We pulled in the latest ocm changes from master and are now compatible with the main go-cs3apis again.

https://github.com/cs3org/reva/pull/4333
https://github.com/cs3org/reva/pull/4281
https://github.com/cs3org/reva/pull/4239
5 changes: 5 additions & 0 deletions changelog/unreleased/ocm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: Improve OCM support

We fixed several bugs with OCM support.

https://github.com/cs3org/reva/pull/4333
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,5 @@ require (
)

replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20231207143248-4d424e3ae348

replace github.com/studio-b12/gowebdav => github.com/aduffeck/gowebdav v0.0.0-20231123085457-ff658b6ea159
aduffeck marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/aduffeck/gowebdav v0.0.0-20231123085457-ff658b6ea159 h1:m63hhLqbqmLGGPtyTtjTdxae61d9tMbRdKvMaDHWcDs=
github.com/aduffeck/gowebdav v0.0.0-20231123085457-ff658b6ea159/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
Expand Down Expand Up @@ -1210,8 +1212,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423 h1:Wd8WDEEusB5+En4PiRWJp1cP59QLNsQun+mOTW8+s6s=
github.com/studio-b12/gowebdav v0.0.0-20221015232716-17255f2e7423/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE=
Expand Down
7 changes: 7 additions & 0 deletions internal/http/services/ocmd/protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,18 @@ func (w *WebDAV) ToOCMProtocol() *ocm.Protocol {
switch p {
case "read":
perms.Permissions.GetPath = true
perms.Permissions.GetQuota = true
perms.Permissions.InitiateFileDownload = true
perms.Permissions.ListContainer = true
perms.Permissions.ListRecycle = true
perms.Permissions.Stat = true
case "write":
perms.Permissions.InitiateFileUpload = true
perms.Permissions.RestoreRecycleItem = true
perms.Permissions.CreateContainer = true
perms.Permissions.Delete = true
perms.Permissions.Move = true
perms.Permissions.ListGrants = true
case "share":
perms.Reshare = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,6 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
}
shareTypes = utils.ReadPlainFromOpaque(md.Opaque, "share-types")
}

role := conversions.RoleFromResourcePermissions(md.PermissionSet, ls != nil)

if md.Space != nil && md.Space.SpaceType != "grant" && utils.ResourceIDEqual(md.Space.Root, id) {
Expand Down Expand Up @@ -1174,6 +1173,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p

if md.Name != "" {
appendToOK(prop.Escaped("oc:name", md.Name))
appendToOK(prop.Escaped("d:displayname", md.Name))
}

if md.Etag != "" {
Expand Down
1 change: 1 addition & 0 deletions internal/http/services/owncloud/ocs/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Config struct {
OCMMountPoint string `mapstructure:"ocm_mount_point"`
ListOCMShares bool `mapstructure:"list_ocm_shares"`
Notifications map[string]interface{} `mapstructure:"notifications"`
IncludeOCMSharees bool `mapstructure:"include_ocm_sharees"`
}

// Init sets sane defaults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
invitepb "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
"github.com/cs3org/reva/v2/pkg/conversions"

"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/config"
Expand All @@ -37,12 +39,14 @@ import (
type Handler struct {
gatewayAddr string
additionalInfoAttribute string
includeOCMSharees bool
}

// Init initializes this and any contained handlers
func (h *Handler) Init(c *config.Config) {
h.gatewayAddr = c.GatewaySvc
h.additionalInfoAttribute = c.AdditionalInfoAttribute
h.includeOCMSharees = c.IncludeOCMSharees
}

// FindSharees implements the /apps/files_sharing/api/v1/sharees endpoint
Expand Down Expand Up @@ -79,6 +83,27 @@ func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) {
}
}

if h.includeOCMSharees {
remoteUsersRes, err := gwc.FindAcceptedUsers(r.Context(), &invitepb.FindAcceptedUsersRequest{Filter: term})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error searching remote users", err)
return
}
if remoteUsersRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error searching remote users", nil)
return
}
for _, user := range remoteUsersRes.GetAcceptedUsers() {
match := h.userAsMatch(user)
log.Debug().Interface("user", user).Interface("match", match).Msg("mapped")
if h.isExactMatch(match, term) {
exactUserMatches = append(exactUserMatches, match)
} else {
userMatches = append(userMatches, match)
}
}
}

groupsRes, err := gwc.FindGroups(r.Context(), &grouppb.FindGroupsRequest{Filter: term, SkipFetchingMembers: true})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error searching groups", err)
Expand Down Expand Up @@ -111,21 +136,27 @@ func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) {
}

func (h *Handler) userAsMatch(u *userpb.User) *conversions.MatchData {
var ocsUserType int
if u.Id.Type == userpb.UserType_USER_TYPE_GUEST || u.Id.Type == userpb.UserType_USER_TYPE_LIGHTWEIGHT {
ocsUserType = 1
data := &conversions.MatchValueData{
ShareType: int(conversions.ShareTypeUser),
// api compatibility with oc10: mark guest users in share invite dialogue
UserType: 0,
// api compatibility with oc10: always use the username
ShareWith: u.Username,
ShareWithAdditionalInfo: h.getAdditionalInfoAttribute(u),
}

switch u.Id.Type {
case userpb.UserType_USER_TYPE_GUEST, userpb.UserType_USER_TYPE_LIGHTWEIGHT:
data.UserType = 1
case userpb.UserType_USER_TYPE_FEDERATED:
data.ShareType = int(conversions.ShareTypeFederatedCloudShare)
data.ShareWith = u.Id.OpaqueId
data.ShareWithProvider = u.Id.Idp
}

return &conversions.MatchData{
Label: u.DisplayName,
Value: &conversions.MatchValueData{
ShareType: int(conversions.ShareTypeUser),
// api compatibility with oc10: mark guest users in share invite dialogue
UserType: ocsUserType,
// api compatibility with oc10: always use the username
ShareWith: u.Username,
ShareWithAdditionalInfo: h.getAdditionalInfoAttribute(u),
},
Value: data,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
ocmv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/response"
"github.com/cs3org/reva/v2/pkg/appctx"
Expand All @@ -50,6 +51,12 @@ const (
func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
shareID := chi.URLParam(r, shareidkey)

if h.isFederatedReceivedShare(r, shareID) {
h.updateReceivedFederatedShare(w, r, shareID, false)
return
}

client, err := h.getClient()
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err)
Expand Down Expand Up @@ -148,6 +155,12 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) {
// RejectReceivedShare handles DELETE Requests on /apps/files_sharing/api/v1/shares/{shareid}
func (h *Handler) RejectReceivedShare(w http.ResponseWriter, r *http.Request) {
shareID := chi.URLParam(r, "shareid")

if h.isFederatedReceivedShare(r, shareID) {
h.updateReceivedFederatedShare(w, r, shareID, true)
return
}

// we need to add a path to the share
receivedShare := &collaboration.ReceivedShare{
Share: &collaboration.Share{
Expand Down Expand Up @@ -254,6 +267,76 @@ func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, re
return data
}

func (h *Handler) updateReceivedFederatedShare(w http.ResponseWriter, r *http.Request, shareID string, rejectShare bool) {
ctx := r.Context()

client, err := h.getClient()
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err)
return
}

share, err := client.GetReceivedOCMShare(ctx, &ocmv1beta1.GetReceivedOCMShareRequest{
Ref: &ocmv1beta1.ShareReference{
Spec: &ocmv1beta1.ShareReference_Id{
Id: &ocmv1beta1.ShareId{
OpaqueId: shareID,
},
},
},
})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", err)
return
}
if share.Status.Code != rpc.Code_CODE_OK {
if share.Status.Code == rpc.Code_CODE_NOT_FOUND {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "not found", nil)
return
}
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", errors.Errorf("code: %d, message: %s", share.Status.Code, share.Status.Message))
return
}

req := &ocmv1beta1.UpdateReceivedOCMShareRequest{
Share: &ocmv1beta1.ReceivedShare{
Id: &ocmv1beta1.ShareId{
OpaqueId: shareID,
},
},
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}},
}
if rejectShare {
req.Share.State = ocmv1beta1.ShareState_SHARE_STATE_REJECTED
} else {
req.Share.State = ocmv1beta1.ShareState_SHARE_STATE_ACCEPTED
}

updateRes, err := client.UpdateReceivedOCMShare(ctx, req)
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", err)
return
}

if updateRes.Status.Code != rpc.Code_CODE_OK {
if updateRes.Status.Code == rpc.Code_CODE_NOT_FOUND {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "not found", nil)
return
}
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", errors.Errorf("code: %d, message: %s", updateRes.Status.Code, updateRes.Status.Message))
return
}

data, err := conversions.ReceivedOCMShare2ShareData(share.Share, h.ocmLocalMount(share.Share))
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", err)
return
}
h.mapUserIdsReceivedFederatedShare(ctx, client, data)
data.State = mapOCMState(req.Share.State)
response.WriteOCSSuccess(w, r, []*conversions.ShareData{data})
}

// getReceivedShareHideFlagFromShareId returns the hide flag of a received share based on its ID.
func (h *Handler) getReceivedShareHideFlagFromShareID(ctx context.Context, shareID string) bool {
client, err := h.getClient()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Reque
return
}

shareWithUser, shareWithProvider := r.FormValue("shareWithUser"), r.FormValue("shareWithProvider")
shareWithUser, shareWithProvider := r.FormValue("shareWith"), r.FormValue("shareWithProvider")
if shareWithUser == "" || shareWithProvider == "" {
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "missing shareWith parameters", nil)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/types/known/fieldmaskpb"

ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
ocmv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/config"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/response"
Expand Down Expand Up @@ -642,6 +643,66 @@ func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) {
}
}

if share == nil {
// check if we have a federated share
req := &ocm.GetOCMShareRequest{
Ref: &ocm.ShareReference{
Spec: &ocm.ShareReference_Id{
Id: &ocm.ShareId{
OpaqueId: shareID,
},
},
},
}
ocmShareResponse, err := client.GetOCMShare(ctx, req)
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc get ocm share request", err)
return
}

ocmShare := ocmShareResponse.GetShare()
if ocmShare != nil {
resourceID = ocmShare.ResourceId
share, err = conversions.OCMShare2ShareData(ocmShare)
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
return
}
}
}

if share == nil {
// check if we have an incoming federated share
req := &ocm.GetReceivedOCMShareRequest{
Ref: &ocm.ShareReference{
Spec: &ocm.ShareReference_Id{
Id: &ocm.ShareId{
OpaqueId: shareID,
},
},
},
}
ocmShareResponse, err := client.GetReceivedOCMShare(ctx, req)
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc get ocm share request", err)
return
}

ocmShare := ocmShareResponse.GetShare()
if ocmShare != nil {
resourceID = &provider.ResourceId{
StorageId: utils.OCMStorageProviderID,
SpaceId: ocmShare.Id.OpaqueId,
OpaqueId: ocmShare.Id.OpaqueId,
}
share, err = conversions.ReceivedOCMShare2ShareData(ocmShare, h.ocmLocalMount(ocmShare))
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err)
return
}
}
}

if share == nil {
sublog.Debug().Msg("no share found with this id")
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "share not found", nil)
Expand Down Expand Up @@ -857,6 +918,10 @@ func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) {
h.removeUserShare(w, r, share)
return
}
if h.isFederatedShare(r, shareID) {
h.removeFederatedShare(w, r, shareID)
return
}

if prov, ok := h.isSpaceShare(r, shareID); ok {
// The request is a remove space member request.
Expand Down
Loading
Loading