Skip to content

Commit

Permalink
[full-ci] fix an error when lock/unlock a public shared file
Browse files Browse the repository at this point in the history
  • Loading branch information
2403905 committed Feb 22, 2024
1 parent 694b9b2 commit 219ec22
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/fix-public-link-lock.md
@@ -0,0 +1,6 @@
Bugfix: Fix an error when lock/unlock a file

We fixed a bug when anonymous user with viewer role in public link of a folder can lock/unlock a file inside it

https://github.com/cs3org/reva/pull/4518
https://github.com/owncloud/ocis/issues/7785
24 changes: 24 additions & 0 deletions internal/grpc/services/storageprovider/storageprovider.go
Expand Up @@ -33,6 +33,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/pkg/appctx"
"github.com/cs3org/reva/v2/pkg/conversions"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/events"
Expand Down Expand Up @@ -230,6 +231,11 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse

// SetLock puts a lock on the given reference
func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
if !canLockPublicShare(ctx) {
return &provider.SetLockResponse{
Status: status.NewPermissionDenied(ctx, nil, "no permission to lock the share"),
}, nil
}
err := s.storage.SetLock(ctx, req.Ref, req.Lock)

return &provider.SetLockResponse{
Expand All @@ -249,6 +255,12 @@ func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*p

// RefreshLock refreshes an existing lock on the given reference
func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) {
if !canLockPublicShare(ctx) {
return &provider.RefreshLockResponse{
Status: status.NewPermissionDenied(ctx, nil, "no permission to refresh the share lock"),
}, nil
}

err := s.storage.RefreshLock(ctx, req.Ref, req.Lock, req.ExistingLockId)

return &provider.RefreshLockResponse{
Expand All @@ -258,6 +270,12 @@ func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequ

// Unlock removes an existing lock from the given reference
func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) {
if !canLockPublicShare(ctx) {
return &provider.UnlockResponse{
Status: status.NewPermissionDenied(ctx, nil, "no permission to unlock the share"),
}, nil
}

err := s.storage.Unlock(ctx, req.Ref, req.Lock)

return &provider.UnlockResponse{
Expand Down Expand Up @@ -1285,3 +1303,9 @@ func estreamFromConfig(c eventconfig) (events.Stream, error) {

return stream.NatsFromConfig("storageprovider", false, stream.NatsConfig(c))
}

func canLockPublicShare(ctx context.Context) bool {
u := ctxpkg.ContextMustGetUser(ctx)
psr := utils.ReadPlainFromOpaque(u.Opaque, "public-share-role")
return psr == "" || psr == conversions.RoleEditor
}
31 changes: 19 additions & 12 deletions internal/http/services/owncloud/ocdav/locks.go
Expand Up @@ -260,11 +260,15 @@ func (cls *cs3LS) Unlock(ctx context.Context, now time.Time, ref *provider.Refer
return err
}

switch res.Status.Code {
switch res.GetStatus().GetCode() {
case rpc.Code_CODE_OK:
return nil
case rpc.Code_CODE_FAILED_PRECONDITION:
return errtypes.Aborted("file is not locked")
case rpc.Code_CODE_LOCKED:
appctx.GetLogger(ctx).Error().Str("token", token).Interface("unlock", ref).
Msg("could not unlock " + res.GetStatus().GetMessage())
return errtypes.Locked("another token")
default:
return errtypes.NewErrtypeFromStatus(res.Status)
}
Expand Down Expand Up @@ -639,16 +643,19 @@ func (s *svc) unlockReference(ctx context.Context, _ http.ResponseWriter, r *htt
t = t[1 : len(t)-1]
}

switch err := s.LockSystem.Unlock(ctx, time.Now(), ref, t); err {
case nil:
return http.StatusNoContent, err
case errors.ErrForbidden:
return http.StatusForbidden, err
case errors.ErrLocked:
return http.StatusLocked, err
case errors.ErrNoSuchLock:
return http.StatusConflict, err
default:
return http.StatusInternalServerError, err
err := s.LockSystem.Unlock(ctx, time.Now(), ref, t)
if err == nil {
return http.StatusNoContent, nil
} else {
switch err.(type) {
case errtypes.Aborted, errtypes.Locked:
return http.StatusLocked, err
case errtypes.PermissionDenied:
return http.StatusForbidden, err
case errtypes.PreconditionFailed:
return http.StatusConflict, err
default:
return http.StatusInternalServerError, err
}
}
}

0 comments on commit 219ec22

Please sign in to comment.