From d2efbe4d14c9b766d7abcb31c95e4a257d37e17e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 18 Sep 2024 15:23:14 +0200 Subject: [PATCH] feat(auth): pass public link user in context Signed-off-by: jkoberg --- changelog/unreleased/fix-publiclink-user.md | 5 ++ pkg/auth/manager/ocmshares/ocmshares.go | 2 + pkg/auth/manager/publicshares/publicshares.go | 7 ++- pkg/events/postprocessing.go | 54 ++++++++++--------- .../utils/decomposedfs/decomposedfs.go | 7 +-- .../utils/decomposedfs/upload/session.go | 11 +++- .../utils/decomposedfs/upload/upload.go | 25 ++++++--- 7 files changed, 73 insertions(+), 38 deletions(-) create mode 100644 changelog/unreleased/fix-publiclink-user.md diff --git a/changelog/unreleased/fix-publiclink-user.md b/changelog/unreleased/fix-publiclink-user.md new file mode 100644 index 0000000000..ce681bf146 --- /dev/null +++ b/changelog/unreleased/fix-publiclink-user.md @@ -0,0 +1,5 @@ +Bugfix: Populate public link user correctly + +When authenticating via public link, always add the `public` user instead of the link owner + +https://github.com/cs3org/reva/pull/4852 diff --git a/pkg/auth/manager/ocmshares/ocmshares.go b/pkg/auth/manager/ocmshares/ocmshares.go index 2cd14b9a24..80dc2279f5 100644 --- a/pkg/auth/manager/ocmshares/ocmshares.go +++ b/pkg/auth/manager/ocmshares/ocmshares.go @@ -159,6 +159,8 @@ func (m *manager) Authenticate(ctx context.Context, ocmshare, sharedSecret strin }, } + user.Opaque = utils.AppendJSONToOpaque(user.Opaque, "impersonating-user", userRes.RemoteUser) + return user, scope, nil } diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index d7a513362d..c47f80a896 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -25,7 +25,6 @@ import ( authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - userprovider "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" @@ -34,6 +33,7 @@ import ( "github.com/cs3org/reva/v2/pkg/auth/scope" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/v2/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -132,7 +132,7 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user if publicShareResponse.GetShare().GetOwner().GetType() == 8 { owner = &user.User{Id: publicShareResponse.GetShare().GetOwner(), DisplayName: "Public", Username: "public"} } else { - getUserResponse, err := gwConn.GetUser(ctx, &userprovider.GetUserRequest{ + getUserResponse, err := gwConn.GetUser(ctx, &user.GetUserRequest{ UserId: publicShareResponse.GetShare().GetCreator(), }) switch { @@ -173,6 +173,9 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user }, } + u := &user.User{Id: &user.UserId{OpaqueId: token, Idp: "public", Type: user.UserType_USER_TYPE_GUEST}, DisplayName: "Public", Username: "public"} + owner.Opaque = utils.AppendJSONToOpaque(owner.Opaque, "impersonating-user", u) + return owner, scope, nil } diff --git a/pkg/events/postprocessing.go b/pkg/events/postprocessing.go index c28b8cc5a5..3921095eb0 100644 --- a/pkg/events/postprocessing.go +++ b/pkg/events/postprocessing.go @@ -57,14 +57,15 @@ var ( // BytesReceived is emitted by the server when it received all bytes of an upload type BytesReceived struct { - UploadID string - SpaceOwner *user.UserId - ExecutingUser *user.User - ResourceID *provider.ResourceId - Filename string - Filesize uint64 - URL string - Timestamp *types.Timestamp + UploadID string + SpaceOwner *user.UserId + ExecutingUser *user.User + ResourceID *provider.ResourceId + Filename string + Filesize uint64 + URL string + Timestamp *types.Timestamp + ImpersonatingUser *user.User } // Unmarshal to fulfill umarshaller interface @@ -85,8 +86,9 @@ type StartPostprocessingStep struct { ResourceID *provider.ResourceId // for file retrieval in after upload case RevaToken string // for file retrieval in after upload case - StepToStart Postprocessingstep - Timestamp *types.Timestamp + StepToStart Postprocessingstep + Timestamp *types.Timestamp + ImpersonatingUser *user.User } // Unmarshal to fulfill umarshaller interface @@ -141,13 +143,14 @@ type VirusscanResult struct { // PostprocessingFinished is emitted by *some* service which can decide that type PostprocessingFinished struct { - UploadID string - Filename string - SpaceOwner *user.UserId - ExecutingUser *user.User - Result map[Postprocessingstep]interface{} // it is a map[step]Event - Outcome PostprocessingOutcome - Timestamp *types.Timestamp + UploadID string + Filename string + SpaceOwner *user.UserId + ExecutingUser *user.User + Result map[Postprocessingstep]interface{} // it is a map[step]Event + Outcome PostprocessingOutcome + Timestamp *types.Timestamp + ImpersonatingUser *user.User } // Unmarshal to fulfill umarshaller interface @@ -175,14 +178,15 @@ func (PostprocessingRetry) Unmarshal(v []byte) (interface{}, error) { // UploadReady is emitted by the storage provider when postprocessing is finished type UploadReady struct { - UploadID string - Filename string - SpaceOwner *user.UserId - ExecutingUser *user.User - FileRef *provider.Reference - Timestamp *types.Timestamp - Failed bool - IsVersion bool + UploadID string + Filename string + SpaceOwner *user.UserId + ExecutingUser *user.User + ImpersonatingUser *user.User + FileRef *provider.Reference + Timestamp *types.Timestamp + Failed bool + IsVersion bool // add reference here? We could use it to inform client pp is finished } diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index 1456f3574a..fdd9557c48 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -382,9 +382,10 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { }, Path: utils.MakeRelativePath(filepath.Join(session.Dir(), session.Filename())), }, - Timestamp: utils.TimeToTS(now), - SpaceOwner: n.SpaceOwnerOrManager(ctx), - IsVersion: isVersion, + Timestamp: utils.TimeToTS(now), + SpaceOwner: n.SpaceOwnerOrManager(ctx), + IsVersion: isVersion, + ImpersonatingUser: ev.ImpersonatingUser, }, ); err != nil { sublog.Error().Err(err).Msg("Failed to publish UploadReady event") diff --git a/pkg/storage/utils/decomposedfs/upload/session.go b/pkg/storage/utils/decomposedfs/upload/session.go index 60adc4cf3a..a83d5f46b5 100644 --- a/pkg/storage/utils/decomposedfs/upload/session.go +++ b/pkg/storage/utils/decomposedfs/upload/session.go @@ -32,6 +32,7 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/v2/pkg/appctx" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/logger" @@ -64,13 +65,17 @@ func (s *OcisSession) lockID() string { return s.info.MetaData["lockid"] } func (s *OcisSession) executantUser() *userpb.User { + var o *typespb.Opaque + _ = json.Unmarshal([]byte(s.info.Storage["UserOpaque"]), &o) return &userpb.User{ Id: &userpb.UserId{ Type: userpb.UserType(userpb.UserType_value[s.info.Storage["UserType"]]), Idp: s.info.Storage["Idp"], OpaqueId: s.info.Storage["UserId"], }, - Username: s.info.Storage["UserName"], + Username: s.info.Storage["UserName"], + DisplayName: s.info.Storage["UserDisplayName"], + Opaque: o, } } @@ -277,6 +282,10 @@ func (s *OcisSession) SetExecutant(u *userpb.User) { s.info.Storage["UserId"] = u.GetId().GetOpaqueId() s.info.Storage["UserType"] = utils.UserTypeToString(u.GetId().Type) s.info.Storage["UserName"] = u.GetUsername() + s.info.Storage["UserDisplayName"] = u.GetDisplayName() + + b, _ := json.Marshal(u.GetOpaque()) + s.info.Storage["UserOpaque"] = string(b) } // Offset returns the current upload offset diff --git a/pkg/storage/utils/decomposedfs/upload/upload.go b/pkg/storage/utils/decomposedfs/upload/upload.go index 4a3bfc61c2..950e6ec6ee 100644 --- a/pkg/storage/utils/decomposedfs/upload/upload.go +++ b/pkg/storage/utils/decomposedfs/upload/upload.go @@ -30,6 +30,7 @@ import ( "strings" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/appctx" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" @@ -38,6 +39,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/metrics" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/metadata/prefixes" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node" + "github.com/cs3org/reva/v2/pkg/utils" "github.com/golang-jwt/jwt" "github.com/pkg/errors" tusd "github.com/tus/tusd/v2/pkg/handler" @@ -178,14 +180,23 @@ func (session *OcisSession) FinishUpload(ctx context.Context) error { return err } + var iu *userpb.User + if utils.ExistsInOpaque(u.Opaque, "impersonating-user") { + iu := &userpb.User{} + if err := utils.ReadJSONFromOpaque(u.Opaque, "impersonating-user", iu); err != nil { + return err + } + } + if err := events.Publish(ctx, session.store.pub, events.BytesReceived{ - UploadID: session.ID(), - URL: s, - SpaceOwner: n.SpaceOwnerOrManager(session.Context(ctx)), - ExecutingUser: u, - ResourceID: &provider.ResourceId{SpaceId: n.SpaceID, OpaqueId: n.ID}, - Filename: session.Filename(), - Filesize: uint64(session.Size()), + UploadID: session.ID(), + URL: s, + SpaceOwner: n.SpaceOwnerOrManager(session.Context(ctx)), + ExecutingUser: u, + ResourceID: &provider.ResourceId{SpaceId: n.SpaceID, OpaqueId: n.ID}, + Filename: session.Filename(), + Filesize: uint64(session.Size()), + ImpersonatingUser: iu, }); err != nil { return err }