Skip to content

Add post-installation redirect based on admin account status #34493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions models/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,20 @@ type CountUserFilter struct {
IsActive optional.Option[bool]
}

// HasUsers checks whether there are any users in the database, or only one user exists.
func HasUsers(ctx context.Context) (ret struct {
HasAnyUser, HasOnlyOneUser bool
}, err error,
) {
res, err := db.GetEngine(ctx).Table(&User{}).Cols("id").Limit(2).Query()
if err != nil {
return ret, fmt.Errorf("error checking user existence: %w", err)
}
ret.HasAnyUser = len(res) != 0
ret.HasOnlyOneUser = len(res) == 1
return ret, nil
}

// CountUsers returns number of users.
func CountUsers(ctx context.Context, opts *CountUserFilter) int64 {
return countUsers(ctx, opts)
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ remember_me.compromised = The login token is not valid anymore which may indicat
forgot_password_title= Forgot Password
forgot_password = Forgot password?
need_account = Need an account?
sign_up_tip = You are registering the first account in the system, which has administrator privileges. Please carefully remember your username and password, as forgetting these credentials may require system reset and reinitialization.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as forgetting these credentials may require system reset and reinitialization.

That's not true, site admin can use gitea CLI to reset user password

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are registering the first account in the system. Please remember your username and password, as this account typically has administrative privileges. How about this? Is it okay?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo the wording is fine..? If the sysadmin and the first registered user are not the same person (e.g. as a SaaS platform without terminal access), the first registered user may not be able to access the gitea cli.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first registered user may not be able to access the gitea cli.

  • Why they can't contact their site admin with CLI access?
  • If the "first" user doesn't have CLI access, then how could they do "system reset and reinitialization" as the message says if they forget password?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. as a SaaS platform without terminal access

As a SaaS platform, isn't there a separate instance management console to help to reset the password? For example, gitea cloud?

Copy link
Member

@BLumia BLumia Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the "first" user doesn't have CLI access, then how could they do "system reset and reinitialization" as the message says if they forget password?

The first user who accessed the webpage to register account might not be the same person who does sysadmin. The person also might be able to reach out to a separated sysadmin person/team to do "system reset and reinitialization", by either via email or other method they have.

What I mean is since the copywriting is "may", so it's likely fine (or maybe we can also change it to "might"). We simply cannot assume the person who control site admin account is the same person who can access the server console to use gitea cli.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it needs more consideration. I think it could be another issue to not block this pull request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not block this pull request.

The message should be clear and should not confuse or frighten end users.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are registering the first account in the system, which has administrator privileges. Please carefully remember your username and password. How about this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about If you forget the username or password, please refer to the Gitea documentation ....

The two approaches could be clearly written in the docs:

  1. For a self-hosted instance, contact server admin to use cli or redeploy.
  2. For Gitea Cloud, use management console

sign_up_now = Register now.
sign_up_successful = Account was successfully created. Welcome!
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.
Expand Down
2 changes: 2 additions & 0 deletions routers/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,5 +607,7 @@ func SubmitInstall(ctx *context.Context) {
// InstallDone shows the "post-install" page, makes it easier to develop the page.
// The name is not called as "PostInstall" to avoid misinterpretation as a handler for "POST /install"
func InstallDone(ctx *context.Context) { //nolint
hasUsers, _ := user_model.HasUsers(ctx)
ctx.Data["IsAccountCreated"] = hasUsers.HasAnyUser
ctx.HTML(http.StatusOK, tplPostInstall)
}
12 changes: 10 additions & 2 deletions routers/web/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,11 @@ func SignOut(ctx *context.Context) {
// SignUp render the register page
func SignUp(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("sign_up")

ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"

hasUsers, _ := user_model.HasUsers(ctx)
ctx.Data["IsFirstTimeRegistration"] = !hasUsers.HasAnyUser

oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
ctx.ServerError("UserSignUp", err)
Expand Down Expand Up @@ -610,7 +612,13 @@ func createUserInContext(ctx *context.Context, tpl templates.TplName, form any,
// sends a confirmation email if required.
func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.User) (ok bool) {
// Auto-set admin for the only user.
if user_model.CountUsers(ctx, nil) == 1 {
hasUsers, err := user_model.HasUsers(ctx)
if err != nil {
ctx.ServerError("HasUsers", err)
return false
}
if hasUsers.HasOnlyOneUser {
// the only user is the one just created, will set it as admin
opts := &user_service.UpdateOptions{
IsActive: optional.Some(true),
IsAdmin: optional.Some(true),
Expand Down
2 changes: 1 addition & 1 deletion templates/post-install.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<!-- the "cup" has a handler, so move it a little leftward to make it visually in the center -->
<div class="tw-ml-[-30px]"><img width="160" src="{{AssetUrlPrefix}}/img/loading.png" alt aria-hidden="true"></div>
<div class="tw-my-[2em] tw-text-[18px]">
<a id="goto-user-login" href="{{AppSubUrl}}/user/login">{{ctx.Locale.Tr "install.installing_desc"}}</a>
<a id="goto-after-install" href="{{AppSubUrl}}{{Iif .IsAccountCreated "/user/login" "/user/sign_up"}}">{{ctx.Locale.Tr "install.installing_desc"}}</a>
</div>
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions templates/user/auth/signup_inner.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
{{end}}
</h4>
<div class="ui attached segment">
{{if .IsFirstTimeRegistration}}
<p>{{ctx.Locale.Tr "auth.sign_up_tip"}}</p>
{{end}}
<form class="ui form" action="{{.SignUpLink}}" method="post">
{{.CsrfTokenHtml}}
{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister)}}
Expand Down
2 changes: 1 addition & 1 deletion web_src/js/features/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function initPreInstall() {
}

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

const targetUrl = el.getAttribute('href');
Expand Down