committed by
Ralf Haferkamp
parent
b1d0a2a577
commit
5a13179a72
+23
-5
@@ -89,7 +89,7 @@ func expandAndVerifyScope(ctx context.Context, req interface{}, tokenScope map[s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
log.Err(err).Msgf("error resolving reference %s under scope %+v", ref.String(), k)
|
||||
log.Err(err).Interface("ref", ref).Interface("scope", k).Msg("error resolving reference under scope")
|
||||
}
|
||||
|
||||
} else if ref, ok := extractShareRef(req); ok {
|
||||
@@ -179,6 +179,11 @@ func resolveOCMShare(ctx context.Context, ref *provider.Reference, scope *authpb
|
||||
return err
|
||||
}
|
||||
|
||||
// for ListOCMSharesRequest, the ref resource id is empty and we set path to . to indicate the root of the share
|
||||
if ref.GetResourceId() == nil && ref.Path == "." {
|
||||
ref.ResourceId = share.GetResourceId()
|
||||
}
|
||||
|
||||
if err := checkCacheForNestedResource(ctx, ref, share.ResourceId, client, mgr); err == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -213,7 +218,7 @@ func checkRelativeReference(ctx context.Context, requested *provider.Reference,
|
||||
if sharedResource.ParentId == nil {
|
||||
// Is the requested resource part of the shared space?
|
||||
if requested.ResourceId.StorageId != sharedResource.Id.StorageId || requested.ResourceId.SpaceId != sharedResource.Id.SpaceId {
|
||||
return errtypes.PermissionDenied("access forbidden via public link")
|
||||
return errtypes.PermissionDenied("space access forbidden via public link")
|
||||
}
|
||||
} else {
|
||||
parentID := sharedResource.ParentId
|
||||
@@ -261,7 +266,7 @@ func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if statResponse.Status.Code != rpc.Code_CODE_OK {
|
||||
if statResponse.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(statResponse.Status.Code, "auth interceptor")
|
||||
}
|
||||
|
||||
@@ -313,14 +318,22 @@ func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if childStat.Status.Code != rpc.Code_CODE_OK {
|
||||
if childStat.GetStatus().GetCode() == rpc.Code_CODE_NOT_FOUND && ref.GetPath() != "" && ref.GetPath() != "." {
|
||||
// The resource does not seem to exist (yet?). We might be part of an initiate upload request.
|
||||
// Stat the parent to get its path and check that against the root path.
|
||||
childStat, err = client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: ref.GetResourceId()}})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
if childStat.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(childStat.Status.Code, "auth interceptor")
|
||||
}
|
||||
pathResp, err = client.GetPath(ctx, &provider.GetPathRequest{ResourceId: childStat.GetInfo().GetId()})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if pathResp.Status.Code != rpc.Code_CODE_OK {
|
||||
if pathResp.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(pathResp.Status.Code, "auth interceptor")
|
||||
}
|
||||
childPath = pathResp.Path
|
||||
@@ -388,6 +401,11 @@ func extractRefForReaderRole(req interface{}) (*provider.Reference, bool) {
|
||||
return v.GetRef(), true
|
||||
case *provider.UnlockRequest:
|
||||
return v.GetRef(), true
|
||||
|
||||
// OCM shares
|
||||
case *ocmv1beta1.ListReceivedOCMSharesRequest:
|
||||
return &provider.Reference{Path: "."}, true // we will try to stat the shared node
|
||||
|
||||
}
|
||||
|
||||
return nil, false
|
||||
|
||||
Generated
Vendored
+20
-15
@@ -39,6 +39,11 @@ import (
|
||||
|
||||
// TODO(labkode): add multi-phase commit logic when commit share or commit ref is enabled.
|
||||
func (s *svc) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest) (*ocm.CreateOCMShareResponse, error) {
|
||||
if len(req.AccessMethods) == 0 {
|
||||
return &ocm.CreateOCMShareResponse{
|
||||
Status: status.NewInvalidArg(ctx, "access methods cannot be empty"),
|
||||
}, nil
|
||||
}
|
||||
c, err := pool.GetOCMShareProviderClient(s.c.OCMShareProviderEndpoint)
|
||||
if err != nil {
|
||||
return &ocm.CreateOCMShareResponse{
|
||||
@@ -48,7 +53,7 @@ func (s *svc) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest
|
||||
|
||||
res, err := c.CreateOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling CreateShare")
|
||||
return nil, errors.Wrap(err, "gateway: error calling CreateOCMShare")
|
||||
}
|
||||
|
||||
status, err := s.addGrant(ctx, req.ResourceId, req.Grantee, req.AccessMethods[0].GetWebdavOptions().Permissions, req.Expiration, nil)
|
||||
@@ -78,7 +83,7 @@ func (s *svc) RemoveOCMShare(ctx context.Context, req *ocm.RemoveOCMShareRequest
|
||||
|
||||
res, err := c.RemoveOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling RemoveShare")
|
||||
return nil, errors.Wrap(err, "gateway: error calling RemoveOCMShare")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -102,7 +107,7 @@ func (s *svc) getOCMShare(ctx context.Context, req *ocm.GetOCMShareRequest) (*oc
|
||||
|
||||
res, err := c.GetOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling GetShare")
|
||||
return nil, errors.Wrap(err, "gateway: error calling GetOCMShare")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -134,7 +139,7 @@ func (s *svc) ListOCMShares(ctx context.Context, req *ocm.ListOCMSharesRequest)
|
||||
|
||||
res, err := c.ListOCMShares(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling ListShares")
|
||||
return nil, errors.Wrap(err, "gateway: error calling ListOCMShares")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -151,7 +156,7 @@ func (s *svc) UpdateOCMShare(ctx context.Context, req *ocm.UpdateOCMShareRequest
|
||||
|
||||
res, err := c.UpdateOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling UpdateShare")
|
||||
return nil, errors.Wrap(err, "gateway: error calling UpdateOCMShare")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -168,7 +173,7 @@ func (s *svc) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceivedOC
|
||||
|
||||
res, err := c.ListReceivedOCMShares(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling ListReceivedShares")
|
||||
return nil, errors.Wrap(err, "gateway: error calling ListReceivedOCMShares")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -223,7 +228,7 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive
|
||||
|
||||
res, err := c.UpdateReceivedOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare")
|
||||
return &ocm.UpdateReceivedOCMShareResponse{
|
||||
Status: &rpc.Status{
|
||||
Code: rpc.Code_CODE_INTERNAL,
|
||||
@@ -256,7 +261,7 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive
|
||||
// handle transfer in case it has not already been accepted
|
||||
if s.isTransferShare(share) && req.GetShare().State == ocm.ShareState_SHARE_STATE_ACCEPTED {
|
||||
if share.State == ocm.ShareState_SHARE_STATE_ACCEPTED {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare, share already accepted.")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare, share already accepted.")
|
||||
return &ocm.UpdateReceivedOCMShareResponse{
|
||||
Status: &rpc.Status{
|
||||
Code: rpc.Code_CODE_FAILED_PRECONDITION,
|
||||
@@ -268,7 +273,7 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive
|
||||
transferDestinationPath, err := s.getTransferDestinationPath(ctx, req)
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare")
|
||||
return &ocm.UpdateReceivedOCMShareResponse{
|
||||
Status: &rpc.Status{
|
||||
Code: rpc.Code_CODE_INTERNAL,
|
||||
@@ -279,7 +284,7 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive
|
||||
|
||||
error := s.handleTransfer(ctx, share, transferDestinationPath)
|
||||
if error != nil {
|
||||
log.Err(error).Msg("gateway: error handling transfer in UpdateReceivedShare")
|
||||
log.Err(error).Msg("gateway: error handling transfer in UpdateReceivedOCMShare")
|
||||
return &ocm.UpdateReceivedOCMShareResponse{
|
||||
Status: &rpc.Status{
|
||||
Code: rpc.Code_CODE_INTERNAL,
|
||||
@@ -309,17 +314,17 @@ func (s *svc) handleTransfer(ctx context.Context, share *ocm.ReceivedShare, tran
|
||||
}
|
||||
destWebdavEndpoint, err := s.getWebdavEndpoint(ctx, granteeIdp)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare")
|
||||
return err
|
||||
}
|
||||
destWebdavEndpointURL, err := url.Parse(destWebdavEndpoint)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare: unable to parse webdav endpoint \"" + destWebdavEndpoint + "\" into URL structure")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare: unable to parse webdav endpoint \"" + destWebdavEndpoint + "\" into URL structure")
|
||||
return err
|
||||
}
|
||||
destWebdavHost, err := s.getWebdavHost(ctx, granteeIdp)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare")
|
||||
return err
|
||||
}
|
||||
var dstWebdavURLString string
|
||||
@@ -330,7 +335,7 @@ func (s *svc) handleTransfer(ctx context.Context, share *ocm.ReceivedShare, tran
|
||||
}
|
||||
dstWebdavHostURL, err := url.Parse(dstWebdavURLString)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedShare: unable to parse webdav service host \"" + dstWebdavURLString + "\" into URL structure")
|
||||
log.Err(err).Msg("gateway: error calling UpdateReceivedOCMShare: unable to parse webdav service host \"" + dstWebdavURLString + "\" into URL structure")
|
||||
return err
|
||||
}
|
||||
destServiceHost := dstWebdavHostURL.Host + dstWebdavHostURL.Path
|
||||
@@ -393,7 +398,7 @@ func (s *svc) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMSh
|
||||
|
||||
res, err := c.GetReceivedOCMShare(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "gateway: error calling GetReceivedShare")
|
||||
return nil, errors.Wrap(err, "gateway: error calling GetReceivedOCMShare")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
||||
Generated
Vendored
+2
-2
@@ -171,9 +171,9 @@ func getResourceType(info *providerpb.ResourceInfo) string {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (s *service) webdavURL(ctx context.Context, share *ocm.Share) string {
|
||||
func (s *service) webdavURL(_ context.Context, share *ocm.Share) string {
|
||||
// the url is in the form of https://cernbox.cern.ch/remote.php/dav/ocm/token
|
||||
p, _ := url.JoinPath(s.conf.WebDAVEndpoint, "/dav/ocm", share.Token)
|
||||
p, _ := url.JoinPath(s.conf.WebDAVEndpoint, "/dav/ocm", share.GetId().GetOpaqueId())
|
||||
return p
|
||||
}
|
||||
|
||||
|
||||
Generated
Vendored
+6
-3
@@ -405,7 +405,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora
|
||||
Status: &rpc.Status{Code: rpc.Code_CODE_INVALID_ARGUMENT, Message: err.Error()},
|
||||
}, nil
|
||||
}
|
||||
if resID.SpaceId != utils.PublicStorageSpaceID {
|
||||
if resID.SpaceId != utils.PublicStorageSpaceID && resID.SpaceId != utils.OCMStorageSpaceID {
|
||||
return &provider.ListStorageSpacesResponse{
|
||||
// a specific id was requested, return not found instead of empty list
|
||||
Status: &rpc.Status{Code: rpc.Code_CODE_NOT_FOUND},
|
||||
@@ -415,7 +415,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora
|
||||
}
|
||||
}
|
||||
|
||||
info, _, grantee, token, err := s.extractLinkFromScope(ctx)
|
||||
info, share, grantee, token, err := s.extractLinkFromScope(ctx)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errtypes.NotFound:
|
||||
@@ -468,6 +468,9 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora
|
||||
SpaceId: utils.PublicStorageSpaceID,
|
||||
OpaqueId: token, // the link share has no id, only the token
|
||||
}
|
||||
if ocmShare, ok := share.(*ocm.Share); ok {
|
||||
root.OpaqueId = ocmShare.GetId().GetOpaqueId()
|
||||
}
|
||||
if spaceID != nil {
|
||||
switch {
|
||||
case utils.ResourceIDEqual(spaceID, root):
|
||||
@@ -506,7 +509,7 @@ func (s *service) extractLinkFromScope(ctx context.Context) (*provider.ResourceI
|
||||
share := &ocm.Share{}
|
||||
err := utils.UnmarshalJSONToProtoV1(v.Resource.Value, share)
|
||||
if err != nil {
|
||||
return nil, nil, nil, "", errtypes.InternalError("failed to unmarshal public share")
|
||||
return nil, nil, nil, "", errtypes.InternalError("failed to unmarshal ocm share")
|
||||
}
|
||||
|
||||
// the share is minimally populated, we need more than the token
|
||||
|
||||
+17
-16
@@ -185,38 +185,38 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
|
||||
}
|
||||
|
||||
// OC10 and Nextcloud (OCM 1.0) are using basic auth for carrying the
|
||||
// shared token.
|
||||
var token string
|
||||
// ocm share id.
|
||||
var ocmshare, sharedSecret string
|
||||
username, _, ok := r.BasicAuth()
|
||||
if ok {
|
||||
// OCM 1.0
|
||||
token = username
|
||||
r.URL.Path = filepath.Join("/", token, r.URL.Path)
|
||||
ctx = context.WithValue(ctx, net.CtxOCM10, true)
|
||||
ocmshare = username
|
||||
sharedSecret = username
|
||||
r.URL.Path = filepath.Join("/", ocmshare, r.URL.Path)
|
||||
} else {
|
||||
token, _ = router.ShiftPath(r.URL.Path)
|
||||
ctx = context.WithValue(ctx, net.CtxOCM10, false)
|
||||
ocmshare, _ = router.ShiftPath(r.URL.Path)
|
||||
sharedSecret = strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
|
||||
}
|
||||
|
||||
authRes, err := handleOCMAuth(ctx, c, token)
|
||||
authRes, err := handleOCMAuth(ctx, c, ocmshare, sharedSecret)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Error().Err(err).Msg("error during ocm authentication")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
case authRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED:
|
||||
log.Debug().Str("token", token).Msg("permission denied")
|
||||
log.Debug().Str("ocmshare", ocmshare).Msg("permission denied")
|
||||
fallthrough
|
||||
case authRes.Status.Code == rpc.Code_CODE_UNAUTHENTICATED:
|
||||
log.Debug().Str("token", token).Msg("unauthorized")
|
||||
log.Debug().Str("ocmshare", ocmshare).Msg("unauthorized")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
case authRes.Status.Code == rpc.Code_CODE_NOT_FOUND:
|
||||
log.Debug().Str("token", token).Msg("not found")
|
||||
log.Debug().Str("ocmshare", ocmshare).Msg("not found")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
case authRes.Status.Code != rpc.Code_CODE_OK:
|
||||
log.Error().Str("token", token).Interface("status", authRes.Status).Msg("grpc auth request failed")
|
||||
log.Error().Str("ocmshare", ocmshare).Interface("status", authRes.Status).Msg("grpc auth request failed")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
|
||||
ctx = ctxpkg.ContextSetUser(ctx, authRes.User)
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, authRes.Token)
|
||||
|
||||
log.Debug().Str("token", token).Interface("user", authRes.User).Msg("OCM user authenticated")
|
||||
log.Debug().Str("ocmshare", ocmshare).Interface("user", authRes.User).Msg("OCM user authenticated")
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
h.OCMSharesHandler.Handler(s).ServeHTTP(w, r)
|
||||
@@ -375,9 +375,10 @@ func handleSignatureAuth(ctx context.Context, selector pool.Selectable[gatewayv1
|
||||
return c.Authenticate(ctx, &authenticateRequest)
|
||||
}
|
||||
|
||||
func handleOCMAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, token string) (*gatewayv1beta1.AuthenticateResponse, error) {
|
||||
func handleOCMAuth(ctx context.Context, c gatewayv1beta1.GatewayAPIClient, ocmshare, sharedSecret string) (*gatewayv1beta1.AuthenticateResponse, error) {
|
||||
return c.Authenticate(ctx, &gatewayv1beta1.AuthenticateRequest{
|
||||
Type: "ocmshares",
|
||||
ClientId: token,
|
||||
Type: "ocmshares",
|
||||
ClientId: ocmshare,
|
||||
ClientSecret: sharedSecret,
|
||||
})
|
||||
}
|
||||
|
||||
Generated
Vendored
-1
@@ -35,7 +35,6 @@ type ctxKey int
|
||||
const (
|
||||
// CtxKeyBaseURI is the key of the base URI context field
|
||||
CtxKeyBaseURI ctxKey = iota
|
||||
CtxOCM10
|
||||
|
||||
// NsDav is the Dav ns
|
||||
NsDav = "DAV:"
|
||||
|
||||
+10
-3
@@ -82,10 +82,11 @@ func (m *manager) Configure(ml map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manager) Authenticate(ctx context.Context, token, _ string) (*userpb.User, map[string]*authpb.Scope, error) {
|
||||
log := appctx.GetLogger(ctx).With().Str("token", token).Logger()
|
||||
func (m *manager) Authenticate(ctx context.Context, ocmshare, sharedSecret string) (*userpb.User, map[string]*authpb.Scope, error) {
|
||||
log := appctx.GetLogger(ctx).With().Str("ocmshare", ocmshare).Logger()
|
||||
// We need to use GetOCMShareByToken, as GetOCMShare would require a user in the context
|
||||
shareRes, err := m.gw.GetOCMShareByToken(ctx, &ocm.GetOCMShareByTokenRequest{
|
||||
Token: token,
|
||||
Token: sharedSecret,
|
||||
})
|
||||
|
||||
switch {
|
||||
@@ -103,6 +104,12 @@ func (m *manager) Authenticate(ctx context.Context, token, _ string) (*userpb.Us
|
||||
return nil, nil, errtypes.InternalError(shareRes.Status.Message)
|
||||
}
|
||||
|
||||
// compare ocm share id
|
||||
if shareRes.GetShare().GetId().GetOpaqueId() != ocmshare {
|
||||
log.Error().Str("persisted", ocmshare).Str("requested", shareRes.GetShare().GetId().GetOpaqueId()).Msg("mismatching ocm share id for existing secret")
|
||||
return nil, nil, errtypes.InvalidCredentials("invalid shared secret")
|
||||
}
|
||||
|
||||
// the user authenticated using the ocmshares authentication method
|
||||
// is the recipient of the share
|
||||
u := shareRes.Share.Grantee.GetUserId()
|
||||
|
||||
+14
-6
@@ -28,6 +28,7 @@ import (
|
||||
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/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"
|
||||
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
|
||||
@@ -123,6 +124,13 @@ func ocmShareScope(_ context.Context, scope *authpb.Scope, resource interface{},
|
||||
return true, nil
|
||||
case *provider.ListStorageSpacesRequest:
|
||||
return true, nil
|
||||
// FIXME why do we need to add them? I think the whole listing of received OCM shares change might be unnecessary ... need to reevaluate that after switching the dav namespace for from /ocm back to /public
|
||||
case *ocmv1beta1.ListReceivedOCMSharesRequest:
|
||||
return true, nil
|
||||
case *ocmv1beta1.ListOCMSharesRequest:
|
||||
return true, nil
|
||||
case *collaboration.ListReceivedSharesRequest:
|
||||
return true, nil
|
||||
|
||||
case *ocmv1beta1.GetOCMShareRequest:
|
||||
return checkOCMShareRef(&share, v.GetRef()), nil
|
||||
@@ -136,24 +144,24 @@ func ocmShareScope(_ context.Context, scope *authpb.Scope, resource interface{},
|
||||
|
||||
func checkStorageRefForOCMShare(s *ocmv1beta1.Share, r *provider.Reference, ns string) bool {
|
||||
if r.ResourceId != nil {
|
||||
return utils.ResourceIDEqual(s.ResourceId, r.GetResourceId()) || strings.HasPrefix(r.ResourceId.OpaqueId, s.Token)
|
||||
return utils.ResourceIDEqual(s.ResourceId, r.GetResourceId()) || strings.HasPrefix(r.ResourceId.OpaqueId, s.GetId().GetOpaqueId())
|
||||
}
|
||||
|
||||
// FIXME: the paths here are hardcoded
|
||||
if strings.HasPrefix(r.GetPath(), "/public/"+s.Token) {
|
||||
if strings.HasPrefix(r.GetPath(), "/public/"+s.GetId().GetOpaqueId()) {
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(r.GetPath(), filepath.Join(ns, s.Token))
|
||||
return strings.HasPrefix(r.GetPath(), filepath.Join(ns, s.GetId().GetOpaqueId()))
|
||||
}
|
||||
|
||||
func checkOCMShareRef(s *ocmv1beta1.Share, ref *ocmv1beta1.ShareReference) bool {
|
||||
return ref.GetToken() == s.Token
|
||||
return ref.GetId().GetOpaqueId() == s.GetId().GetOpaqueId()
|
||||
}
|
||||
|
||||
// AddOCMShareScope adds the scope to allow access to an OCM share and the share resource.
|
||||
func AddOCMShareScope(share *ocmv1beta1.Share, role authpb.Role, scopes map[string]*authpb.Scope) (map[string]*authpb.Scope, error) {
|
||||
// Create a new "scope share" to only expose the required fields `ResourceId` and `Token` to the scope.
|
||||
scopeShare := ocmv1beta1.Share{ResourceId: share.ResourceId, Token: share.Token}
|
||||
// Create a new "scope share" to only expose the required fields `ResourceId`, `Id` and `Token` to the scope.
|
||||
scopeShare := ocmv1beta1.Share{ResourceId: share.ResourceId, Id: share.GetId(), Token: share.Token}
|
||||
val, err := utils.MarshalProtoV1ToJSON(&scopeShare)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+1
-1
@@ -396,7 +396,7 @@ func (m *mgr) ListShares(ctx context.Context, user *userpb.User, filters []*ocm.
|
||||
}
|
||||
|
||||
for _, share := range m.model.Shares {
|
||||
if utils.UserEqual(user.Id, share.Owner) || utils.UserEqual(user.Id, share.Creator) {
|
||||
if utils.UserEqual(user.Id, share.Owner) || utils.UserEqual(user.Id, share.Creator) || utils.UserEqual(user.Id, share.GetGrantee().GetUserId()) {
|
||||
// no filter we return earlier
|
||||
if len(filters) == 0 {
|
||||
ss = append(ss, share)
|
||||
|
||||
+42
-12
@@ -73,12 +73,12 @@ func (c *config) ApplyDefaults() {
|
||||
|
||||
// BearerAuthenticator represents an authenticator that adds a Bearer token to the Authorization header of HTTP requests.
|
||||
type BearerAuthenticator struct {
|
||||
token string
|
||||
Token string
|
||||
}
|
||||
|
||||
// Authorize adds the Bearer token to the Authorization header of the provided HTTP request.
|
||||
func (b BearerAuthenticator) Authorize(_ *http.Client, r *http.Request, _ string) error {
|
||||
r.Header.Add("Authorization", "Bearer "+b.token)
|
||||
r.Header.Add("Authorization", "Bearer "+b.Token)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ func (BearerAuthenticator) Verify(*http.Client, *http.Response, string) (bool, e
|
||||
}
|
||||
|
||||
// Clone creates a new instance of the BearerAuthenticator.
|
||||
func (BearerAuthenticator) Clone() gowebdav.Authenticator {
|
||||
return BearerAuthenticator{}
|
||||
func (b BearerAuthenticator) Clone() gowebdav.Authenticator {
|
||||
return BearerAuthenticator{Token: b.Token}
|
||||
}
|
||||
|
||||
// Close is not implemented for the BearerAuthenticator. It always returns nil.
|
||||
@@ -196,7 +196,7 @@ func (d *driver) webdavClient(ctx context.Context, forUser *userpb.UserId, ref *
|
||||
|
||||
// FIXME: it's still not clear from the OCM APIs how to use the shared secret
|
||||
// will use as a token in the bearer authentication as this is the reva implementation
|
||||
c := gowebdav.NewAuthClient(endpoint, gowebdav.NewPreemptiveAuth(BearerAuthenticator{token: secret}))
|
||||
c := gowebdav.NewAuthClient(endpoint, gowebdav.NewPreemptiveAuth(BearerAuthenticator{Token: secret}))
|
||||
if d.c.Insecure {
|
||||
c.SetTransport(&http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
@@ -250,17 +250,21 @@ func convertStatToResourceInfo(ref *provider.Reference, f fs.FileInfo, share *oc
|
||||
t = provider.ResourceType_RESOURCE_TYPE_CONTAINER
|
||||
}
|
||||
|
||||
var name string
|
||||
if share.ResourceType == provider.ResourceType_RESOURCE_TYPE_FILE {
|
||||
name = share.Name
|
||||
} else {
|
||||
name = f.Name()
|
||||
}
|
||||
|
||||
webdavFile, ok := f.(gowebdav.File)
|
||||
if !ok {
|
||||
return nil, errtypes.InternalError("could not get webdav props")
|
||||
}
|
||||
|
||||
var name string
|
||||
switch {
|
||||
case share.ResourceType == provider.ResourceType_RESOURCE_TYPE_FILE:
|
||||
name = share.Name
|
||||
case webdavFile.Path() == "/":
|
||||
name = share.Name
|
||||
default:
|
||||
name = webdavFile.Name()
|
||||
}
|
||||
|
||||
opaqueid := base64.StdEncoding.EncodeToString([]byte(webdavFile.Path()))
|
||||
|
||||
// ids are of the format <ocmstorageproviderid>$<shareid>!<opaqueid>
|
||||
@@ -461,6 +465,13 @@ func (d *driver) ListStorageSpaces(ctx context.Context, filters []*provider.List
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// FIXME This might have to be ListOCMShares
|
||||
// these are grants
|
||||
|
||||
lsRes, err := d.gateway.ListOCMShares(ctx, &ocmpb.ListOCMSharesRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(spaceTypes) == 0 {
|
||||
spaceTypes["mountpoint"] = exists
|
||||
@@ -489,6 +500,25 @@ func (d *driver) ListStorageSpaces(ctx context.Context, filters []*provider.List
|
||||
Root: root,
|
||||
}
|
||||
|
||||
spaces = append(spaces, space)
|
||||
}
|
||||
for _, share := range lsRes.Shares {
|
||||
root := &provider.ResourceId{
|
||||
StorageId: utils.OCMStorageProviderID,
|
||||
SpaceId: share.Id.OpaqueId,
|
||||
OpaqueId: share.Id.OpaqueId,
|
||||
}
|
||||
space := &provider.StorageSpace{
|
||||
Id: &provider.StorageSpaceId{
|
||||
OpaqueId: storagespace.FormatResourceID(*root),
|
||||
},
|
||||
SpaceType: "mountpoint",
|
||||
Owner: &userv1beta1.User{
|
||||
Id: share.Grantee.GetUserId(),
|
||||
},
|
||||
Root: root,
|
||||
}
|
||||
|
||||
spaces = append(spaces, space)
|
||||
}
|
||||
}
|
||||
|
||||
+17
-3
@@ -9,11 +9,11 @@ import (
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
invitev1beta1 "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1"
|
||||
permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
revactx "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
@@ -58,7 +58,7 @@ func GetServiceUserContextWithContext(ctx context.Context, gwc gateway.GatewayAP
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, authRes.Token), nil
|
||||
return metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, authRes.Token), nil
|
||||
}
|
||||
|
||||
// GetUser gets the specified user
|
||||
@@ -76,9 +76,23 @@ func GetUserWithContext(ctx context.Context, userID *user.UserId, gwc gateway.Ga
|
||||
|
||||
if err := checkStatusCode("getting user", getUserResponse.GetStatus().GetCode()); err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
return getUserResponse.GetUser(), nil
|
||||
}
|
||||
|
||||
// GetUserWithContext gets the specified accepted user
|
||||
func GetAcceptedUserWithContext(ctx context.Context, userID *user.UserId, gwc gateway.GatewayAPIClient) (*user.User, error) {
|
||||
getAcceptedUserResponse, err := gwc.GetAcceptedUser(ctx, &invitev1beta1.GetAcceptedUserRequest{RemoteUserId: userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getUserResponse.GetUser(), nil
|
||||
if err := checkStatusCode("getting accepted user", getAcceptedUserResponse.GetStatus().GetCode()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getAcceptedUserResponse.GetRemoteUser(), nil
|
||||
}
|
||||
|
||||
// GetSpace returns the given space
|
||||
|
||||
Reference in New Issue
Block a user