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

Create and list OCM shares in OCS layer #3692

Merged
merged 26 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
204b47f
create and list ocm shares
gmgigi96 Feb 21, 2023
f3cef0d
send provider in user find response
gmgigi96 Feb 22, 2023
9caeb7e
send correct user type
gmgigi96 Feb 22, 2023
b13f8a4
fix table name
gmgigi96 Feb 22, 2023
eb6e615
fix sql query for storing share
gmgigi96 Feb 22, 2023
891dfdc
fix ctime and mtime for received share
gmgigi96 Feb 22, 2023
5e9f223
fix scan received share
gmgigi96 Feb 22, 2023
7146349
fix expiration parsing in ocs layer
gmgigi96 Feb 23, 2023
202ed91
fix expiration convertion on received shared
gmgigi96 Feb 23, 2023
fe96a22
better error handling creating federated share
gmgigi96 Feb 23, 2023
8d49ebb
set provider domain in config when forwarding invitation token
gmgigi96 Feb 23, 2023
7d0b3ae
fix provider domain on sharing
gmgigi96 Feb 23, 2023
edae293
add item source and item type in list federated response
gmgigi96 Feb 23, 2023
45f6329
fix expiration for ocm shares
gmgigi96 Feb 23, 2023
2d29d24
fix name resolution
gmgigi96 Feb 23, 2023
5f0020d
fix users for received share
gmgigi96 Feb 23, 2023
2084c98
add mimetype to received share
gmgigi96 Feb 23, 2023
f36aeaa
fill file target
gmgigi96 Feb 23, 2023
b0e0a49
unescape path in ocm storage
gmgigi96 Feb 23, 2023
e03da7f
return proper error when resource is not found in ocm storage driver
gmgigi96 Feb 24, 2023
2991c49
add changelog
gmgigi96 Feb 28, 2023
9ebccdd
fix linting
gmgigi96 Feb 28, 2023
83eb682
fix tests
gmgigi96 Feb 28, 2023
84abef8
fix integration tests
gmgigi96 Mar 1, 2023
39a34f8
make configuratble ocm shares in ocs list response
gmgigi96 Mar 1, 2023
ae5711e
fix linter
gmgigi96 Mar 1, 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
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
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