mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 11:41:32 +01:00 
			
		
		
		
	Add link to user profile in markdown mention only if user exists (#21533)
Previously mentioning a user would link to its profile, regardless of whether the user existed. This change tests if the user exists and only if it does - a link to its profile is added. * Fixes #3444 Signed-off-by: Yarden Shoham <hrsi88@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		
							parent
							
								
									82ecd3b19e
								
							
						
					
					
						commit
						63ebb53fd5
					
				| @ -33,6 +33,7 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| 	"code.gitea.io/gitea/routers" | ||||
| 	markup_service "code.gitea.io/gitea/services/markup" | ||||
| 
 | ||||
| 	"github.com/go-git/go-git/v5" | ||||
| 	"github.com/go-git/go-git/v5/config" | ||||
| @ -112,7 +113,7 @@ func runPR() { | ||||
| 	log.Printf("[PR] Setting up router\n") | ||||
| 	// routers.GlobalInit() | ||||
| 	external.RegisterRenderers() | ||||
| 	markup.Init() | ||||
| 	markup.Init(markup_service.ProcessorHelper()) | ||||
| 	c := routers.NormalRoutes(graceful.GetManager().HammerContext()) | ||||
| 
 | ||||
| 	log.Printf("[PR] Ready for testing !\n") | ||||
|  | ||||
| @ -603,8 +603,14 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) { | ||||
| 			start = loc.End | ||||
| 			continue | ||||
| 		} | ||||
| 		replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, mention[1:]), mention, "mention")) | ||||
| 		node = node.NextSibling.NextSibling | ||||
| 		mentionedUsername := mention[1:] | ||||
| 
 | ||||
| 		if processorHelper.IsUsernameMentionable != nil && processorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { | ||||
| 			replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, mentionedUsername), mention, "mention")) | ||||
| 			node = node.NextSibling.NextSibling | ||||
| 		} else { | ||||
| 			node = node.NextSibling | ||||
| 		} | ||||
| 		start = 0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -38,6 +38,11 @@ func TestMain(m *testing.M) { | ||||
| 	if err := git.InitSimple(context.Background()); err != nil { | ||||
| 		log.Fatal("git init failed, err: %v", err) | ||||
| 	} | ||||
| 	markup.Init(&markup.ProcessorHelper{ | ||||
| 		IsUsernameMentionable: func(ctx context.Context, username string) bool { | ||||
| 			return username == "r-lyeh" | ||||
| 		}, | ||||
| 	}) | ||||
| 	os.Exit(m.Run()) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -19,8 +19,18 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| type ProcessorHelper struct { | ||||
| 	IsUsernameMentionable func(ctx context.Context, username string) bool | ||||
| } | ||||
| 
 | ||||
| var processorHelper ProcessorHelper | ||||
| 
 | ||||
| // Init initialize regexps for markdown parsing | ||||
| func Init() { | ||||
| func Init(ph *ProcessorHelper) { | ||||
| 	if ph != nil { | ||||
| 		processorHelper = *ph | ||||
| 	} | ||||
| 
 | ||||
| 	NewSanitizer() | ||||
| 	if len(setting.Markdown.CustomURLSchemes) > 0 { | ||||
| 		CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes) | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| package misc | ||||
| 
 | ||||
| import ( | ||||
| 	go_context "context" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| @ -13,6 +14,7 @@ import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/markup" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	api "code.gitea.io/gitea/modules/structs" | ||||
| 	"code.gitea.io/gitea/modules/templates" | ||||
| @ -50,6 +52,11 @@ func wrap(ctx *context.Context) *context.APIContext { | ||||
| 
 | ||||
| func TestAPI_RenderGFM(t *testing.T) { | ||||
| 	setting.AppURL = AppURL | ||||
| 	markup.Init(&markup.ProcessorHelper{ | ||||
| 		IsUsernameMentionable: func(ctx go_context.Context, username string) bool { | ||||
| 			return username == "r-lyeh" | ||||
| 		}, | ||||
| 	}) | ||||
| 
 | ||||
| 	options := api.MarkdownOption{ | ||||
| 		Mode:    "gfm", | ||||
|  | ||||
| @ -41,6 +41,7 @@ import ( | ||||
| 	"code.gitea.io/gitea/services/automerge" | ||||
| 	"code.gitea.io/gitea/services/cron" | ||||
| 	"code.gitea.io/gitea/services/mailer" | ||||
| 	markup_service "code.gitea.io/gitea/services/markup" | ||||
| 	repo_migrations "code.gitea.io/gitea/services/migrations" | ||||
| 	mirror_service "code.gitea.io/gitea/services/mirror" | ||||
| 	pull_service "code.gitea.io/gitea/services/pull" | ||||
| @ -123,7 +124,7 @@ func GlobalInitInstalled(ctx context.Context) { | ||||
| 
 | ||||
| 	highlight.NewContext() | ||||
| 	external.RegisterRenderers() | ||||
| 	markup.Init() | ||||
| 	markup.Init(markup_service.ProcessorHelper()) | ||||
| 
 | ||||
| 	if setting.EnableSQLite3 { | ||||
| 		log.Info("SQLite3 support is enabled") | ||||
|  | ||||
							
								
								
									
										19
									
								
								services/markup/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								services/markup/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package markup | ||||
| 
 | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models/unittest" | ||||
| ) | ||||
| 
 | ||||
| func TestMain(m *testing.M) { | ||||
| 	unittest.MainTest(m, &unittest.TestOptions{ | ||||
| 		GiteaRootPath: filepath.Join("..", ".."), | ||||
| 		FixtureFiles:  []string{"user.yml"}, | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										29
									
								
								services/markup/processorhelper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								services/markup/processorhelper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package markup | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"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) | ||||
| 			if err != nil { | ||||
| 				log.Error("Failed to validate user in mention %q exists, assuming it does", username) | ||||
| 				userExists = true | ||||
| 			} | ||||
| 			return userExists | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										20
									
								
								services/markup/processorhelper_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								services/markup/processorhelper_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package markup | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models/unittest" | ||||
| 
 | ||||
| 	"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")) | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user