Skip to content

Commit 0548c10

Browse files
Add post-installation redirect based on admin account status (#34493)
This PR adds a feature to direct users to appropriate pages after system installation: - If no admin credentials were provided during installation, redirect to the registration page with a prominent notice about creating the first administrative account - If admin credentials were already set, redirect directly to the login page ![4d396ad132d9b57fc4f45a62117177f1](https://github.com/user-attachments/assets/3a5d8700-9194-4d3b-a862-e64c8c347932) --------- Co-authored-by: wxiaoguang <[email protected]>
1 parent 7de114a commit 0548c10

File tree

7 files changed

+32
-4
lines changed

7 files changed

+32
-4
lines changed

models/user/user.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,20 @@ type CountUserFilter struct {
831831
IsActive optional.Option[bool]
832832
}
833833

834+
// HasUsers checks whether there are any users in the database, or only one user exists.
835+
func HasUsers(ctx context.Context) (ret struct {
836+
HasAnyUser, HasOnlyOneUser bool
837+
}, err error,
838+
) {
839+
res, err := db.GetEngine(ctx).Table(&User{}).Cols("id").Limit(2).Query()
840+
if err != nil {
841+
return ret, fmt.Errorf("error checking user existence: %w", err)
842+
}
843+
ret.HasAnyUser = len(res) != 0
844+
ret.HasOnlyOneUser = len(res) == 1
845+
return ret, nil
846+
}
847+
834848
// CountUsers returns number of users.
835849
func CountUsers(ctx context.Context, opts *CountUserFilter) int64 {
836850
return countUsers(ctx, opts)

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ remember_me.compromised = The login token is not valid anymore which may indicat
421421
forgot_password_title= Forgot Password
422422
forgot_password = Forgot password?
423423
need_account = Need an account?
424+
sign_up_tip = You are registering the first account in the system, which has administrator privileges. Please carefully remember your username and password. If you forget the username or password, please refer to the Gitea documentation to recover the account.
424425
sign_up_now = Register now.
425426
sign_up_successful = Account was successfully created. Welcome!
426427
confirmation_mail_sent_prompt_ex = A new confirmation email has been sent to <b>%s</b>. Please check your inbox within the next %s to complete the registration process. If your registration email address is incorrect, you can sign in again and change it.

routers/install/install.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,5 +601,7 @@ func SubmitInstall(ctx *context.Context) {
601601
// InstallDone shows the "post-install" page, makes it easier to develop the page.
602602
// The name is not called as "PostInstall" to avoid misinterpretation as a handler for "POST /install"
603603
func InstallDone(ctx *context.Context) { //nolint
604+
hasUsers, _ := user_model.HasUsers(ctx)
605+
ctx.Data["IsAccountCreated"] = hasUsers.HasAnyUser
604606
ctx.HTML(http.StatusOK, tplPostInstall)
605607
}

routers/web/auth/auth.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,11 @@ func SignOut(ctx *context.Context) {
421421
// SignUp render the register page
422422
func SignUp(ctx *context.Context) {
423423
ctx.Data["Title"] = ctx.Tr("sign_up")
424-
425424
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
426425

426+
hasUsers, _ := user_model.HasUsers(ctx)
427+
ctx.Data["IsFirstTimeRegistration"] = !hasUsers.HasAnyUser
428+
427429
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
428430
if err != nil {
429431
ctx.ServerError("UserSignUp", err)
@@ -610,7 +612,13 @@ func createUserInContext(ctx *context.Context, tpl templates.TplName, form any,
610612
// sends a confirmation email if required.
611613
func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.User) (ok bool) {
612614
// Auto-set admin for the only user.
613-
if user_model.CountUsers(ctx, nil) == 1 {
615+
hasUsers, err := user_model.HasUsers(ctx)
616+
if err != nil {
617+
ctx.ServerError("HasUsers", err)
618+
return false
619+
}
620+
if hasUsers.HasOnlyOneUser {
621+
// the only user is the one just created, will set it as admin
614622
opts := &user_service.UpdateOptions{
615623
IsActive: optional.Some(true),
616624
IsAdmin: user_service.UpdateOptionFieldFromValue(true),

templates/post-install.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<!-- the "cup" has a handler, so move it a little leftward to make it visually in the center -->
55
<div class="tw-ml-[-30px]"><img width="160" src="{{AssetUrlPrefix}}/img/loading.png" alt aria-hidden="true"></div>
66
<div class="tw-my-[2em] tw-text-[18px]">
7-
<a id="goto-user-login" href="{{AppSubUrl}}/user/login">{{ctx.Locale.Tr "install.installing_desc"}}</a>
7+
<a id="goto-after-install" href="{{AppSubUrl}}{{Iif .IsAccountCreated "/user/login" "/user/sign_up"}}">{{ctx.Locale.Tr "install.installing_desc"}}</a>
88
</div>
99
</div>
1010
</div>

templates/user/auth/signup_inner.tmpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
{{end}}
88
</h4>
99
<div class="ui attached segment">
10+
{{if .IsFirstTimeRegistration}}
11+
<p>{{ctx.Locale.Tr "auth.sign_up_tip"}}</p>
12+
{{end}}
1013
<form class="ui form" action="{{.SignUpLink}}" method="post">
1114
{{.CsrfTokenHtml}}
1215
{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister)}}

web_src/js/features/install.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ function initPreInstall() {
104104
}
105105

106106
function initPostInstall() {
107-
const el = document.querySelector('#goto-user-login');
107+
const el = document.querySelector('#goto-after-install');
108108
if (!el) return;
109109

110110
const targetUrl = el.getAttribute('href');

0 commit comments

Comments
 (0)