Merge pull request 'feat: Add option to disable builtin authentication' (#6112) from squel/forgejo-disable-internal-signin into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6112
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
This commit is contained in:
Gusted 2024-12-01 19:02:05 +00:00
commit d35bc0e636
6 changed files with 59 additions and 0 deletions

View file

@ -901,6 +901,9 @@ LEVEL = Info
;; Show Registration button
;SHOW_REGISTRATION_BUTTON = true
;;
;; Whether to allow internal signin
; ENABLE_INTERNAL_SIGNIN = true
;;
;; Show milestones dashboard page - a view of all the user's milestones
;SHOW_MILESTONES_DASHBOARD_PAGE = true
;;

View file

@ -43,6 +43,7 @@ var Service = struct {
AllowOnlyInternalRegistration bool
AllowOnlyExternalRegistration bool
ShowRegistrationButton bool
EnableInternalSignIn bool
ShowMilestonesDashboardPage bool
RequireSignInView bool
EnableNotifyMail bool
@ -175,6 +176,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
Service.EmailDomainBlockList = append(Service.EmailDomainBlockList, toAdd...)
}
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
Service.EnableInternalSignIn = sec.Key("ENABLE_INTERNAL_SIGNIN").MustBool(true)
Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true)
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true)

View file

@ -164,6 +164,7 @@ func SignIn(ctx *context.Context) {
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled(ctx)
ctx.Data["EnableInternalSignIn"] = setting.Service.EnableInternalSignIn
if setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin {
context.SetCaptchaData(ctx)
@ -187,6 +188,13 @@ func SignInPost(ctx *context.Context) {
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled(ctx)
ctx.Data["EnableInternalSignIn"] = setting.Service.EnableInternalSignIn
// Permission denied if EnableInternalSignIn is false
if !setting.Service.EnableInternalSignIn {
ctx.Error(http.StatusForbidden)
return
}
if ctx.HasError() {
ctx.HTML(http.StatusOK, tplSignIn)

View file

@ -1,7 +1,9 @@
{{if or .OAuth2Providers .EnableOpenIDSignIn}}
{{if .EnableInternalSignIn}}
<div class="divider divider-text">
{{ctx.Locale.Tr "sign_in_or"}}
</div>
{{end}}
<div id="oauth2-login-navigator" class="tw-py-1">
<div class="tw-flex tw-flex-col tw-justify-center">
<div id="oauth2-login-navigator-inner" class="tw-flex tw-flex-col tw-flex-wrap tw-items-center tw-gap-2">

View file

@ -10,6 +10,7 @@
{{end}}
</h4>
<div class="ui attached segment">
{{if .EnableInternalSignIn}}
<form class="ui form" action="{{.SignInLink}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
@ -43,6 +44,7 @@
</button>
</div>
</form>
{{end}}
{{template "user/auth/oauth_container" .}}
</div>

View file

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/tests"
@ -93,3 +94,44 @@ func TestSigninWithRememberMe(t *testing.T) {
req = NewRequest(t, "GET", "/user/settings")
session.MakeRequest(t, req, http.StatusOK)
}
func TestDisableSignin(t *testing.T) {
defer tests.PrepareTestEnv(t)()
t.Run("Disabled", func(t *testing.T) {
defer test.MockVariableValue(&setting.Service.EnableInternalSignIn, false)()
t.Run("UI", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user/login")
resp := MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
htmlDoc.AssertElement(t, "form[action='/user/login']", false)
})
t.Run("Signin", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "POST", "/user/login")
MakeRequest(t, req, http.StatusForbidden)
})
})
t.Run("Enabled", func(t *testing.T) {
defer test.MockVariableValue(&setting.Service.EnableInternalSignIn, true)()
t.Run("UI", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user/login")
resp := MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
htmlDoc.AssertElement(t, "form[action='/user/login']", true)
})
t.Run("Signin", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "POST", "/user/login")
MakeRequest(t, req, http.StatusOK)
})
})
}