Skip to content

Commit

Permalink
Use new ocm 1.2 fields from CS3APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
glpatcern committed Feb 18, 2025
1 parent 6e1c8de commit 6e2bdaa
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 45 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/coreos/go-oidc/v3 v3.12.0
github.com/creasty/defaults v1.8.0
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1
github.com/cs3org/go-cs3apis v0.0.0-20250218144737-544dd3919658
github.com/dgraph-io/ristretto v0.2.0
github.com/dolthub/go-mysql-server v0.14.0
github.com/gdexlab/go-render v1.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ func (s *service) getWebdavProtocol(share *ocm.Share, m *ocm.AccessMethod_Webdav

return &ocmd.WebDAV{
Permissions: perms,
Requirements: m.WebdavOptions.Requirements,
URI: s.webdavURL(share),
SharedSecret: share.Token,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/http/services/experimental/sciencemesh/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (h *appsHandler) webappTemplate(ctx context.Context, id *ocmpb.ShareId) (st
return "", errtypes.BadRequest("share does not contain webapp protocol")
}

return webapp.UriTemplate, nil
return webapp.Uri, nil
}

func getWebappProtocol(protocols []*ocmpb.Protocol) (*ocmpb.WebappProtocol, bool) {
Expand Down
6 changes: 3 additions & 3 deletions internal/http/services/experimental/sciencemesh/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) {

perm, viewMode := getPermissionsByRole(req.Role)

log.Debug().Msg("calling gatewayClient.CreateOCMShare from sciencemesh/share.go")
log.Debug().Msg("calling gatewayClient.CreateOCMShare")
shareRes, err := h.gatewayClient.CreateOCMShare(ctx, &ocm.CreateOCMShareRequest{
ResourceId: statRes.Info.Id,
Grantee: &providerpb.Grantee{
Expand All @@ -117,11 +117,11 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) {
},
RecipientMeshProvider: recipientProviderInfo.ProviderInfo,
AccessMethods: []*ocm.AccessMethod{
share.NewWebDavAccessMethod(perm),
share.NewWebDavAccessMethod(perm, []string{}),
share.NewWebappAccessMethod(viewMode),
},
})
log.Debug().Msg("called gatewayClient.CreateOCMShare from sciencemesh/share.go")
log.Debug().Any("response", shareRes).Msg("called gatewayClient.CreateOCMShare")

switch {
case err != nil:
Expand Down
30 changes: 16 additions & 14 deletions internal/http/services/opencloudmesh/ocmd/shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log := appctx.GetLogger(ctx)
req, err := getCreateShareRequest(r)

log.Info().Any("req", req).Msg("OCM /shares request received")
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, err.Error(), nil)
return
}
log.Info().Any("req", req).Msg("OCM /shares request received")

_, meshProvider, err := getIDAndMeshProvider(req.Sender)
log.Debug().Msgf("Determined Mesh Provider '%s' from req.Sender '%s'", meshProvider, req.Sender)
Expand All @@ -99,7 +100,7 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) {
Provider: &providerInfo,
})
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error sending a grpc is provider allowed request", err)
reqres.WriteError(w, r, reqres.APIErrorServerError, "error sending a grpc isProviderAllowed request", err)
return
}
if providerAllowedResp.Status.Code != rpc.Code_CODE_OK {
Expand Down Expand Up @@ -139,7 +140,7 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) {

protocols, err := getAndResolveProtocols(req.Protocols, r)
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, err.Error(), nil)
reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, "error with protocols payload", err)
return
}

