From 88a03a6133e90337ee17cb0277f306f54877f34b Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Sun, 23 Oct 2022 12:13:52 +0300 Subject: [PATCH] Link mentioned user in markdown only if they are visible to viewer (#21554) We need to make sure a user can't confirm the existence of a user with private visibility * Follow up on #21533 ### Before #### User ![image](https://user-images.githubusercontent.com/20454870/197357580-340911d7-1659-4fc9-a9f6-7ed6bc3476b4.png) #### Admin ![image](https://user-images.githubusercontent.com/20454870/197357676-a8f0ae63-8f80-4221-a9b5-b6311552910a.png) ### After #### User ![image](https://user-images.githubusercontent.com/20454870/197357536-05616edb-7821-469d-8e51-6f8cb84c1362.png) #### Admin ![image](https://user-images.githubusercontent.com/20454870/197357703-071fe984-de79-43aa-a77c-a85b046292a4.png) Signed-off-by: Yarden Shoham Co-authored-by: wxiaoguang Co-authored-by: Lunny Xiao --- services/markup/processorhelper.go | 20 +++++++------ services/markup/processorhelper_test.go | 37 +++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go index 2b1cac2a5b886..5042884e5ef9a 100644 --- a/services/markup/processorhelper.go +++ b/services/markup/processorhelper.go @@ -8,22 +8,26 @@ import ( "context" "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" + gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/markup" ) func ProcessorHelper() *markup.ProcessorHelper { return &markup.ProcessorHelper{ IsUsernameMentionable: func(ctx context.Context, username string) bool { - // TODO: cast ctx to modules/context.Context and use IsUserVisibleToViewer - - // Only link if the user actually exists - userExists, err := user.IsUserExist(ctx, 0, username) + mentionedUser, err := user.GetUserByName(ctx, username) if err != nil { - log.Error("Failed to validate user in mention %q exists, assuming it does", username) - userExists = true + return false + } + + giteaCtx, ok := ctx.(*gitea_context.Context) + if !ok { + // when using general context, use user's visibility to check + return mentionedUser.Visibility.IsPublic() } - return userExists + + // when using gitea context (web context), use user's visibility and user's permission to check + return user.IsUserVisibleToViewer(giteaCtx, mentionedUser, giteaCtx.Doer) }, } } diff --git a/services/markup/processorhelper_test.go b/services/markup/processorhelper_test.go index 386465bc9189c..f7eab3d958b0b 100644 --- a/services/markup/processorhelper_test.go +++ b/services/markup/processorhelper_test.go @@ -6,15 +6,48 @@ package markup import ( "context" + "net/http" "testing" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/models/user" + gitea_context "code.gitea.io/gitea/modules/context" "github.com/stretchr/testify/assert" ) func TestProcessorHelper(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, ProcessorHelper().IsUsernameMentionable(context.Background(), "user10")) - assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), "no-such-user")) + + userPublic := "user1" + userPrivate := "user31" + userLimited := "user33" + userNoSuch := "no-such-user" + + unittest.AssertCount(t, &user.User{Name: userPublic}, 1) + unittest.AssertCount(t, &user.User{Name: userPrivate}, 1) + unittest.AssertCount(t, &user.User{Name: userLimited}, 1) + unittest.AssertCount(t, &user.User{Name: userNoSuch}, 0) + + // when using general context, use user's visibility to check + assert.True(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPublic)) + assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userLimited)) + assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPrivate)) + assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userNoSuch)) + + // when using web context, use user.IsUserVisibleToViewer to check + var err error + giteaCtx := &gitea_context.Context{} + giteaCtx.Req, err = http.NewRequest("GET", "/", nil) + assert.NoError(t, err) + + giteaCtx.Doer = nil + assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic)) + assert.False(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate)) + + giteaCtx.Doer, err = user.GetUserByName(db.DefaultContext, userPrivate) + assert.NoError(t, err) + assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic)) + assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate)) }