2014-03-25 12:51:42 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2021-06-09 02:33:54 +03:00
// Copyright 2021 The Gitea Authors. All rights reserved.
2014-03-25 12:51:42 +04:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2021-06-09 02:33:54 +03:00
package install
2014-03-25 12:51:42 +04:00
2014-03-28 15:26:22 +04:00
import (
2020-12-25 12:59:32 +03:00
"fmt"
2020-10-20 00:03:08 +03:00
"net/http"
2014-03-30 01:50:51 +04:00
"os"
2014-04-08 23:27:35 +04:00
"os/exec"
2015-02-05 13:12:37 +03:00
"path/filepath"
2014-03-30 01:50:51 +04:00
"strings"
2021-01-26 18:36:53 +03:00
"time"
2014-03-30 01:50:51 +04:00
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-12-01 10:50:01 +03:00
db_install "code.gitea.io/gitea/models/db/install"
2021-10-29 11:23:10 +03:00
"code.gitea.io/gitea/models/migrations"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
2018-02-18 21:14:37 +03:00
"code.gitea.io/gitea/modules/generate"
2019-12-15 12:51:28 +03:00
"code.gitea.io/gitea/modules/graceful"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/templates"
2021-06-01 22:12:50 +03:00
"code.gitea.io/gitea/modules/translation"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/user"
2020-11-28 05:42:08 +03:00
"code.gitea.io/gitea/modules/util"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2021-01-30 11:55:53 +03:00
"code.gitea.io/gitea/modules/web/middleware"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2019-08-23 19:40:30 +03:00
2021-01-26 18:36:53 +03:00
"gitea.com/go-chi/session"
2019-08-23 19:40:30 +03:00
"gopkg.in/ini.v1"
2014-03-28 15:26:22 +04:00
)
2014-06-22 21:14:03 +04:00
const (
2016-11-18 06:03:03 +03:00
// tplInstall template for installation page
2020-10-20 00:03:08 +03:00
tplInstall base . TplName = "install"
tplPostInstall base . TplName = "post-install"
2014-06-22 21:14:03 +04:00
)
2021-12-07 08:44:08 +03:00
var supportedDbTypeNames [ ] map [ string ] string // use a slice to keep order
func getDbTypeNames ( ) [ ] map [ string ] string {
if supportedDbTypeNames == nil {
for _ , t := range setting . SupportedDatabaseTypes {
supportedDbTypeNames = append ( supportedDbTypeNames , map [ string ] string { "type" : t , "name" : setting . DatabaseTypeNames [ t ] } )
}
}
return supportedDbTypeNames
}
2021-06-09 02:33:54 +03:00
// Init prepare for rendering installation page
func Init ( next http . Handler ) http . Handler {
2021-01-26 18:36:53 +03:00
var rnd = templates . HTMLRenderer ( )
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 , 200 , string ( tplPostInstall ) , nil )
return
}
2021-01-30 11:55:53 +03:00
var locale = middleware . Locale ( resp , req )
2021-01-26 18:36:53 +03:00
var startTime = time . Now ( )
var ctx = context . Context {
Resp : context . NewResponse ( resp ) ,
2021-01-30 11:55:53 +03:00
Flash : & middleware . Flash { } ,
2021-01-26 18:36:53 +03:00
Locale : locale ,
Render : rnd ,
Session : session . GetSession ( req ) ,
Data : map [ string ] interface { } {
"Title" : locale . Tr ( "install.install" ) ,
"PageIsInstall" : true ,
2021-12-07 08:44:08 +03:00
"DbTypeNames" : getDbTypeNames ( ) ,
2021-01-26 18:36:53 +03:00
"i18n" : locale ,
"Language" : locale . Language ( ) ,
2021-06-01 22:12:50 +03:00
"Lang" : locale . Language ( ) ,
"AllLangs" : translation . AllLangs ( ) ,
2021-01-26 18:36:53 +03:00
"CurrentURL" : setting . AppSubURL + req . URL . RequestURI ( ) ,
"PageStartTime" : startTime ,
2021-12-15 09:59:57 +03:00
2021-11-24 12:49:20 +03:00
"PasswordHashAlgorithms" : user_model . AvailableHashAlgorithms ,
2021-01-26 18:36:53 +03:00
} ,
}
2021-06-01 22:12:50 +03:00
for _ , lang := range translation . AllLangs ( ) {
if lang . Lang == locale . Language ( ) {
ctx . Data [ "LangName" ] = lang . Name
break
}
}
2021-01-26 18:36:53 +03:00
ctx . Req = context . WithContext ( req , & ctx )
next . ServeHTTP ( resp , ctx . Req )
} )
2015-02-01 20:41:03 +03:00
}
2014-03-30 01:50:51 +04:00
2016-11-18 06:03:03 +03:00
// Install render installation page
2016-03-11 19:56:52 +03:00
func Install ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := forms . InstallForm { }
2015-02-01 20:41:03 +03:00
2015-07-09 08:17:48 +03:00
// Database settings
2019-08-24 12:24:45 +03:00
form . DbHost = setting . Database . Host
form . DbUser = setting . Database . User
form . DbPasswd = setting . Database . Passwd
form . DbName = setting . Database . Name
form . DbPath = setting . Database . Path
2020-01-20 18:45:14 +03:00
form . DbSchema = setting . Database . Schema
2019-08-24 12:24:45 +03:00
form . Charset = setting . Database . Charset
2015-02-01 20:41:03 +03:00
2021-12-07 08:44:08 +03:00
curDBType := setting . Database . Type
var isCurDBTypeSupported bool
for _ , dbType := range setting . SupportedDatabaseTypes {
if dbType == curDBType {
isCurDBTypeSupported = true
break
2015-09-12 22:31:36 +03:00
}
2015-07-09 08:17:48 +03:00
}
2021-12-07 08:44:08 +03:00
if ! isCurDBTypeSupported {
curDBType = "mysql"
}
ctx . Data [ "CurDbType" ] = curDBType
2020-11-16 10:33:41 +03:00
2015-07-09 08:17:48 +03:00
// Application general settings
form . AppName = setting . AppName
2015-02-01 20:41:03 +03:00
form . RepoRootPath = setting . RepoRootPath
2020-09-29 12:05:13 +03:00
form . LFSRootPath = setting . LFS . Path
2015-02-01 20:41:03 +03:00
2017-06-18 03:30:04 +03:00
// Note(unknown): it's hard for Windows users change a running user,
2015-02-01 20:41:03 +03:00
// so just use current one if config says default.
if setting . IsWindows && setting . RunUser == "git" {
2015-07-31 09:50:11 +03:00
form . RunUser = user . CurrentUsername ( )
2015-02-01 20:41:03 +03:00
} else {
form . RunUser = setting . RunUser
2014-04-10 22:37:43 +04:00
}
2014-03-30 01:50:51 +04:00
2015-02-01 20:41:03 +03:00
form . Domain = setting . Domain
2016-02-28 04:48:39 +03:00
form . SSHPort = setting . SSH . Port
2016-08-12 00:55:10 +03:00
form . HTTPPort = setting . HTTPPort
2016-11-27 09:03:59 +03:00
form . AppURL = setting . AppURL
2016-02-12 17:19:45 +03:00
form . LogRootPath = setting . LogRootPath
2015-02-01 20:41:03 +03:00
2015-07-09 08:17:48 +03:00
// E-mail service settings
if setting . MailService != nil {
form . SMTPHost = setting . MailService . Host
2015-07-09 11:10:31 +03:00
form . SMTPFrom = setting . MailService . From
2017-02-24 04:37:13 +03:00
form . SMTPUser = setting . MailService . User
2014-04-27 08:34:48 +04:00
}
2015-07-09 08:17:48 +03:00
form . RegisterConfirm = setting . Service . RegisterEmailConfirm
form . MailNotify = setting . Service . EnableNotifyMail
// Server and other services settings
form . OfflineMode = setting . OfflineMode
2015-08-29 19:22:26 +03:00
form . DisableGravatar = setting . DisableGravatar
2016-08-07 20:27:38 +03:00
form . EnableFederatedAvatar = setting . EnableFederatedAvatar
2017-11-29 15:47:42 +03:00
form . EnableOpenIDSignIn = setting . Service . EnableOpenIDSignIn
form . EnableOpenIDSignUp = setting . Service . EnableOpenIDSignUp
2015-07-09 08:17:48 +03:00
form . DisableRegistration = setting . Service . DisableRegistration
2018-05-13 10:51:16 +03:00
form . AllowOnlyExternalRegistration = setting . Service . AllowOnlyExternalRegistration
2015-09-13 19:14:32 +03:00
form . EnableCaptcha = setting . Service . EnableCaptcha
2015-07-09 08:17:48 +03:00
form . RequireSignInView = setting . Service . RequireSignInView
2017-01-08 06:12:03 +03:00
form . DefaultKeepEmailPrivate = setting . Service . DefaultKeepEmailPrivate
2017-05-08 22:51:53 +03:00
form . DefaultAllowCreateOrganization = setting . Service . DefaultAllowCreateOrganization
2017-09-12 09:48:13 +03:00
form . DefaultEnableTimetracking = setting . Service . DefaultEnableTimetracking
2017-01-08 06:12:03 +03:00
form . NoReplyAddress = setting . Service . NoReplyAddress
2021-02-17 01:37:20 +03:00
form . PasswordAlgorithm = setting . PasswordHashAlgo
2014-04-27 08:34:48 +04:00
2021-01-30 11:55:53 +03:00
middleware . AssignForm ( form , ctx . Data )
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplInstall )
2014-04-10 22:37:43 +04:00
}
2021-12-01 10:50:01 +03:00
func checkDatabase ( ctx * context . Context , form * forms . InstallForm ) bool {
var err error
if ( setting . Database . Type == "sqlite3" ) &&
len ( setting . Database . Path ) == 0 {
ctx . Data [ "Err_DbPath" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.err_empty_db_path" ) , tplInstall , form )
return false
}
// Check if the user is trying to re-install in an installed database
db . UnsetDefaultEngine ( )
defer db . UnsetDefaultEngine ( )
if err = db . InitEngine ( ctx ) ; err != nil {
if strings . Contains ( err . Error ( ) , ` Unknown database type: sqlite3 ` ) {
ctx . Data [ "Err_DbType" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.sqlite3_not_available" , "https://docs.gitea.io/en-us/install-from-binary/" ) , tplInstall , form )
} else {
ctx . Data [ "Err_DbSetting" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_setting" , err ) , tplInstall , form )
}
return false
}
err = db_install . CheckDatabaseConnection ( )
if err != nil {
ctx . Data [ "Err_DbSetting" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_setting" , err ) , tplInstall , form )
return false
}
hasPostInstallationUser , err := db_install . HasPostInstallationUsers ( )
if err != nil {
ctx . Data [ "Err_DbSetting" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_table" , "user" , err ) , tplInstall , form )
return false
}
dbMigrationVersion , err := db_install . GetMigrationVersion ( )
if err != nil {
ctx . Data [ "Err_DbSetting" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_table" , "version" , err ) , tplInstall , form )
return false
}
if hasPostInstallationUser && dbMigrationVersion > 0 {
log . Error ( "The database is likely to have been used by Gitea before, database migration version=%d" , dbMigrationVersion )
confirmed := form . ReinstallConfirmFirst && form . ReinstallConfirmSecond && form . ReinstallConfirmThird
if ! confirmed {
ctx . Data [ "Err_DbInstalledBefore" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.reinstall_error" ) , tplInstall , form )
return false
}
log . Info ( "User confirmed reinstallation of Gitea into a pre-existing database" )
}
if hasPostInstallationUser || dbMigrationVersion > 0 {
log . Info ( "Gitea will be installed in a database with: hasPostInstallationUser=%v, dbMigrationVersion=%v" , hasPostInstallationUser , dbMigrationVersion )
}
return true
}
2021-06-09 02:33:54 +03:00
// SubmitInstall response for submit install items
func SubmitInstall ( ctx * context . Context ) {
2016-12-20 15:32:02 +03:00
var err error
2021-12-01 10:50:01 +03:00
form := * web . GetForm ( ctx ) . ( * forms . InstallForm )
// fix form values
if form . AppURL != "" && form . AppURL [ len ( form . AppURL ) - 1 ] != '/' {
form . AppURL += "/"
}
2021-12-07 08:44:08 +03:00
ctx . Data [ "CurDbType" ] = form . DbType
2014-04-27 08:34:48 +04:00
2014-03-30 01:50:51 +04:00
if ctx . HasError ( ) {
2017-02-24 04:37:13 +03:00
if ctx . HasValue ( "Err_SMTPUser" ) {
2015-07-08 14:47:56 +03:00
ctx . Data [ "Err_SMTP" ] = true
}
if ctx . HasValue ( "Err_AdminName" ) ||
ctx . HasValue ( "Err_AdminPasswd" ) ||
ctx . HasValue ( "Err_AdminEmail" ) {
ctx . Data [ "Err_Admin" ] = true
}
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplInstall )
2014-03-30 01:50:51 +04:00
return
}
2016-12-20 15:32:02 +03:00
if _ , err = exec . LookPath ( "git" ) ; err != nil {
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.test_git_failed" , err ) , tplInstall , & form )
2014-04-08 23:27:35 +04:00
return
}
2021-12-01 10:50:01 +03:00
// ---- Basic checks are passed, now test configuration.
2019-08-24 12:24:45 +03:00
2021-12-01 10:50:01 +03:00
// Test database setting.
2021-12-07 08:44:08 +03:00
setting . Database . Type = form . DbType
2019-08-24 12:24:45 +03:00
setting . Database . Host = form . DbHost
setting . Database . User = form . DbUser
setting . Database . Passwd = form . DbPasswd
setting . Database . Name = form . DbName
2020-01-20 18:45:14 +03:00
setting . Database . Schema = form . DbSchema
2019-08-24 12:24:45 +03:00
setting . Database . SSLMode = form . SSLMode
setting . Database . Charset = form . Charset
setting . Database . Path = form . DbPath
2021-11-07 06:11:27 +03:00
setting . Database . LogSQL = ! setting . IsProd
2021-02-17 01:37:20 +03:00
setting . PasswordHashAlgo = form . PasswordAlgorithm
2021-12-01 10:50:01 +03:00
if ! checkDatabase ( ctx , & form ) {
2015-09-12 22:31:36 +03:00
return
2015-07-08 14:47:56 +03:00
}
2021-12-01 10:50:01 +03:00
// Prepare AppDataPath, it is very important for Gitea
if err = setting . PrepareAppDataPath ( ) ; err != nil {
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_app_data_path" , err ) , tplInstall , & form )
2014-03-30 01:50:51 +04:00
return
}
// Test repository root path.
2020-10-11 23:27:20 +03:00
form . RepoRootPath = strings . ReplaceAll ( form . RepoRootPath , "\\" , "/" )
2016-12-20 15:32:02 +03:00
if err = os . MkdirAll ( form . RepoRootPath , os . ModePerm ) ; err != nil {
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_RepoRootPath" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_repo_path" , err ) , tplInstall , & form )
2014-03-30 01:50:51 +04:00
return
}
2016-12-26 04:16:37 +03:00
// Test LFS root path if not empty, empty meaning disable LFS
if form . LFSRootPath != "" {
2020-10-11 23:27:20 +03:00
form . LFSRootPath = strings . ReplaceAll ( form . LFSRootPath , "\\" , "/" )
2016-12-26 04:16:37 +03:00
if err := os . MkdirAll ( form . LFSRootPath , os . ModePerm ) ; err != nil {
ctx . Data [ "Err_LFSRootPath" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_lfs_path" , err ) , tplInstall , & form )
return
}
}
2016-02-12 17:19:45 +03:00
// Test log root path.
2020-10-11 23:27:20 +03:00
form . LogRootPath = strings . ReplaceAll ( form . LogRootPath , "\\" , "/" )
2016-12-20 15:32:02 +03:00
if err = os . MkdirAll ( form . LogRootPath , os . ModePerm ) ; err != nil {
2016-02-12 17:19:45 +03:00
ctx . Data [ "Err_LogRootPath" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_log_root_path" , err ) , tplInstall , & form )
2016-02-12 17:19:45 +03:00
return
}
2016-08-10 03:41:18 +03:00
currentUser , match := setting . IsRunUserMatchCurrentUser ( form . RunUser )
if ! match {
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_RunUser" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.run_user_not_match" , form . RunUser , currentUser ) , tplInstall , & form )
2014-09-08 03:02:58 +04:00
return
}
2015-09-12 22:31:36 +03:00
// Check logic loophole between disable self-registration and no admin account.
if form . DisableRegistration && len ( form . AdminName ) == 0 {
ctx . Data [ "Err_Services" ] = true
ctx . Data [ "Err_Admin" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.no_admin_and_disable_registration" ) , tplInstall , form )
2015-09-12 22:31:36 +03:00
return
}
2019-05-28 09:18:40 +03:00
// Check admin user creation
if len ( form . AdminName ) > 0 {
// Ensure AdminName is valid
2021-11-24 12:49:20 +03:00
if err := user_model . IsUsableUsername ( form . AdminName ) ; err != nil {
2019-05-28 09:18:40 +03:00
ctx . Data [ "Err_Admin" ] = true
ctx . Data [ "Err_AdminName" ] = true
2021-11-24 12:49:20 +03:00
if db . IsErrNameReserved ( err ) {
2019-05-28 09:18:40 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.err_admin_name_is_reserved" ) , tplInstall , form )
return
2021-11-24 12:49:20 +03:00
} else if db . IsErrNamePatternNotAllowed ( err ) {
2019-05-28 09:18:40 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.err_admin_name_pattern_not_allowed" ) , tplInstall , form )
return
}
ctx . RenderWithErr ( ctx . Tr ( "install.err_admin_name_is_invalid" ) , tplInstall , form )
return
}
// Check Admin email
if len ( form . AdminEmail ) == 0 {
ctx . Data [ "Err_Admin" ] = true
ctx . Data [ "Err_AdminEmail" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.err_empty_admin_email" ) , tplInstall , form )
return
}
// Check admin password.
if len ( form . AdminPasswd ) == 0 {
ctx . Data [ "Err_Admin" ] = true
ctx . Data [ "Err_AdminPasswd" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.err_empty_admin_password" ) , tplInstall , form )
return
}
if form . AdminPasswd != form . AdminConfirmPasswd {
ctx . Data [ "Err_Admin" ] = true
ctx . Data [ "Err_AdminPasswd" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.password_not_match" ) , tplInstall , form )
return
}
2014-03-30 19:58:21 +04:00
}
2021-12-01 10:50:01 +03:00
// Init the engine with migration
if err = db . InitEngineWithMigration ( ctx , migrations . Migrate ) ; err != nil {
db . UnsetDefaultEngine ( )
ctx . Data [ "Err_DbSetting" ] = true
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_setting" , err ) , tplInstall , & form )
return
2015-02-01 20:41:03 +03:00
}
2021-12-01 10:50:01 +03:00
db . UnsetDefaultEngine ( )
2015-02-01 20:41:03 +03:00
2014-03-30 01:50:51 +04:00
// Save settings.
2015-02-01 22:39:58 +03:00
cfg := ini . Empty ( )
2020-11-28 05:42:08 +03:00
isFile , err := util . IsFile ( setting . CustomConf )
if err != nil {
log . Error ( "Unable to check if %s is a file. Error: %v" , setting . CustomConf , err )
}
if isFile {
2015-02-14 00:48:23 +03:00
// Keeps custom settings if there is already something.
2016-12-20 15:32:02 +03:00
if err = cfg . Append ( setting . CustomConf ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Failed to load custom conf '%s': %v" , setting . CustomConf , err )
2015-02-14 00:48:23 +03:00
}
}
2019-08-24 12:24:45 +03:00
cfg . Section ( "database" ) . Key ( "DB_TYPE" ) . SetValue ( setting . Database . Type )
cfg . Section ( "database" ) . Key ( "HOST" ) . SetValue ( setting . Database . Host )
cfg . Section ( "database" ) . Key ( "NAME" ) . SetValue ( setting . Database . Name )
cfg . Section ( "database" ) . Key ( "USER" ) . SetValue ( setting . Database . User )
cfg . Section ( "database" ) . Key ( "PASSWD" ) . SetValue ( setting . Database . Passwd )
2020-01-20 18:45:14 +03:00
cfg . Section ( "database" ) . Key ( "SCHEMA" ) . SetValue ( setting . Database . Schema )
2019-08-24 12:24:45 +03:00
cfg . Section ( "database" ) . Key ( "SSL_MODE" ) . SetValue ( setting . Database . SSLMode )
cfg . Section ( "database" ) . Key ( "CHARSET" ) . SetValue ( setting . Database . Charset )
cfg . Section ( "database" ) . Key ( "PATH" ) . SetValue ( setting . Database . Path )
2020-10-10 18:19:50 +03:00
cfg . Section ( "database" ) . Key ( "LOG_SQL" ) . SetValue ( "false" ) // LOG_SQL is rarely helpful
2015-02-01 22:39:58 +03:00
2015-07-09 08:17:48 +03:00
cfg . Section ( "" ) . Key ( "APP_NAME" ) . SetValue ( form . AppName )
2015-02-01 22:39:58 +03:00
cfg . Section ( "repository" ) . Key ( "ROOT" ) . SetValue ( form . RepoRootPath )
cfg . Section ( "" ) . Key ( "RUN_USER" ) . SetValue ( form . RunUser )
2016-12-27 10:34:34 +03:00
cfg . Section ( "server" ) . Key ( "SSH_DOMAIN" ) . SetValue ( form . Domain )
2017-04-21 05:43:29 +03:00
cfg . Section ( "server" ) . Key ( "DOMAIN" ) . SetValue ( form . Domain )
2015-02-01 22:39:58 +03:00
cfg . Section ( "server" ) . Key ( "HTTP_PORT" ) . SetValue ( form . HTTPPort )
2016-11-27 09:03:59 +03:00
cfg . Section ( "server" ) . Key ( "ROOT_URL" ) . SetValue ( form . AppURL )
2014-03-30 01:50:51 +04:00
2015-08-19 15:36:19 +03:00
if form . SSHPort == 0 {
cfg . Section ( "server" ) . Key ( "DISABLE_SSH" ) . SetValue ( "true" )
} else {
cfg . Section ( "server" ) . Key ( "DISABLE_SSH" ) . SetValue ( "false" )
2020-12-25 12:59:32 +03:00
cfg . Section ( "server" ) . Key ( "SSH_PORT" ) . SetValue ( fmt . Sprint ( form . SSHPort ) )
2015-08-19 15:36:19 +03:00
}
2016-12-26 04:16:37 +03:00
if form . LFSRootPath != "" {
cfg . Section ( "server" ) . Key ( "LFS_START_SERVER" ) . SetValue ( "true" )
cfg . Section ( "server" ) . Key ( "LFS_CONTENT_PATH" ) . SetValue ( form . LFSRootPath )
2021-12-01 10:50:01 +03:00
var lfsJwtSecret string
if lfsJwtSecret , err = generate . NewJwtSecretBase64 ( ) ; err != nil {
2018-02-18 21:14:37 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.lfs_jwt_secret_failed" , err ) , tplInstall , & form )
return
}
2021-12-01 10:50:01 +03:00
cfg . Section ( "server" ) . Key ( "LFS_JWT_SECRET" ) . SetValue ( lfsJwtSecret )
2016-12-26 04:16:37 +03:00
} else {
cfg . Section ( "server" ) . Key ( "LFS_START_SERVER" ) . SetValue ( "false" )
}
2015-02-01 20:41:03 +03:00
if len ( strings . TrimSpace ( form . SMTPHost ) ) > 0 {
2015-02-01 22:39:58 +03:00
cfg . Section ( "mailer" ) . Key ( "ENABLED" ) . SetValue ( "true" )
cfg . Section ( "mailer" ) . Key ( "HOST" ) . SetValue ( form . SMTPHost )
2015-07-09 11:10:31 +03:00
cfg . Section ( "mailer" ) . Key ( "FROM" ) . SetValue ( form . SMTPFrom )
2017-02-24 04:37:13 +03:00
cfg . Section ( "mailer" ) . Key ( "USER" ) . SetValue ( form . SMTPUser )
2015-02-01 22:39:58 +03:00
cfg . Section ( "mailer" ) . Key ( "PASSWD" ) . SetValue ( form . SMTPPasswd )
2015-07-09 08:17:48 +03:00
} else {
cfg . Section ( "mailer" ) . Key ( "ENABLED" ) . SetValue ( "false" )
2014-03-30 01:50:51 +04:00
}
2020-12-25 12:59:32 +03:00
cfg . Section ( "service" ) . Key ( "REGISTER_EMAIL_CONFIRM" ) . SetValue ( fmt . Sprint ( form . RegisterConfirm ) )
cfg . Section ( "service" ) . Key ( "ENABLE_NOTIFY_MAIL" ) . SetValue ( fmt . Sprint ( form . MailNotify ) )
cfg . Section ( "server" ) . Key ( "OFFLINE_MODE" ) . SetValue ( fmt . Sprint ( form . OfflineMode ) )
cfg . Section ( "picture" ) . Key ( "DISABLE_GRAVATAR" ) . SetValue ( fmt . Sprint ( form . DisableGravatar ) )
cfg . Section ( "picture" ) . Key ( "ENABLE_FEDERATED_AVATAR" ) . SetValue ( fmt . Sprint ( form . EnableFederatedAvatar ) )
cfg . Section ( "openid" ) . Key ( "ENABLE_OPENID_SIGNIN" ) . SetValue ( fmt . Sprint ( form . EnableOpenIDSignIn ) )
cfg . Section ( "openid" ) . Key ( "ENABLE_OPENID_SIGNUP" ) . SetValue ( fmt . Sprint ( form . EnableOpenIDSignUp ) )
cfg . Section ( "service" ) . Key ( "DISABLE_REGISTRATION" ) . SetValue ( fmt . Sprint ( form . DisableRegistration ) )
cfg . Section ( "service" ) . Key ( "ALLOW_ONLY_EXTERNAL_REGISTRATION" ) . SetValue ( fmt . Sprint ( form . AllowOnlyExternalRegistration ) )
cfg . Section ( "service" ) . Key ( "ENABLE_CAPTCHA" ) . SetValue ( fmt . Sprint ( form . EnableCaptcha ) )
cfg . Section ( "service" ) . Key ( "REQUIRE_SIGNIN_VIEW" ) . SetValue ( fmt . Sprint ( form . RequireSignInView ) )
cfg . Section ( "service" ) . Key ( "DEFAULT_KEEP_EMAIL_PRIVATE" ) . SetValue ( fmt . Sprint ( form . DefaultKeepEmailPrivate ) )
cfg . Section ( "service" ) . Key ( "DEFAULT_ALLOW_CREATE_ORGANIZATION" ) . SetValue ( fmt . Sprint ( form . DefaultAllowCreateOrganization ) )
cfg . Section ( "service" ) . Key ( "DEFAULT_ENABLE_TIMETRACKING" ) . SetValue ( fmt . Sprint ( form . DefaultEnableTimetracking ) )
cfg . Section ( "service" ) . Key ( "NO_REPLY_ADDRESS" ) . SetValue ( fmt . Sprint ( form . NoReplyAddress ) )
2014-03-30 01:50:51 +04:00
2015-02-01 22:39:58 +03:00
cfg . Section ( "" ) . Key ( "RUN_MODE" ) . SetValue ( "prod" )
2014-03-30 19:58:21 +04:00
2015-02-01 22:39:58 +03:00
cfg . Section ( "session" ) . Key ( "PROVIDER" ) . SetValue ( "file" )
2014-12-21 06:51:16 +03:00
2020-10-10 18:19:50 +03:00
cfg . Section ( "log" ) . Key ( "MODE" ) . SetValue ( "console" )
2021-03-28 22:08:19 +03:00
cfg . Section ( "log" ) . Key ( "LEVEL" ) . SetValue ( setting . LogLevel . String ( ) )
2016-02-12 17:19:45 +03:00
cfg . Section ( "log" ) . Key ( "ROOT_PATH" ) . SetValue ( form . LogRootPath )
2020-10-10 18:19:50 +03:00
cfg . Section ( "log" ) . Key ( "ROUTER" ) . SetValue ( "console" )
2014-08-27 12:39:36 +04:00
2022-01-20 05:41:59 +03:00
cfg . Section ( "repository.signing" ) . Key ( "DEFAULT_TRUST_MODEL" ) . SetValue ( "committer" )
2015-02-01 22:39:58 +03:00
cfg . Section ( "security" ) . Key ( "INSTALL_LOCK" ) . SetValue ( "true" )
2021-12-01 10:50:01 +03:00
var internalToken string
if internalToken , err = generate . NewInternalToken ( ) ; err != nil {
ctx . RenderWithErr ( ctx . Tr ( "install.internal_token_failed" , err ) , tplInstall , & form )
2016-12-20 15:32:02 +03:00
return
}
2021-12-01 10:50:01 +03:00
cfg . Section ( "security" ) . Key ( "INTERNAL_TOKEN" ) . SetValue ( internalToken )
// if there is already a SECRET_KEY, we should not overwrite it, otherwise the encrypted data will not be able to be decrypted
if setting . SecretKey == "" {
var secretKey string
if secretKey , err = generate . NewSecretKey ( ) ; err != nil {
ctx . RenderWithErr ( ctx . Tr ( "install.secret_key_failed" , err ) , tplInstall , & form )
return
}
cfg . Section ( "security" ) . Key ( "SECRET_KEY" ) . SetValue ( secretKey )
}
2021-02-17 01:37:20 +03:00
if len ( form . PasswordAlgorithm ) > 0 {
cfg . Section ( "security" ) . Key ( "PASSWORD_HASH_ALGO" ) . SetValue ( form . PasswordAlgorithm )
}
2014-03-30 01:50:51 +04:00
2021-12-01 10:50:01 +03:00
log . Info ( "Save settings to custom config file %s" , setting . CustomConf )
2016-12-20 15:32:02 +03:00
err = os . MkdirAll ( filepath . Dir ( setting . CustomConf ) , os . ModePerm )
2016-11-10 13:02:01 +03:00
if err != nil {
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , tplInstall , & form )
2016-11-10 13:02:01 +03:00
return
}
2016-12-20 15:32:02 +03:00
if err = cfg . SaveTo ( setting . CustomConf ) ; err != nil {
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , tplInstall , & form )
2014-03-30 01:50:51 +04:00
return
}
2021-12-01 10:50:01 +03:00
// ---- All checks are passed
// Reload settings (and re-initialize database connection)
reloadSettings ( ctx )
2014-03-30 01:50:51 +04:00
2015-12-08 08:59:14 +03:00
// Create admin account
2015-07-08 14:47:56 +03:00
if len ( form . AdminName ) > 0 {
2021-11-24 12:49:20 +03:00
u := & user_model . User {
2015-07-08 14:47:56 +03:00
Name : form . AdminName ,
Email : form . AdminEmail ,
Passwd : form . AdminPasswd ,
IsAdmin : true ,
IsActive : true ,
2015-12-08 08:59:14 +03:00
}
2021-11-24 12:49:20 +03:00
if err = user_model . CreateUser ( u ) ; err != nil {
if ! user_model . IsErrUserAlreadyExist ( err ) {
2015-07-08 14:47:56 +03:00
setting . InstallLock = false
ctx . Data [ "Err_AdminName" ] = true
ctx . Data [ "Err_AdminEmail" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_admin_setting" , err ) , tplInstall , & form )
2015-07-08 14:47:56 +03:00
return
}
log . Info ( "Admin account already exist" )
2021-11-24 12:49:20 +03:00
u , _ = user_model . GetUserByName ( u . Name )
2014-03-30 19:09:59 +04:00
}
2015-12-08 08:59:14 +03:00
2020-10-20 00:03:08 +03:00
days := 86400 * setting . LogInRememberDays
2021-03-07 11:12:43 +03:00
ctx . SetCookie ( setting . CookieUserName , u . Name , days )
2020-10-20 00:03:08 +03:00
ctx . SetSuperSecureCookie ( base . EncodeMD5 ( u . Rands + u . Passwd ) ,
2021-03-07 11:12:43 +03:00
setting . CookieRememberName , u . Name , days )
2020-10-20 00:03:08 +03:00
2015-12-08 08:59:14 +03:00
// Auto-login for admin
2016-12-20 15:32:02 +03:00
if err = ctx . Session . Set ( "uid" , u . ID ) ; err != nil {
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , tplInstall , & form )
2016-11-10 13:02:01 +03:00
return
}
2016-12-20 15:32:02 +03:00
if err = ctx . Session . Set ( "uname" , u . Name ) ; err != nil {
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , tplInstall , & form )
2016-11-10 13:02:01 +03:00
return
}
2020-05-17 15:43:29 +03:00
if err = ctx . Session . Release ( ) ; err != nil {
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , tplInstall , & form )
return
}
2014-03-30 19:09:59 +04:00
}
2014-03-30 01:50:51 +04:00
log . Info ( "First-time run install finished!" )
2020-10-20 00:03:08 +03:00
2014-09-08 03:02:58 +04:00
ctx . Flash . Success ( ctx . Tr ( "install.install_success" ) )
2020-10-20 00:03:08 +03:00
2021-12-15 09:59:57 +03:00
ctx . RespHeader ( ) . Add ( "Refresh" , "1; url=" + setting . AppURL + "user/login" )
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplPostInstall )
2020-10-20 00:03:08 +03:00
// 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
2021-05-31 09:18:11 +03:00
srv := ctx . Value ( http . ServerContextKey ) . ( * http . Server )
2020-10-20 00:03:08 +03:00
go func ( ) {
if err := srv . Shutdown ( graceful . GetManager ( ) . HammerContext ( ) ) ; err != nil {
log . Error ( "Unable to shutdown the install server! Error: %v" , err )
}
} ( )
2014-03-25 12:51:42 +04:00
}