diff --git a/changelog/unreleased/fix-ocm-weddav.md b/changelog/unreleased/fix-ocm-weddav.md new file mode 100644 index 00000000000..c6769985d21 --- /dev/null +++ b/changelog/unreleased/fix-ocm-weddav.md @@ -0,0 +1,5 @@ +Bugfix: OCM Specification Compliance + +OCM Specification Compliance + +https://github.com/owncloud/ocis/pull/11773 diff --git a/go.mod b/go.mod index cde997c5207..5b7445b35af 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/open-policy-agent/opa v1.6.0 github.com/orcaman/concurrent-map v1.0.0 github.com/owncloud/libre-graph-api-go v1.0.5-0.20250217093259-fa3804be6c27 - github.com/owncloud/reva/v2 v2.0.0-20251017104024-82c22e954c1c + github.com/owncloud/reva/v2 v2.0.0-20251106102926-751223b32d48 github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.12 github.com/prometheus/client_golang v1.23.2 @@ -335,7 +335,6 @@ require ( golang.org/x/sys v0.37.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.37.0 // indirect - golang.org/x/tools/godoc v0.1.0-deprecated // indirect google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect @@ -345,7 +344,7 @@ require ( sigs.k8s.io/yaml v1.5.0 // indirect ) -replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 +replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20251030165916-532350997dde replace github.com/egirna/icap-client => github.com/kobergj/icap-client v0.0.0-20250116172800-8eaa5022532b diff --git a/go.sum b/go.sum index c191d3bcfcf..458ec970ff5 100644 --- a/go.sum +++ b/go.sum @@ -578,8 +578,8 @@ github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4O github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kobergj/go-micro/v4 v4.0.0-20250610135441-d0b187215699 h1:3TOdtI6WPyvBB+uCykapjRtQX8vTHMlyhINzR+58B4k= github.com/kobergj/go-micro/v4 v4.0.0-20250610135441-d0b187215699/go.mod h1:eE/tD53n3KbVrzrWxKLxdkGw45Fg1qaNLWjpJMvIUF4= -github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 h1:A1xJ2NKgiYFiaHiLl9B5yw/gUBACSs9crDykTS3GuQI= -github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= +github.com/kobergj/gowebdav v0.0.0-20251030165916-532350997dde h1:HYcp4J4xYe2m9KSUVbTccJb14TpSs+ldCfDFgqsXedI= +github.com/kobergj/gowebdav v0.0.0-20251030165916-532350997dde/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= github.com/kobergj/icap-client v0.0.0-20250116172800-8eaa5022532b h1:NBKEgFtIukCreWOEvtrgNQusqosGyhlxzyiHbba1zEI= github.com/kobergj/icap-client v0.0.0-20250116172800-8eaa5022532b/go.mod h1:HpntrRsQA6RKNXy2Nbr4kVj+NO3OYWpAQUVxeya+3sU= github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90 h1:pfI8Z5yavO6fU6vDGlWhZ4BgDlvj8c6xB7J57HfTPwA= @@ -717,8 +717,8 @@ github.com/orcaman/concurrent-map v1.0.0 h1:I/2A2XPCb4IuQWcQhBhSwGfiuybl/J0ev9HD github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/owncloud/libre-graph-api-go v1.0.5-0.20250217093259-fa3804be6c27 h1:ID8s5lGBntmrlI6TbDAjTzRyHucn3bVM2wlW+HBplv4= github.com/owncloud/libre-graph-api-go v1.0.5-0.20250217093259-fa3804be6c27/go.mod h1:+gT+x62AS9u2Farh9wE2uYmgdvTg0MQgsSI62D+xoRg= -github.com/owncloud/reva/v2 v2.0.0-20251017104024-82c22e954c1c h1:8xgW1qAuKNdXgH9P8F4hDI5vU6/VM1PibZhIFj7JSU0= -github.com/owncloud/reva/v2 v2.0.0-20251017104024-82c22e954c1c/go.mod h1:EgvdLWO1ezgdVqewaAP2GIZJfRRggwZItJnnTBxNNrY= +github.com/owncloud/reva/v2 v2.0.0-20251106102926-751223b32d48 h1:RGnvbZNOE1ss3b0BOM8J+bPrk6prfXB0paKnWaDA/Xg= +github.com/owncloud/reva/v2 v2.0.0-20251106102926-751223b32d48/go.mod h1:XenQR69s8JQ5Q4/+/vQbSg6B4+0iM6inYjNxB7SJAhI= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pablodz/inotifywaitgo v0.0.9 h1:njquRbBU7fuwIe5rEvtaniVBjwWzcpdUVptSgzFqZsw= diff --git a/services/graph/pkg/service/v0/utils.go b/services/graph/pkg/service/v0/utils.go index 8f6fd92772d..a326a3bfbbc 100644 --- a/services/graph/pkg/service/v0/utils.go +++ b/services/graph/pkg/service/v0/utils.go @@ -6,6 +6,7 @@ import ( "encoding/json" "io" "net/http" + "path" "reflect" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" @@ -544,7 +545,7 @@ func cs3ReceivedOCMSharesToDriveItems(ctx context.Context, // file shares resOpaqueID := "/" if receivedShares[0].GetResourceType() == storageprovider.ResourceType_RESOURCE_TYPE_FILE { - resOpaqueID += receivedShares[0].GetName() + resOpaqueID = path.Join(resOpaqueID, receivedShares[0].GetName()) } shareStat, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{ diff --git a/tests/acceptance/TestHelpers/GraphHelper.php b/tests/acceptance/TestHelpers/GraphHelper.php index 91fc25b4926..bd7b99e7b96 100644 --- a/tests/acceptance/TestHelpers/GraphHelper.php +++ b/tests/acceptance/TestHelpers/GraphHelper.php @@ -143,7 +143,7 @@ public static function getEtagRegex(): string { * @return string */ public static function getFederatedUserRegex(): string { - return '(?=(.{4})*$)[A-Za-z0-9+/]*={0,2}$'; + return self::getUUIDv4Regex() . '@[a-zA-Z-\\\.]+(:\\\d+)?'; } /** diff --git a/tests/acceptance/features/apiOcm/searchFederationUsers.feature b/tests/acceptance/features/apiOcm/searchFederationUsers.feature index fc461a76619..7464abb9d8a 100755 --- a/tests/acceptance/features/apiOcm/searchFederationUsers.feature +++ b/tests/acceptance/features/apiOcm/searchFederationUsers.feature @@ -64,7 +64,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%local_host_port%" + "const": "%local_base_url%" }, "issuerAssignedId": { "type": "string", @@ -126,7 +126,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%remote_host_port%" + "const": "%remote_base_url%" }, "issuerAssignedId": { "type": "string", @@ -194,7 +194,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%local_host_port%" + "const": "%local_base_url%" }, "issuerAssignedId": { "type": "string", @@ -256,7 +256,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%remote_host_port%" + "const": "%remote_base_url%" }, "issuerAssignedId": { "type": "string", @@ -346,7 +346,7 @@ Feature: search federation users }, "idp": { "type": "string", - "const": "%remote_host_port%" + "const": "%remote_base_url%" }, "mail": { "type": "string", @@ -385,7 +385,7 @@ Feature: search federation users "const": "Alice Hansen" }, "idp": { - "const": "%local_host_port%" + "const": "%local_base_url%" }, "mail": { "pattern": "alice@example.org" @@ -409,7 +409,7 @@ Feature: search federation users "const": "Carol King" }, "idp": { - "const": "%local_host_port%" + "const": "%local_base_url%" }, "mail": { "pattern": "carol@example.org" @@ -480,7 +480,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%local_host_port%" + "const": "%local_base_url%" }, "issuerAssignedId": { "type": "string", @@ -545,7 +545,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%remote_host_port%" + "const": "%remote_base_url%" }, "issuerAssignedId": { "type": "string", @@ -692,7 +692,7 @@ Feature: search federation users ], "properties": { "issuer": { - "const": "%remote_host_port%" + "const": "%remote_base_url%" }, "issuerAssignedId": { "type": "string", diff --git a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmcore/ocmcore.go b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmcore/ocmcore.go index 16beba4da38..4be0e5d695c 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmcore/ocmcore.go +++ b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmcore/ocmcore.go @@ -207,7 +207,7 @@ func (s *service) UpdateOCMCoreShare(ctx context.Context, req *ocmcore.UpdateOCM } fileMask := &fieldmaskpb.FieldMask{Paths: []string{"protocols"}} - user := &userpb.User{Id: ocmuser.RemoteID(&userpb.UserId{OpaqueId: grantee})} + user := &userpb.User{Id: ocmuser.DecodeRemoteUserFederatedID(&userpb.UserId{OpaqueId: grantee})} _, err := s.repo.UpdateReceivedShare(ctx, user, &ocm.ReceivedShare{ Id: &ocm.ShareId{ OpaqueId: req.GetOcmShareId(), @@ -234,7 +234,7 @@ func (s *service) DeleteOCMCoreShare(ctx context.Context, req *ocmcore.DeleteOCM return nil, errtypes.UserRequired("missing remote user id in a metadata") } - share, err := s.repo.GetReceivedShare(ctx, &userpb.User{Id: ocmuser.RemoteID(&userpb.UserId{OpaqueId: grantee})}, &ocm.ShareReference{ + share, err := s.repo.GetReceivedShare(ctx, &userpb.User{Id: ocmuser.DecodeRemoteUserFederatedID(&userpb.UserId{OpaqueId: grantee})}, &ocm.ShareReference{ Spec: &ocm.ShareReference_Id{ Id: &ocm.ShareId{ OpaqueId: req.GetId(), @@ -245,7 +245,7 @@ func (s *service) DeleteOCMCoreShare(ctx context.Context, req *ocmcore.DeleteOCM return nil, errtypes.InternalError("unable to get share details") } - granteeUser := &userpb.User{Id: ocmuser.RemoteID(&userpb.UserId{OpaqueId: grantee})} + granteeUser := &userpb.User{Id: ocmuser.DecodeRemoteUserFederatedID(&userpb.UserId{OpaqueId: grantee})} err = s.repo.DeleteReceivedShare(ctx, granteeUser, &ocm.ShareReference{ Spec: &ocm.ShareReference_Id{ Id: &ocm.ShareId{ @@ -262,7 +262,7 @@ func (s *service) DeleteOCMCoreShare(ctx context.Context, req *ocmcore.DeleteOCM if err := events.Publish(ctx, s.eventStream, events.OCMCoreShareDelete{ ShareID: share.Id.OpaqueId, Sharer: share.GetOwner(), - Grantee: ocmuser.RemoteID(&userpb.UserId{OpaqueId: grantee}), + Grantee: ocmuser.DecodeRemoteUserFederatedID(&userpb.UserId{OpaqueId: grantee}), ResourceName: share.Name, CTime: &typespb.Timestamp{Seconds: uint64(time.Now().Unix())}, }); err != nil { diff --git a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocminvitemanager/ocminvitemanager.go b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocminvitemanager/ocminvitemanager.go index 000b8e24882..e7ba3ec5d96 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocminvitemanager/ocminvitemanager.go +++ b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocminvitemanager/ocminvitemanager.go @@ -180,8 +180,8 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite remoteUser, err := s.ocmClient.InviteAccepted(ctx, ocmEndpoint, &client.InviteAcceptedRequest{ Token: req.InviteToken.GetToken(), RecipientProvider: s.conf.ProviderDomain, - // The UserID is only a string here. To not loose the IDP information we use the FederatedID encoding - // i.e. base64(UserID@IDP) + // The UserID is only a string here. To not lose the IDP information we use the FederatedID encoding + // i.e. UserID@IDP UserID: ocmuser.FederatedID(user.GetId(), "").GetOpaqueId(), Email: user.GetMail(), Name: user.GetDisplayName(), @@ -219,7 +219,7 @@ func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInvite // we're using the provider domain as the IDP part of the ID remoteUserID := &userpb.UserId{ Type: userpb.UserType_USER_TYPE_FEDERATED, - Idp: req.GetOriginSystemProvider().Domain, + Idp: ocmuser.NormalizeOCMUserIPD(req.GetOriginSystemProvider().Domain), OpaqueId: remoteUser.UserID, } diff --git a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index fcec039b8f6..a55f7eb0823 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/vendor/github.com/owncloud/reva/v2/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -325,9 +325,9 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq // 2.b replace outgoing user ids with ocm user ids // unpack the federated user id - shareWith := ocmuser.FormatOCMUser(ocmuser.RemoteID(req.GetGrantee().GetUserId())) + shareWith := ocmuser.FormatOCMUser(ocmuser.FederatedID(req.GetGrantee().GetUserId(), "")) - // wrap the local user id in a federated user id + // wrap the local user id in a local federated user id owner := ocmuser.FormatOCMUser(ocmuser.FederatedID(info.Owner, s.conf.ProviderDomain)) sender := ocmuser.FormatOCMUser(ocmuser.FederatedID(user.Id, s.conf.ProviderDomain)) diff --git a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/invites.go b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/invites.go index 7cf8b035ba4..a58f1dc819e 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/invites.go +++ b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/invites.go @@ -60,7 +60,7 @@ type acceptInviteRequest struct { Email string `json:"email"` } -// AcceptInvite informs avout an accepted invitation so that the users +// AcceptInvite informs about an accepted invitation so that the users // can initiate the OCM share creation. func (h *invitesHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -73,7 +73,7 @@ func (h *invitesHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) { } if req.Token == "" || req.UserID == "" || req.RecipientProvider == "" { - reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, "token, userID and recipiendProvider must not be null", nil) + reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, "token, userID and recipientProvider must not be null", nil) return } @@ -111,7 +111,7 @@ func (h *invitesHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) { userObj := &userpb.User{ Id: &userpb.UserId{ OpaqueId: req.UserID, - Idp: req.RecipientProvider, + Idp: ocmuser.NormalizeOCMUserIPD(req.RecipientProvider), Type: userpb.UserType_USER_TYPE_FEDERATED, }, Mail: req.Email, diff --git a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/notifications.go b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/notifications.go index 41e55b344dc..37fa1b709d5 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/notifications.go +++ b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/notifications.go @@ -29,10 +29,10 @@ import ( ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/go-chi/render" "github.com/owncloud/reva/v2/pkg/appctx" "github.com/owncloud/reva/v2/pkg/rgrpc/todo/pool" "github.com/owncloud/reva/v2/pkg/utils" - "github.com/go-chi/render" ) const ( @@ -99,7 +99,6 @@ func (h *notifHandler) Notifications(w http.ResponseWriter, r *http.Request) { return } - // TODO(lopresti) this is all to be implemented. For now we just log what we got log.Debug().Msgf("Received OCM notification: %+v", req) var status *rpc.Status diff --git a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/shares.go b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/shares.go index 0a3770896df..fcbc4025f66 100644 --- a/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/shares.go +++ b/vendor/github.com/owncloud/reva/v2/internal/http/services/ocmd/shares.go @@ -34,11 +34,12 @@ import ( ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/go-playground/validator/v10" "github.com/owncloud/reva/v2/internal/http/services/reqres" "github.com/owncloud/reva/v2/pkg/appctx" + ocmuser "github.com/owncloud/reva/v2/pkg/ocm/user" "github.com/owncloud/reva/v2/pkg/rgrpc/todo/pool" "github.com/owncloud/reva/v2/pkg/utils" - "github.com/go-playground/validator/v10" ) var validate = validator.New() @@ -124,7 +125,7 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) { return } - shareWith, _, err := getIDAndMeshProvider(req.ShareWith) + shareWith, _, err := getLocalUserID(req.ShareWith) if err != nil { reqres.WriteError(w, r, reqres.APIErrorInvalidParameter, err.Error(), nil) return @@ -197,11 +198,28 @@ func (h *sharesHandler) CreateShare(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) } +func getLocalUserID(user string) (id, provider string, err error) { + idPart, provider, err := getIDAndMeshProvider(user) + if err != nil { + return "", "", err + } + + // Handle nested @ in idPart (e.g. "user@idp@provider") + if inner := strings.LastIndex(idPart, "@"); inner != -1 { + id = idPart[:inner] + } else { + id = idPart + } + + return id, provider, nil +} + func getUserIDFromOCMUser(user string) (*userpb.UserId, error) { id, idp, err := getIDAndMeshProvider(user) if err != nil { return nil, err } + idp = ocmuser.NormalizeOCMUserIPD(idp) return &userpb.UserId{ OpaqueId: id, Idp: idp, @@ -210,13 +228,21 @@ func getUserIDFromOCMUser(user string) (*userpb.UserId, error) { }, nil } -func getIDAndMeshProvider(user string) (string, string, error) { - // the user is in the form of dimitri@apiwise.nl - split := strings.Split(user, "@") - if len(split) < 2 { - return "", "", errors.New("not in the form @") +func getIDAndMeshProvider(user string) (id, provider string, err error) { + last := strings.LastIndex(user, "@") + if last == -1 { + return "", "", fmt.Errorf("%s not in the form @", user) } - return strings.Join(split[:len(split)-1], "@"), split[len(split)-1], nil + + id, provider = user[:last], user[last+1:] + if id == "" { + return "", "", errors.New("id cannot be empty") + } + if provider == "" { + return "", "", errors.New("provider cannot be empty") + } + + return id, provider, nil } func getCreateShareRequest(r *http.Request) (*createShareRequest, error) { diff --git a/vendor/github.com/owncloud/reva/v2/pkg/ocm/invite/repository/json/json.go b/vendor/github.com/owncloud/reva/v2/pkg/ocm/invite/repository/json/json.go index 2ec73c84e1e..a239736bee4 100644 --- a/vendor/github.com/owncloud/reva/v2/pkg/ocm/invite/repository/json/json.go +++ b/vendor/github.com/owncloud/reva/v2/pkg/ocm/invite/repository/json/json.go @@ -226,12 +226,14 @@ func (m *manager) GetRemoteUser(ctx context.Context, initiator *userpb.UserId, r log := appctx.GetLogger(ctx) for _, acceptedUser := range m.model.AcceptedUsers[initiator.GetOpaqueId()] { log.Info().Msgf("looking for '%s' at '%s' - considering '%s' at '%s'", - remoteUserID.OpaqueId, - remoteUserID.Idp, - acceptedUser.Id.GetOpaqueId(), - acceptedUser.Id.GetIdp(), - ) + remoteUserID.OpaqueId, remoteUserID.Idp, + acceptedUser.Id.GetOpaqueId(), acceptedUser.Id.GetIdp()) + if (acceptedUser.Id.GetOpaqueId() == remoteUserID.OpaqueId) && (remoteUserID.Idp == "" || idpsEqual(acceptedUser.Id.GetIdp(), remoteUserID.Idp)) { + log.Info().Msgf("remote user OpaqueId:'%s' Idp:'%s' matches OpaqueId:'%s' Idp:'%s'", + remoteUserID.OpaqueId, remoteUserID.Idp, + acceptedUser.Id.GetOpaqueId(), acceptedUser.Id.GetIdp()) + return acceptedUser, nil } } diff --git a/vendor/github.com/owncloud/reva/v2/pkg/ocm/provider/authorizer/json/json.go b/vendor/github.com/owncloud/reva/v2/pkg/ocm/provider/authorizer/json/json.go index 100295bc4de..ad46c12a67b 100644 --- a/vendor/github.com/owncloud/reva/v2/pkg/ocm/provider/authorizer/json/json.go +++ b/vendor/github.com/owncloud/reva/v2/pkg/ocm/provider/authorizer/json/json.go @@ -173,10 +173,12 @@ func (a *authorizer) IsProviderAllowed(ctx context.Context, pi *ocmprovider.Prov } switch { - case !providerAuthorized: - return errtypes.NotFound(pi.GetDomain()) case !a.conf.VerifyRequestHostname: + log.Info().Msg("VerifyRequestHostname is disabled. any provider is allowed") return nil + case !providerAuthorized: + log.Info().Msg("providerAuthorized is false") + return errtypes.NotFound(pi.GetDomain()) case len(pi.Services) == 0: return ErrNoIP } diff --git a/vendor/github.com/owncloud/reva/v2/pkg/ocm/user/user.go b/vendor/github.com/owncloud/reva/v2/pkg/ocm/user/user.go index 9be8add2b4d..501bec0257f 100644 --- a/vendor/github.com/owncloud/reva/v2/pkg/ocm/user/user.go +++ b/vendor/github.com/owncloud/reva/v2/pkg/ocm/user/user.go @@ -1,50 +1,76 @@ package user import ( - "encoding/base64" "fmt" + "net/url" "strings" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" ) -// FederatedID creates a federated user id by +// FederatedID creates a federated id for local users by // 1. stripping the protocol from the domain and -// 2. base64 encoding the opaque id with the domain to get a unique identifier that cannot collide with other users +// 2. concatenating the opaque id with the domain to get a unique identifier that cannot collide with other users func FederatedID(id *userpb.UserId, domain string) *userpb.UserId { - opaqueId := base64.URLEncoding.EncodeToString([]byte(id.OpaqueId + "@" + id.Idp)) - return &userpb.UserId{ + if domain == "" { + domain = id.Idp + } + // strip protocol from the domain + idp := id.Idp + if u, err := url.Parse(id.Idp); err == nil && u.Host != "" { + idp = u.Host + } + opaqueId := id.OpaqueId + if !strings.Contains(id.OpaqueId, "@") { + opaqueId = id.OpaqueId + "@" + idp + } + + u := &userpb.UserId{ Type: userpb.UserType_USER_TYPE_FEDERATED, - Idp: domain, + Idp: NormalizeOCMUserIPD(domain), OpaqueId: opaqueId, } + + return u } -// RemoteID creates a remote user id by -// 1. decoding the base64 encoded opaque id -// 2. splitting the opaque id at the last @ to get the opaque id and the domain -func RemoteID(id *userpb.UserId) *userpb.UserId { +// DecodeRemoteUserFederatedID decodes opaque id into remote user's federated id by +// splitting the opaque id at the last @ to get the opaque id and the domain +func DecodeRemoteUserFederatedID(id *userpb.UserId) *userpb.UserId { remoteId := &userpb.UserId{ Type: userpb.UserType_USER_TYPE_PRIMARY, Idp: id.Idp, OpaqueId: id.OpaqueId, } - bytes, err := base64.URLEncoding.DecodeString(id.GetOpaqueId()) - if err != nil { - return remoteId - } - remote := string(bytes) + remote := id.OpaqueId last := strings.LastIndex(remote, "@") if last == -1 { return remoteId } remoteId.OpaqueId = remote[:last] - remoteId.Idp = remote[last+1:] + remoteId.Idp = NormalizeOCMUserIPD(remote[last+1:]) return remoteId } // FormatOCMUser formats a user id in the form of @ used by the OCM API in shareWith, owner and creator fields func FormatOCMUser(u *userpb.UserId) string { - return fmt.Sprintf("%s@%s", u.OpaqueId, u.Idp) + if u.Idp == "" { + return u.OpaqueId + } + // strip protocol from the domain + idp := u.Idp + if u, err := url.Parse(u.Idp); err == nil && u.Host != "" { + idp = u.Host + } + return fmt.Sprintf("%s@%s", u.OpaqueId, idp) +} + +// NormalizeOCMUserIPD ensures that the idp has a scheme (https://) prefix if prefix is missing +// to keep the idp consistent across shares and received shares in the OCM share store. +func NormalizeOCMUserIPD(idp string) string { + if strings.Contains(idp, "://") { + return idp + } + return "https://" + idp } diff --git a/vendor/github.com/studio-b12/gowebdav/file.go b/vendor/github.com/studio-b12/gowebdav/file.go index 15f45473439..80cff48b62b 100644 --- a/vendor/github.com/studio-b12/gowebdav/file.go +++ b/vendor/github.com/studio-b12/gowebdav/file.go @@ -32,7 +32,7 @@ func newFile(path, name string, p *propstat) *File { path = FixSlashes(path) f.name = filepath.Base(name) - f.path = filepath.Clean(filepath.Join(path, f.name)) + f.path = filepath.Clean(filepath.Join(path, name)) f.modified = p.Modified() f.etag = p.ETag() f.contentType = p.ContentType() diff --git a/vendor/modules.txt b/vendor/modules.txt index bce990f3296..95702e9cef8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1246,7 +1246,7 @@ github.com/orcaman/concurrent-map # github.com/owncloud/libre-graph-api-go v1.0.5-0.20250217093259-fa3804be6c27 ## explicit; go 1.18 github.com/owncloud/libre-graph-api-go -# github.com/owncloud/reva/v2 v2.0.0-20251017104024-82c22e954c1c +# github.com/owncloud/reva/v2 v2.0.0-20251106102926-751223b32d48 ## explicit; go 1.24.0 github.com/owncloud/reva/v2/cmd/revad/internal/grace github.com/owncloud/reva/v2/cmd/revad/runtime @@ -1851,7 +1851,7 @@ github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml github.com/stretchr/testify/mock github.com/stretchr/testify/require -# github.com/studio-b12/gowebdav v0.9.0 => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 +# github.com/studio-b12/gowebdav v0.9.0 => github.com/kobergj/gowebdav v0.0.0-20251030165916-532350997dde ## explicit; go 1.17 github.com/studio-b12/gowebdav # github.com/tchap/go-patricia/v2 v2.3.3 @@ -2475,7 +2475,7 @@ sigs.k8s.io/yaml # stash.kopano.io/kgol/rndm v1.1.2 ## explicit; go 1.13 stash.kopano.io/kgol/rndm -# github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 +# github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20251030165916-532350997dde # github.com/egirna/icap-client => github.com/kobergj/icap-client v0.0.0-20250116172800-8eaa5022532b # github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c # github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90