Skip to content

Commit

Permalink
Create and list OCM shares in OCS layer (#3692)
Browse files Browse the repository at this point in the history
* create and list ocm shares

* send provider in user find response

* send correct user type

* fix table name

* fix sql query for storing share

* fix ctime and mtime for received share

* fix scan received share

* fix expiration parsing in ocs layer

* fix expiration convertion on received shared

* better error handling creating federated share

* set provider domain in config when forwarding invitation token

* fix provider domain on sharing

* add item source and item type in list federated response

* fix expiration for ocm shares

* fix name resolution

* fix users for received share

* add mimetype to received share

* fill file target

* unescape path in ocm storage

* return proper error when resource is not found in ocm storage driver

* add changelog

* fix linting

* fix tests

* fix integration tests

* make configuratble ocm shares in ocs list response

* fix linter
  • Loading branch information
gmgigi96 authored Mar 1, 2023
1 parent 2e0d2b9 commit 7f8d5d8
Show file tree
Hide file tree
Showing 21 changed files with 405 additions and 119 deletions.
3 changes: 3 additions & 0 deletions changelog/unreleased/ocm-create-list-shares-ocs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Enhancement: Create and list OCM shares in OCS layer

https://github.com/cs3org/reva/pull/3692
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ require (
github.com/sciencemesh/meshdirectory-web v1.0.4
github.com/sethvargo/go-password v0.2.0
github.com/stretchr/testify v1.8.1
github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2
github.com/thanhpk/randstr v1.0.4
github.com/tus/tusd v1.10.0
github.com/wk8/go-ordered-map v1.0.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df h1:C+J/LwTqP8gRPt1MdSzBNZP0OYuDm5wsmDKgwpLjYzo=
github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s=
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2 h1:VsBj3UD2xyAOu7kJw6O/2jjG2UXLFoBzihqDU9Ofg9M=
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
Expand Down
8 changes: 8 additions & 0 deletions internal/grpc/services/ocmcore/ocmcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ package ocmcore
import (
"context"
"fmt"
"time"

ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1"
ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/ocm/share"
"github.com/cs3org/reva/pkg/ocm/share/repository/registry"
Expand Down Expand Up @@ -110,6 +112,10 @@ func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCM
return nil, errtypes.NotSupported("share type not supported")
}

now := &typesv1beta1.Timestamp{
Seconds: uint64(time.Now().Unix()),
}

share, err := s.repo.StoreReceivedShare(ctx, &ocm.ReceivedShare{
ResourceId: &providerpb.ResourceId{
OpaqueId: req.ResourceId,
Expand All @@ -126,6 +132,8 @@ func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCM
Owner: req.Owner,
Creator: req.Sender,
Protocols: req.Protocols,
Ctime: now,
Mtime: now,
Expiration: req.Expiration,
State: ocm.ShareState_SHARE_STATE_PENDING,
})
Expand Down
3 changes: 2 additions & 1 deletion internal/grpc/services/ocminvitemanager/ocminvitemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type config struct {
OCMClientTimeout int `mapstructure:"ocm_timeout"`
OCMClientInsecure bool `mapstructure:"ocm_insecure"`
GatewaySVC string `mapstructure:"gateway_svc"`
ProviderDomain string `mapstructure:"provider_domain" docs:"The same domain registered in the provider authorizer"`

tokenExpiration time.Duration
}
Expand Down Expand Up @@ -174,7 +175,7 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite

remoteUser, err := s.ocmClient.InviteAccepted(ctx, ocmEndpoint, &client.InviteAcceptedRequest{
Token: req.InviteToken.GetToken(),
RecipientProvider: user.GetId().GetIdp(),
RecipientProvider: s.conf.ProviderDomain,
UserID: user.GetId().GetOpaqueId(),
Email: user.GetMail(),
Name: user.GetDisplayName(),
Expand Down
17 changes: 12 additions & 5 deletions internal/grpc/services/ocmshareprovider/ocmshareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type config struct {
ClientInsecure bool `mapstructure:"client_insecure"`
GatewaySVC string `mapstructure:"gatewaysvc"`
WebDAVPrefix string `mapstructure:"webdav_prefix"`
ProviderDomain string `mapstructure:"provider_domain" docs:"The same domain registered in the provider authorizer"`
}

type service struct {
Expand Down Expand Up @@ -270,11 +271,17 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq
}

newShareReq := &client.NewShareRequest{
ShareWith: formatOCMUser(req.Grantee.GetUserId()),
Name: ocmshare.Name,
ResourceID: fmt.Sprintf("%s:%s", req.ResourceId.StorageId, req.ResourceId.OpaqueId),
Owner: formatOCMUser(info.Owner),
Sender: formatOCMUser(user.Id),
ShareWith: formatOCMUser(req.Grantee.GetUserId()),
Name: ocmshare.Name,
ResourceID: fmt.Sprintf("%s:%s", req.ResourceId.StorageId, req.ResourceId.OpaqueId),
Owner: formatOCMUser(&userpb.UserId{
OpaqueId: info.Owner.OpaqueId,
Idp: s.conf.ProviderDomain, // FIXME: this is not generally true in case of resharing
}),
Sender: formatOCMUser(&userpb.UserId{
OpaqueId: user.Id.OpaqueId,
Idp: s.conf.ProviderDomain,
}),
SenderDisplayName: user.DisplayName,
ShareType: "user",
ResourceType: getResourceType(info),
Expand Down
2 changes: 2 additions & 0 deletions internal/http/services/owncloud/ocs/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type Config struct {
ResourceInfoCacheDrivers map[string]map[string]interface{} `mapstructure:"resource_info_caches"`
UserIdentifierCacheTTL int `mapstructure:"user_identifier_cache_ttl"`
AllowedLanguages []string `mapstructure:"allowed_languages"`
OCMMountPoint string `mapstructure:"ocm_mount_point"`
ListOCMShares bool `mapstructure:"list_ocm_shares"`
}

// Init sets sane defaults.
Expand Down
80 changes: 80 additions & 0 deletions internal/http/services/owncloud/ocs/conversions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ import (
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/mime"
"github.com/cs3org/reva/pkg/publicshare"
publicsharemgr "github.com/cs3org/reva/pkg/publicshare/manager/registry"
"github.com/cs3org/reva/pkg/user"
Expand Down Expand Up @@ -173,6 +176,7 @@ type MatchData struct {
type MatchValueData struct {
ShareType int `json:"shareType" xml:"shareType"`
ShareWith string `json:"shareWith" xml:"shareWith"`
ShareWithProvider string `json:"shareWithProvider" xml:"shareWithProvider"`
ShareWithAdditionalInfo string `json:"shareWithAdditionalInfo" xml:"shareWithAdditionalInfo"`
}

Expand Down Expand Up @@ -242,6 +246,82 @@ func PublicShare2ShareData(share *link.PublicShare, r *http.Request, publicURL s
return sd
}

func formatRemoteUser(u *userpb.UserId) string {
return fmt.Sprintf("%s@%s", u.OpaqueId, u.Idp)
}

func webdavInfo(protocols []*ocm.Protocol) (*ocm.WebDAVProtocol, bool) {
for _, p := range protocols {
if opt, ok := p.Term.(*ocm.Protocol_WebdavOptions); ok {
return opt.WebdavOptions, true
}
}
return nil, false
}

// ReceivedOCMShare2ShareData converts a cs3 ocm received share into a share data model.
func ReceivedOCMShare2ShareData(share *ocm.ReceivedShare, path string) (*ShareData, error) {
webdav, ok := webdavInfo(share.Protocols)
if !ok {
return nil, errtypes.InternalError("webdav endpoint not in share")
}

s := &ShareData{
ID: share.Id.OpaqueId,
UIDOwner: formatRemoteUser(share.Creator),
UIDFileOwner: formatRemoteUser(share.Owner),
ShareWith: share.Grantee.GetUserId().OpaqueId,
Permissions: RoleFromResourcePermissions(webdav.Permissions.Permissions).OCSPermissions(),
ShareType: ShareTypeFederatedCloudShare,
Path: path,
FileTarget: path,
MimeType: mime.Detect(share.ResourceType == provider.ResourceType_RESOURCE_TYPE_CONTAINER, share.Name),
ItemType: ResourceType(share.ResourceType).String(),
ItemSource: path,
STime: share.Ctime.Seconds,
Name: share.Name,
}

if share.Expiration != nil {
s.Expiration = timestampToExpiration(share.Expiration)
}
return s, nil
}

func webdavAMInfo(methods []*ocm.AccessMethod) (*ocm.WebDAVAccessMethod, bool) {
for _, a := range methods {
if opt, ok := a.Term.(*ocm.AccessMethod_WebdavOptions); ok {
return opt.WebdavOptions, true
}
}
return nil, false
}

// OCMShare2ShareData converts a cs3 ocm share into a share data model.
func OCMShare2ShareData(share *ocm.Share) (*ShareData, error) {
webdav, ok := webdavAMInfo(share.AccessMethods)
if !ok {
return nil, errtypes.InternalError("webdav endpoint not in share")
}

s := &ShareData{
ID: share.Id.OpaqueId,
UIDOwner: share.Creator.OpaqueId,
UIDFileOwner: share.Owner.OpaqueId,
ShareWith: formatRemoteUser(share.Grantee.GetUserId()),
Permissions: RoleFromResourcePermissions(webdav.Permissions).OCSPermissions(),
ShareType: ShareTypeFederatedCloudShare,
STime: share.Ctime.Seconds,
Name: share.Name,
}

if share.Expiration != nil {
s.Expiration = timestampToExpiration(share.Expiration)
}

return s, nil
}

// LocalUserIDToString transforms a cs3api user id into an ocs data model without domain name
// TODO ocs uses user names ... so an additional lookup is needed. see mapUserIds().
func LocalUserIDToString(userID *userpb.UserId) string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,23 @@ func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) {
}

func (h *Handler) userAsMatch(u *userpb.User) *conversions.MatchData {
shareWith := u.Username
if shareWith == "" {
shareWith = u.Id.OpaqueId
}

shareType := conversions.ShareTypeUser
if u.Id.Type == userpb.UserType_USER_TYPE_FEDERATED {
shareType = conversions.ShareTypeFederatedCloudShare
}

return &conversions.MatchData{
Label: u.DisplayName,
Value: &conversions.MatchValueData{
ShareType: int(conversions.ShareTypeUser),
ShareType: int(shareType),
// api compatibility with oc10: always use the username
ShareWith: u.Username,
ShareWith: shareWith,
ShareWithProvider: u.Id.Idp,
ShareWithAdditionalInfo: h.getAdditionalInfoAttribute(u),
},
}
Expand Down
Loading

0 comments on commit 7f8d5d8

Please sign in to comment.