Expand Down Expand Up @@ -249,45 +250,46 @@ func getOCMShareType(t string) ocm.ShareType {
func getAndResolveProtocols(p Protocols, r *http.Request) ([]*ocm.Protocol, error) {
protos := make([]*ocm.Protocol, 0, len(p))
for _, data := range p {
var uri string
ocmProto := data.ToOCMProtocol()
protocolName := GetProtocolName(data)
var uri string
var isLocalhost bool

switch protocolName {
case "webdav":
uri = ocmProto.GetWebdavOptions().Uri
isLocalhost = strings.Contains(uri, "localhost")
reqs := ocmProto.GetWebdavOptions().Requirements
if len(reqs) > 0 {
// we currently do not support any kind of requirement
return nil, errtypes.BadRequest(fmt.Sprintf("incoming OCM share with requirements %+v not supported at this endpoint", reqs))
}
case "webapp":
uri = ocmProto.GetWebappOptions().UriTemplate
isLocalhost = strings.Contains(uri, "localhost")
uri = ocmProto.GetWebappOptions().Uri
}

// Irrespective from the presence of a full `uri` in the payload (deprecated), resolve the remote root
// Irrespective from the presence of a full `uri` in the payload (deprecated), validate the
// remote is an OCM server and resolve the remote root
// yet skip this if the remote is localhost (for integration tests)
if isLocalhost {
if strings.Contains(uri, "localhost") {
protos = append(protos, ocmProto)
continue
}
remoteRoot, err := discoverOcmRoot(r, protocolName)
if err != nil {
return nil, err
}
uri, _ = url.JoinPath(remoteRoot, uri[strings.LastIndex(uri, "/")+1:])

uri, _ = url.JoinPath(remoteRoot, uri[strings.LastIndex(uri, "/")+1:])
switch protocolName {
case "webdav":
ocmProto.GetWebdavOptions().Uri = uri
case "webapp":
ocmProto.GetWebappOptions().UriTemplate = uri
ocmProto.GetWebappOptions().Uri = uri
}
protos = append(protos, ocmProto)
}

return protos, nil
}


func discoverOcmRoot(r *http.Request, proto string) (string, error) {
// implements the OCM discovery logic to fetch the root at the remote host that sent the share for the given proto, see
// https://cs3org.github.io/OCM-API/docs.html?branch=v1.1.0&repo=OCM-API&user=cs3org#/paths/~1ocm-provider/get
Expand Down
6 changes: 3 additions & 3 deletions internal/http/services/opencloudmesh/ocmd/specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ type Protocols []Protocol
// Protocol represents the way of access the resource
// in the OCM share.
type Protocol interface {
// ToOCMProtocol converts the protocol to a OCM `Protocol` struct
// ToOCMProtocol converts the protocol to a CS3API OCM `Protocol` struct
ToOCMProtocol() *ocm.Protocol
}

Expand Down Expand Up @@ -131,7 +131,7 @@ func (w *WebDAV) ToOCMProtocol() *ocm.Protocol {
}
}

return ocmshare.NewWebDAVProtocol(w.URI, w.SharedSecret, perms)
return ocmshare.NewWebDAVProtocol(w.URI, w.SharedSecret, perms, w.Requirements)
}

// Webapp contains the parameters for the Webapp protocol.
Expand Down Expand Up @@ -226,7 +226,7 @@ func (p Protocols) MarshalJSON() ([]byte, error) {
for _, prot := range p {
d[GetProtocolName(prot)] = prot
}
// fill in the OCM v1.0 properties: for now we only create OCM 1.1 payloads,
// fill in the OCM v1.0 properties: we only create OCM 1.1+ payloads,
// irrespective from the capabilities of the remote server.
d["name"] = "multi"
d["options"] = map[string]any{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Reque
},
RecipientMeshProvider: providerInfoResp.ProviderInfo,
AccessMethods: []*ocm.AccessMethod{
share.NewWebDavAccessMethod(role.CS3ResourcePermissions()),
share.NewWebDavAccessMethod(role.CS3ResourcePermissions(), []string{}),
share.NewWebappAccessMethod(getViewModeFromRole(role)),
},
})
Expand Down
4 changes: 1 addition & 3 deletions internal/http/services/reqres/reqres.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ type APIError struct {

// WriteError handles writing error responses.
func WriteError(w http.ResponseWriter, r *http.Request, code APIErrorCode, message string, e error) {
if e != nil {
appctx.GetLogger(r.Context()).Error().Err(e).Msg(message)
}
appctx.GetLogger(r.Context()).Error().Err(e).Any("code", code).Str("message", message).Msg("sending back error response")

var encoded []byte
var err error
Expand Down
4 changes: 2 additions & 2 deletions pkg/ocm/share/repository/nextcloud/nextcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (sm *Manager) efssShareToOcm(resp *EfssShare) *ocm.Share {
// first generate the map of access methods, assuming WebDAV is always present
var am = make([]*ocm.AccessMethod, 0, 3)
am = append(am, share.NewWebDavAccessMethod(conversions.RoleFromOCSPermissions(
conversions.Permissions(resp.Protocols.WebDAV.Permissions)).CS3ResourcePermissions()))
conversions.Permissions(resp.Protocols.WebDAV.Permissions)).CS3ResourcePermissions(), []string{}))
if resp.Protocols.WebApp.ViewMode != "" {
am = append(am, share.NewWebappAccessMethod(utils.GetAppViewMode(resp.Protocols.WebApp.ViewMode)))
}
Expand Down Expand Up @@ -326,7 +326,7 @@ func efssReceivedShareToOcm(resp *ReceivedEfssShare) *ocm.ReceivedShare {
var proto = make([]*ocm.Protocol, 0, 3)
proto = append(proto, share.NewWebDAVProtocol(resp.Share.Protocols.WebDAV.URI, resp.Share.Token, &ocm.SharePermissions{
Permissions: conversions.RoleFromOCSPermissions(conversions.Permissions(resp.Share.Protocols.WebDAV.Permissions)).CS3ResourcePermissions(),
}))
}, []string{}))
if resp.Share.Protocols.WebApp.ViewMode != "" {
proto = append(proto, share.NewWebappProtocol(resp.Share.Protocols.WebApp.URI, utils.GetAppViewMode(resp.Share.Protocols.WebApp.ViewMode)))
}
Expand Down
6 changes: 4 additions & 2 deletions pkg/ocm/share/repository/sql/conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ func convertToCS3OCMReceivedShare(s *dbReceivedShare, p []*ocm.Protocol) *ocm.Re
func convertToCS3AccessMethod(m *dbAccessMethod) *ocm.AccessMethod {
switch m.Type {
case WebDAVAccessMethod:
return share.NewWebDavAccessMethod(conversions.RoleFromOCSPermissions(conversions.Permissions(*m.WebDAVPermissions)).CS3ResourcePermissions())
return share.NewWebDavAccessMethod(
conversions.RoleFromOCSPermissions(conversions.Permissions(*m.WebDAVPermissions)).CS3ResourcePermissions(),
[]string{}) // TODO persist requirements
case WebappAccessMethod:
return share.NewWebappAccessMethod(appprovider.ViewMode(*m.WebAppViewMode))
case TransferAccessMethod:
Expand All @@ -281,7 +283,7 @@ func convertToCS3Protocol(p *dbProtocol) *ocm.Protocol {
case WebDAVProtocol:
return share.NewWebDAVProtocol(*p.WebDAVURI, *p.WebDAVSharedSecret, &ocm.SharePermissions{
Permissions: conversions.RoleFromOCSPermissions(conversions.Permissions(*p.WebDavPermissions)).CS3ResourcePermissions(),
})
}, []string{}) // TODO persist requirements
case WebappProtocol:
return share.NewWebappProtocol(*p.WebappURI, appprovider.ViewMode(*p.WebappViewMode))
case TransferProtocol:
Expand Down
2 changes: 1 addition & 1 deletion pkg/ocm/share/repository/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ func storeWebappProtocol(tx *sql.Tx, shareID int64, o *ocm.Protocol_WebappOption
}

query := "INSERT INTO ocm_protocol_webapp SET ocm_protocol_id=?, uri_template=?, view_mode=?"
params := []any{pID, o.WebappOptions.UriTemplate, o.WebappOptions.ViewMode}
params := []any{pID, o.WebappOptions.Uri, o.WebappOptions.ViewMode}

_, err = tx.Exec(query, params...)
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/ocm/share/repository/sql/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func createReceivedShareTables(ctx *sql.Context, initData []*ocm.ReceivedShare)
must(webdav.Insert(ctx, sql.NewRow(i, prot.WebdavOptions.Uri, prot.WebdavOptions.SharedSecret, int64(conversions.RoleFromResourcePermissions(prot.WebdavOptions.Permissions.Permissions).OCSPermissions()))))
case *ocm.Protocol_WebappOptions:
must(protocols.Insert(ctx, sql.NewRow(i, mustInt(share.Id.OpaqueId), int8(WebappProtocol))))
must(webapp.Insert(ctx, sql.NewRow(i, prot.WebappOptions.UriTemplate, int8(prot.WebappOptions.ViewMode))))
must(webapp.Insert(ctx, sql.NewRow(i, prot.WebappOptions.Uri, int8(prot.WebappOptions.ViewMode))))
case *ocm.Protocol_TransferOptions:
must(protocols.Insert(ctx, sql.NewRow(i, mustInt(share.Id.OpaqueId), int8(TransferProtocol))))
must(transfer.Insert(ctx, sql.NewRow(i, prot.TransferOptions.SourceUri, prot.TransferOptions.SharedSecret, int64(prot.TransferOptions.Size))))
Expand Down
14 changes: 8 additions & 6 deletions pkg/ocm/share/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,26 @@ import (
)

// NewWebDAVProtocol is an abstraction for creating a WebDAV protocol.
func NewWebDAVProtocol(uri, sharedSecret string, perms *ocm.SharePermissions) *ocm.Protocol {
func NewWebDAVProtocol(uri, sharedSecret string, perms *ocm.SharePermissions, reqs []string) *ocm.Protocol {
return &ocm.Protocol{
Term: &ocm.Protocol_WebdavOptions{
WebdavOptions: &ocm.WebDAVProtocol{
Uri: uri,
SharedSecret: sharedSecret,
Permissions: perms,
Requirements: reqs,
},
},
}
}

// NewWebappProtocol is an abstraction for creating a Webapp protocol.
func NewWebappProtocol(uriTemplate string, viewMode appprovider.ViewMode) *ocm.Protocol {
func NewWebappProtocol(uri string, viewMode appprovider.ViewMode) *ocm.Protocol {
return &ocm.Protocol{
Term: &ocm.Protocol_WebappOptions{
WebappOptions: &ocm.WebappProtocol{
UriTemplate: uriTemplate,
ViewMode: viewMode,
Uri: uri,
ViewMode: viewMode,
},
},
}
Expand All @@ -63,11 +64,12 @@ func NewTransferProtocol(sourceURI, sharedSecret string, size uint64) *ocm.Proto
}

// NewWebDavAccessMethod is an abstraction for creating a WebDAV access method.
func NewWebDavAccessMethod(perms *provider.ResourcePermissions) *ocm.AccessMethod {
func NewWebDavAccessMethod(perms *provider.ResourcePermissions, reqs []string) *ocm.AccessMethod {
return &ocm.AccessMethod{
Term: &ocm.AccessMethod_WebdavOptions{
WebdavOptions: &ocm.WebDAVAccessMethod{
Permissions: perms,
Permissions: perms,
Requirements: reqs,
},
},
}
Expand Down
48 changes: 41 additions & 7 deletions tests/integration/grpc/ocm_share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewViewerRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewViewerRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand Down Expand Up @@ -278,7 +278,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand Down Expand Up @@ -374,7 +374,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewViewerRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewViewerRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand Down Expand Up @@ -477,7 +477,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand Down Expand Up @@ -626,7 +626,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand All @@ -643,7 +643,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand All @@ -668,7 +668,7 @@ var _ = Describe("ocm share", func() {
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions()),
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expand All @@ -677,6 +677,40 @@ var _ = Describe("ocm share", func() {
})
})

Context("einstein creates a share with a requirement that cannot be met", func() {
It("fail with bad request error", func() {
fileToShare := &provider.Reference{
Path: "/home/file-with-req",
}
By("creating a file")
Expect(helpers.CreateFile(ctxEinstein, cernboxgw, fileToShare.Path, []byte("test"))).To(Succeed())

By("share the file with marie")
info, err := stat(ctxEinstein, cernboxgw, fileToShare)
Expect(err).ToNot(HaveOccurred())

cesnet, err := cernboxgw.GetInfoByDomain(ctxEinstein, &ocmproviderpb.GetInfoByDomainRequest{
Domain: "cesnet.cz",
})
Expect(err).ToNot(HaveOccurred())
Expect(cesnet.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK))

createShareRes, err := cernboxgw.CreateOCMShare(ctxEinstein, &ocmv1beta1.CreateOCMShareRequest{
ResourceId: info.Id,
Grantee: &provider.Grantee{
Id: &provider.Grantee_UserId{
UserId: marie.Id,
},
},
AccessMethods: []*ocmv1beta1.AccessMethod{
share.NewWebDavAccessMethod(conversions.NewEditorRole().CS3ResourcePermissions(), []string{"unsupported-requirement"}),
},
RecipientMeshProvider: cesnet.ProviderInfo,
})
Expect(err).ToNot(HaveOccurred())
Expect(createShareRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_INVALID_ARGUMENT))
})
})
})
})

Expand Down

0 comments on commit 6e2bdaa

Please sign in to comment.