mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add ui.explore settings to control view of explore pages (2) (#14094)
This is an alternative PR to #13687. Add `[ui.explore]` settings to allow restricting the explore pages to logged in users only and to disable the users explore page. The two proposed settings are: - `REQUIRE_SIGNIN_VIEW`: Only allows access to the explore pages if the user is signed in. Also restricts - `/api/v1/user/search` - `/api/v1/users/{username}` - `/api/v1/users/{username}/repos` - but does not restrict `/api/v1/users/{username}/heatmap` - `DISABLE_USERS_PAGE`: Disables the /explore/users page Fix #2908 Close #13687 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		@@ -479,6 +479,12 @@ relation to port exhaustion.
 | 
				
			|||||||
  The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
 | 
					  The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
 | 
				
			||||||
- `USER_DELETE_WITH_COMMENTS_MAX_TIME`: **0** Minimum amount of time a user must exist before comments are kept when the user is deleted.
 | 
					- `USER_DELETE_WITH_COMMENTS_MAX_TIME`: **0** Minimum amount of time a user must exist before comments are kept when the user is deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Service - Expore (`service.explore`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `REQUIRE_SIGNIN_VIEW`: **false**: Only allow signed in users to view the explore pages.
 | 
				
			||||||
 | 
					- `DISABLE_USERS_PAGE`: **false**: Disable the users explore page.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## SSH Minimum Key Sizes (`ssh.minimum_key_sizes`)
 | 
					## SSH Minimum Key Sizes (`ssh.minimum_key_sizes`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Define allowed algorithms and their minimum key length (use -1 to disable a type):
 | 
					Define allowed algorithms and their minimum key length (use -1 to disable a type):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,6 +135,11 @@ menu:
 | 
				
			|||||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: 允许通过反向认证做自动注册。
 | 
					- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: 允许通过反向认证做自动注册。
 | 
				
			||||||
- `ENABLE_CAPTCHA`: 注册时使用图片验证码。
 | 
					- `ENABLE_CAPTCHA`: 注册时使用图片验证码。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Service - Expore (`service.explore`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `REQUIRE_SIGNIN_VIEW`: **false**: 仅允许已登录的用户查看探索页面。
 | 
				
			||||||
 | 
					- `DISABLE_USERS_PAGE`: **false**: 不显示用户探索页面。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Webhook (`webhook`)
 | 
					## Webhook (`webhook`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `QUEUE_LENGTH`: 说明: Hook 任务队列长度。
 | 
					- `QUEUE_LENGTH`: 说明: Hook 任务队列长度。
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/structs"
 | 
						"code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,6 +60,12 @@ var Service struct {
 | 
				
			|||||||
	EnableOpenIDSignUp bool
 | 
						EnableOpenIDSignUp bool
 | 
				
			||||||
	OpenIDWhitelist    []*regexp.Regexp
 | 
						OpenIDWhitelist    []*regexp.Regexp
 | 
				
			||||||
	OpenIDBlacklist    []*regexp.Regexp
 | 
						OpenIDBlacklist    []*regexp.Regexp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Explore page settings
 | 
				
			||||||
 | 
						Explore struct {
 | 
				
			||||||
 | 
							RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
 | 
				
			||||||
 | 
							DisableUsersPage  bool `ini:"DISABLE_USERS_PAGE"`
 | 
				
			||||||
 | 
						} `ini:"service.explore"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newService() {
 | 
					func newService() {
 | 
				
			||||||
@@ -108,6 +115,10 @@ func newService() {
 | 
				
			|||||||
	Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
 | 
						Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
 | 
				
			||||||
	Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
 | 
						Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := Cfg.Section("service.explore").MapTo(&Service.Explore); err != nil {
 | 
				
			||||||
 | 
							log.Fatal("Failed to map service.explore settings: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec = Cfg.Section("openid")
 | 
						sec = Cfg.Section("openid")
 | 
				
			||||||
	Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)
 | 
						Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)
 | 
				
			||||||
	Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn)
 | 
						Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,6 +204,14 @@ func reqToken() func(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func reqExploreSignIn() func(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						return func(ctx *context.APIContext) {
 | 
				
			||||||
 | 
							if setting.Service.Explore.RequireSigninView && !ctx.IsSigned {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusUnauthorized, "reqExploreSignIn", "you must be signed in to search for users")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func reqBasicAuth() func(ctx *context.APIContext) {
 | 
					func reqBasicAuth() func(ctx *context.APIContext) {
 | 
				
			||||||
	return func(ctx *context.APIContext) {
 | 
						return func(ctx *context.APIContext) {
 | 
				
			||||||
		if !ctx.Context.IsBasicAuth {
 | 
							if !ctx.Context.IsBasicAuth {
 | 
				
			||||||
@@ -603,16 +611,16 @@ func Routes() *web.Route {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// Users
 | 
							// Users
 | 
				
			||||||
		m.Group("/users", func() {
 | 
							m.Group("/users", func() {
 | 
				
			||||||
			m.Get("/search", user.Search)
 | 
								m.Get("/search", reqExploreSignIn(), user.Search)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			m.Group("/{username}", func() {
 | 
								m.Group("/{username}", func() {
 | 
				
			||||||
				m.Get("", user.GetInfo)
 | 
									m.Get("", reqExploreSignIn(), user.GetInfo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if setting.Service.EnableUserHeatmap {
 | 
									if setting.Service.EnableUserHeatmap {
 | 
				
			||||||
					m.Get("/heatmap", user.GetUserHeatmapData)
 | 
										m.Get("/heatmap", user.GetUserHeatmapData)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				m.Get("/repos", user.ListUserRepos)
 | 
									m.Get("/repos", reqExploreSignIn(), user.ListUserRepos)
 | 
				
			||||||
				m.Group("/tokens", func() {
 | 
									m.Group("/tokens", func() {
 | 
				
			||||||
					m.Combo("").Get(user.ListAccessTokens).
 | 
										m.Combo("").Get(user.ListAccessTokens).
 | 
				
			||||||
						Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
 | 
											Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,6 +171,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ExploreRepos render explore repositories page
 | 
					// ExploreRepos render explore repositories page
 | 
				
			||||||
func ExploreRepos(ctx *context.Context) {
 | 
					func ExploreRepos(ctx *context.Context) {
 | 
				
			||||||
 | 
						ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("explore")
 | 
						ctx.Data["Title"] = ctx.Tr("explore")
 | 
				
			||||||
	ctx.Data["PageIsExplore"] = true
 | 
						ctx.Data["PageIsExplore"] = true
 | 
				
			||||||
	ctx.Data["PageIsExploreRepositories"] = true
 | 
						ctx.Data["PageIsExploreRepositories"] = true
 | 
				
			||||||
@@ -247,6 +248,10 @@ func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplN
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ExploreUsers render explore users page
 | 
					// ExploreUsers render explore users page
 | 
				
			||||||
func ExploreUsers(ctx *context.Context) {
 | 
					func ExploreUsers(ctx *context.Context) {
 | 
				
			||||||
 | 
						if setting.Service.Explore.DisableUsersPage {
 | 
				
			||||||
 | 
							ctx.Redirect(setting.AppSubURL + "/explore/repos")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("explore")
 | 
						ctx.Data["Title"] = ctx.Tr("explore")
 | 
				
			||||||
	ctx.Data["PageIsExplore"] = true
 | 
						ctx.Data["PageIsExplore"] = true
 | 
				
			||||||
	ctx.Data["PageIsExploreUsers"] = true
 | 
						ctx.Data["PageIsExploreUsers"] = true
 | 
				
			||||||
@@ -263,6 +268,7 @@ func ExploreUsers(ctx *context.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ExploreOrganizations render explore organizations page
 | 
					// ExploreOrganizations render explore organizations page
 | 
				
			||||||
func ExploreOrganizations(ctx *context.Context) {
 | 
					func ExploreOrganizations(ctx *context.Context) {
 | 
				
			||||||
 | 
						ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("explore")
 | 
						ctx.Data["Title"] = ctx.Tr("explore")
 | 
				
			||||||
	ctx.Data["PageIsExplore"] = true
 | 
						ctx.Data["PageIsExplore"] = true
 | 
				
			||||||
	ctx.Data["PageIsExploreOrganizations"] = true
 | 
						ctx.Data["PageIsExploreOrganizations"] = true
 | 
				
			||||||
@@ -288,6 +294,7 @@ func ExploreCode(ctx *context.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
 | 
				
			||||||
	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
 | 
						ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("explore")
 | 
						ctx.Data["Title"] = ctx.Tr("explore")
 | 
				
			||||||
	ctx.Data["PageIsExplore"] = true
 | 
						ctx.Data["PageIsExplore"] = true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,6 +286,7 @@ func goGet(ctx *context.Context) {
 | 
				
			|||||||
func RegisterRoutes(m *web.Route) {
 | 
					func RegisterRoutes(m *web.Route) {
 | 
				
			||||||
	reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true})
 | 
						reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true})
 | 
				
			||||||
	ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
 | 
						ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
 | 
				
			||||||
 | 
						ignExploreSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView})
 | 
				
			||||||
	ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
 | 
						ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
 | 
				
			||||||
	reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
 | 
						reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -335,7 +336,7 @@ func RegisterRoutes(m *web.Route) {
 | 
				
			|||||||
		m.Get("/users", routers.ExploreUsers)
 | 
							m.Get("/users", routers.ExploreUsers)
 | 
				
			||||||
		m.Get("/organizations", routers.ExploreOrganizations)
 | 
							m.Get("/organizations", routers.ExploreOrganizations)
 | 
				
			||||||
		m.Get("/code", routers.ExploreCode)
 | 
							m.Get("/code", routers.ExploreCode)
 | 
				
			||||||
	}, ignSignIn)
 | 
						}, ignExploreSignIn)
 | 
				
			||||||
	m.Get("/issues", reqSignIn, user.Issues)
 | 
						m.Get("/issues", reqSignIn, user.Issues)
 | 
				
			||||||
	m.Get("/pulls", reqSignIn, user.Pulls)
 | 
						m.Get("/pulls", reqSignIn, user.Pulls)
 | 
				
			||||||
	m.Get("/milestones", reqSignIn, reqMilestonesDashboardPageEnabled, user.Milestones)
 | 
						m.Get("/milestones", reqSignIn, reqMilestonesDashboardPageEnabled, user.Milestones)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,9 +2,11 @@
 | 
				
			|||||||
	<a class="{{if .PageIsExploreRepositories}}active{{end}} item" href="{{AppSubUrl}}/explore/repos">
 | 
						<a class="{{if .PageIsExploreRepositories}}active{{end}} item" href="{{AppSubUrl}}/explore/repos">
 | 
				
			||||||
		{{svg "octicon-repo"}} {{.i18n.Tr "explore.repos"}}
 | 
							{{svg "octicon-repo"}} {{.i18n.Tr "explore.repos"}}
 | 
				
			||||||
	</a>
 | 
						</a>
 | 
				
			||||||
 | 
						{{if not .UsersIsDisabled}}
 | 
				
			||||||
		<a class="{{if .PageIsExploreUsers}}active{{end}} item" href="{{AppSubUrl}}/explore/users">
 | 
							<a class="{{if .PageIsExploreUsers}}active{{end}} item" href="{{AppSubUrl}}/explore/users">
 | 
				
			||||||
			{{svg "octicon-person"}} {{.i18n.Tr "explore.users"}}
 | 
								{{svg "octicon-person"}} {{.i18n.Tr "explore.users"}}
 | 
				
			||||||
		</a>
 | 
							</a>
 | 
				
			||||||
 | 
						{{end}}
 | 
				
			||||||
	<a class="{{if .PageIsExploreOrganizations}}active{{end}} item" href="{{AppSubUrl}}/explore/organizations">
 | 
						<a class="{{if .PageIsExploreOrganizations}}active{{end}} item" href="{{AppSubUrl}}/explore/organizations">
 | 
				
			||||||
		{{svg "octicon-organization"}} {{.i18n.Tr "explore.organizations"}}
 | 
							{{svg "octicon-organization"}} {{.i18n.Tr "explore.organizations"}}
 | 
				
			||||||
	</a>
 | 
						</a>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user