aboutsummaryrefslogtreecommitdiffstats
path: root/routers/install
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-03-04 10:12:02 +0800
committerGitHub <noreply@github.com>2023-03-04 10:12:02 +0800
commitb2359f3df6673c1b2d04f0112be62990c139aba0 (patch)
tree05928f69132db314a2b43acf6900bd2584b9bc04 /routers/install
parent5c4075e16dd7afc75557b178239b8172e286d5c3 (diff)
downloadgitea-b2359f3df6673c1b2d04f0112be62990c139aba0.tar.gz
gitea-b2359f3df6673c1b2d04f0112be62990c139aba0.zip
Fix various bugs for "install" page (#23194)
## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Diffstat (limited to 'routers/install')
-rw-r--r--routers/install/install.go48
-rw-r--r--routers/install/routes.go13
2 files changed, 43 insertions, 18 deletions
diff --git a/routers/install/install.go b/routers/install/install.go
index a3d64e5f73..a377c2950b 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -59,11 +59,6 @@ func Init(ctx goctx.Context) func(next http.Handler) http.Handler {
dbTypeNames := getSupportedDbTypeNames()
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- if setting.InstallLock {
- resp.Header().Add("Refresh", "1; url="+setting.AppURL+"user/login")
- _ = rnd.HTML(resp, http.StatusOK, string(tplPostInstall), nil)
- return
- }
locale := middleware.Locale(resp, req)
startTime := time.Now()
ctx := context.Context{
@@ -93,6 +88,11 @@ func Init(ctx goctx.Context) func(next http.Handler) http.Handler {
// Install render installation page
func Install(ctx *context.Context) {
+ if setting.InstallLock {
+ InstallDone(ctx)
+ return
+ }
+
form := forms.InstallForm{}
// Database settings
@@ -162,7 +162,7 @@ func Install(ctx *context.Context) {
form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
form.NoReplyAddress = setting.Service.NoReplyAddress
- form.PasswordAlgorithm = setting.PasswordHashAlgo
+ form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo)
middleware.AssignForm(form, ctx.Data)
ctx.HTML(http.StatusOK, tplInstall)
@@ -234,6 +234,11 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool {
// SubmitInstall response for submit install items
func SubmitInstall(ctx *context.Context) {
+ if setting.InstallLock {
+ InstallDone(ctx)
+ return
+ }
+
var err error
form := *web.GetForm(ctx).(*forms.InstallForm)
@@ -277,7 +282,6 @@ func SubmitInstall(ctx *context.Context) {
setting.Database.Charset = form.Charset
setting.Database.Path = form.DbPath
setting.Database.LogSQL = !setting.IsProd
- setting.PasswordHashAlgo = form.PasswordAlgorithm
if !checkDatabase(ctx, &form) {
return
@@ -499,6 +503,12 @@ func SubmitInstall(ctx *context.Context) {
}
if len(form.PasswordAlgorithm) > 0 {
+ var algorithm *hash.PasswordHashAlgorithm
+ setting.PasswordHashAlgo, algorithm = hash.SetDefaultPasswordHashAlgorithm(form.PasswordAlgorithm)
+ if algorithm == nil {
+ ctx.RenderWithErr(ctx.Tr("install.invalid_password_algorithm"), tplInstall, &form)
+ return
+ }
cfg.Section("security").Key("PASSWORD_HASH_ALGO").SetValue(form.PasswordAlgorithm)
}
@@ -571,18 +581,26 @@ func SubmitInstall(ctx *context.Context) {
}
log.Info("First-time run install finished!")
+ InstallDone(ctx)
- ctx.Flash.Success(ctx.Tr("install.install_success"))
-
- ctx.RespHeader().Add("Refresh", "1; url="+setting.AppURL+"user/login")
- ctx.HTML(http.StatusOK, tplPostInstall)
-
- // Now get the http.Server from this request and shut it down
- // NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
- srv := ctx.Value(http.ServerContextKey).(*http.Server)
go func() {
+ // Sleep for a while to make sure the user's browser has loaded the post-install page and its assets (images, css, js)
+ // What if this duration is not long enough? That's impossible -- if the user can't load the simple page in time, how could they install or use Gitea in the future ....
+ time.Sleep(3 * time.Second)
+
+ // Now get the http.Server from this request and shut it down
+ // NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
+ srv := ctx.Value(http.ServerContextKey).(*http.Server)
if err := srv.Shutdown(graceful.GetManager().HammerContext()); err != nil {
log.Error("Unable to shutdown the install server! Error: %v", err)
}
+
+ // After the HTTP server for "install" shuts down, the `runWeb()` will continue to run the "normal" server
}()
}
+
+// 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
+ ctx.HTML(http.StatusOK, tplPostInstall)
+}
diff --git a/routers/install/routes.go b/routers/install/routes.go
index 9aa5a88d24..a8efc92fe1 100644
--- a/routers/install/routes.go
+++ b/routers/install/routes.go
@@ -6,6 +6,7 @@ package install
import (
goctx "context"
"fmt"
+ "html"
"net/http"
"path"
@@ -37,7 +38,7 @@ func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler {
// Why we need this? The first recover will try to render a beautiful
// error page for user, but the process can still panic again, then
// we have to just recover twice and send a simple error page that
- // should not panic any more.
+ // should not panic anymore.
defer func() {
if err := recover(); err != nil {
combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, log.Stack(2))
@@ -107,8 +108,9 @@ func Routes(ctx goctx.Context) *web.Route {
r.Use(installRecovery(ctx))
r.Use(Init(ctx))
- r.Get("/", Install)
+ r.Get("/", Install) // it must be on the root, because the "install.js" use the window.location to replace the "localhost" AppURL
r.Post("/", web.Bind(forms.InstallForm{}), SubmitInstall)
+ r.Get("/post-install", InstallDone)
r.Get("/api/healthz", healthcheck.Check)
r.NotFound(web.Wrap(installNotFound))
@@ -116,5 +118,10 @@ func Routes(ctx goctx.Context) *web.Route {
}
func installNotFound(w http.ResponseWriter, req *http.Request) {
- http.Redirect(w, req, setting.AppURL, http.StatusFound)
+ w.Header().Add("Content-Type", "text/html; charset=utf-8")
+ w.Header().Add("Refresh", fmt.Sprintf("1; url=%s", setting.AppSubURL+"/"))
+ // do not use 30x status, because the "post-install" page needs to use 404/200 to detect if Gitea has been installed.
+ // the fetch API could follow 30x requests to the page with 200 status.
+ w.WriteHeader(http.StatusNotFound)
+ _, _ = fmt.Fprintf(w, `Not Found. <a href="%s">Go to default page</a>.`, html.EscapeString(setting.AppSubURL+"/"))
}