2014-03-25 12:51:42 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package routers
2014-03-28 15:26:22 +04:00
import (
"errors"
2014-03-30 01:50:51 +04:00
"os"
2014-04-08 23:27:35 +04:00
"os/exec"
2014-05-26 04:11:25 +04:00
"path"
2015-02-05 13:12:37 +03:00
"path/filepath"
2014-03-30 01:50:51 +04:00
"strings"
2014-07-26 08:24:27 +04:00
"github.com/Unknwon/com"
2014-04-18 17:35:09 +04:00
"github.com/go-xorm/xorm"
2015-02-01 22:39:58 +03:00
"gopkg.in/ini.v1"
2015-11-27 01:33:45 +03:00
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/user"
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
tplInstall base . TplName = "install"
2014-06-22 21:14:03 +04:00
)
2016-11-18 06:03:03 +03:00
// InstallInit prepare for rendering installation page
2016-03-11 19:56:52 +03:00
func InstallInit ( ctx * context . Context ) {
2014-05-26 04:11:25 +04:00
if setting . InstallLock {
2014-09-08 03:02:58 +04:00
ctx . Handle ( 404 , "Install" , errors . New ( "Installation is prohibited" ) )
2014-03-28 15:26:22 +04:00
return
}
2014-03-25 12:51:42 +04:00
2014-09-08 03:02:58 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "install.install" )
2014-03-28 15:26:22 +04:00
ctx . Data [ "PageIsInstall" ] = true
2015-09-06 23:31:22 +03:00
dbOpts := [ ] string { "MySQL" , "PostgreSQL" }
if models . EnableSQLite3 {
dbOpts = append ( dbOpts , "SQLite3" )
}
2016-08-12 00:38:45 +03:00
if models . EnableTiDB {
2015-09-06 23:31:22 +03:00
dbOpts = append ( dbOpts , "TiDB" )
}
ctx . Data [ "DbOptions" ] = dbOpts
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 ) {
2015-02-01 20:41:03 +03:00
form := auth . InstallForm { }
2015-07-09 08:17:48 +03:00
// Database settings
2015-02-01 20:41:03 +03:00
form . DbHost = models . DbCfg . Host
form . DbUser = models . DbCfg . User
form . DbName = models . DbCfg . Name
form . DbPath = models . DbCfg . Path
2015-09-12 04:00:12 +03:00
ctx . Data [ "CurDbOption" ] = "MySQL"
switch models . DbCfg . Type {
case "postgres" :
ctx . Data [ "CurDbOption" ] = "PostgreSQL"
case "sqlite3" :
if models . EnableSQLite3 {
2015-09-12 22:31:36 +03:00
ctx . Data [ "CurDbOption" ] = "SQLite3"
}
case "tidb" :
2016-08-12 00:38:45 +03:00
if models . EnableTiDB {
2015-09-12 22:31:36 +03:00
ctx . Data [ "CurDbOption" ] = "TiDB"
2015-09-12 04:00:12 +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
// Note(unknwon): it's hard for Windows users change a running user,
// 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
2015-07-09 08:17:48 +03:00
form . SMTPEmail = 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
2015-07-09 08:17:48 +03:00
form . DisableRegistration = setting . Service . DisableRegistration
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
2014-04-27 08:34:48 +04:00
2014-04-10 22:37:43 +04:00
auth . AssignForm ( form , ctx . Data )
2016-11-18 06:03:03 +03:00
ctx . HTML ( 200 , tplInstall )
2014-04-10 22:37:43 +04:00
}
2016-11-18 06:03:03 +03:00
// InstallPost response for submit install items
2016-03-11 19:56:52 +03:00
func InstallPost ( ctx * context . Context , form auth . InstallForm ) {
2015-02-01 20:41:03 +03:00
ctx . Data [ "CurDbOption" ] = form . DbType
2014-04-27 08:34:48 +04:00
2014-03-30 01:50:51 +04:00
if ctx . HasError ( ) {
2015-07-08 14:47:56 +03:00
if ctx . HasValue ( "Err_SMTPEmail" ) {
ctx . Data [ "Err_SMTP" ] = true
}
if ctx . HasValue ( "Err_AdminName" ) ||
ctx . HasValue ( "Err_AdminPasswd" ) ||
ctx . HasValue ( "Err_AdminEmail" ) {
ctx . Data [ "Err_Admin" ] = true
}
2016-11-18 06:03:03 +03:00
ctx . HTML ( 200 , tplInstall )
2014-03-30 01:50:51 +04:00
return
}
2014-04-08 23:27:35 +04: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
}
2014-03-30 01:50:51 +04:00
// Pass basic check, now test configuration.
// Test database setting.
2015-09-06 23:31:22 +03:00
dbTypes := map [ string ] string { "MySQL" : "mysql" , "PostgreSQL" : "postgres" , "SQLite3" : "sqlite3" , "TiDB" : "tidb" }
2015-02-01 20:41:03 +03:00
models . DbCfg . Type = dbTypes [ form . DbType ]
2014-09-08 03:02:58 +04:00
models . DbCfg . Host = form . DbHost
models . DbCfg . User = form . DbUser
2015-02-01 20:41:03 +03:00
models . DbCfg . Passwd = form . DbPasswd
models . DbCfg . Name = form . DbName
models . DbCfg . SSLMode = form . SSLMode
models . DbCfg . Path = form . DbPath
2014-03-30 01:50:51 +04:00
2015-09-12 22:31:36 +03:00
if ( models . DbCfg . Type == "sqlite3" || models . DbCfg . Type == "tidb" ) &&
len ( models . DbCfg . Path ) == 0 {
ctx . Data [ "Err_DbPath" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.err_empty_db_path" ) , tplInstall , & form )
2015-09-12 22:31:36 +03:00
return
} else if models . DbCfg . Type == "tidb" &&
strings . ContainsAny ( path . Base ( models . DbCfg . Path ) , ".-" ) {
2015-07-08 14:47:56 +03:00
ctx . Data [ "Err_DbPath" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.err_invalid_tidb_name" ) , tplInstall , & form )
2015-07-08 14:47:56 +03:00
return
}
2014-03-30 19:09:59 +04:00
// Set test engine.
2014-03-30 18:47:08 +04:00
var x * xorm . Engine
if err := models . NewTestEngine ( x ) ; err != nil {
2014-03-30 19:09:59 +04:00
if strings . Contains ( err . Error ( ) , ` Unknown database type: sqlite3 ` ) {
2015-07-08 14:47:56 +03:00
ctx . Data [ "Err_DbType" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.sqlite3_not_available" , "https://gogs.io/docs/installation/install_from_binary.html" ) , tplInstall , & form )
2014-03-30 17:39:44 +04:00
} else {
2015-07-08 14:47:56 +03:00
ctx . Data [ "Err_DbSetting" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_setting" , err ) , tplInstall , & form )
2014-03-30 17:39:44 +04:00
}
2014-03-30 01:50:51 +04:00
return
}
// Test repository root path.
2015-11-24 06:32:07 +03:00
form . RepoRootPath = strings . Replace ( form . RepoRootPath , "\\" , "/" , - 1 )
2014-03-30 01:50:51 +04: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-02-12 17:19:45 +03:00
// Test log root path.
form . LogRootPath = strings . Replace ( form . LogRootPath , "\\" , "/" , - 1 )
if err := os . MkdirAll ( form . LogRootPath , os . ModePerm ) ; err != nil {
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
}
2014-09-08 03:02:58 +04:00
// Check admin password.
2015-09-12 22:31:36 +03:00
if len ( form . AdminName ) > 0 && len ( form . AdminPasswd ) == 0 {
ctx . Data [ "Err_Admin" ] = true
ctx . Data [ "Err_AdminPasswd" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.err_empty_admin_password" ) , tplInstall , form )
2015-09-12 22:31:36 +03:00
return
}
2015-02-01 20:41:03 +03:00
if form . AdminPasswd != form . AdminConfirmPasswd {
2015-08-02 07:36:35 +03:00
ctx . Data [ "Err_Admin" ] = true
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_AdminPasswd" ] = true
2016-11-18 06:03:03 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.password_not_match" ) , tplInstall , form )
2014-03-30 19:58:21 +04:00
return
}
2016-11-27 09:03:59 +03:00
if form . AppURL [ len ( form . AppURL ) - 1 ] != '/' {
form . AppURL += "/"
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 ( )
2015-02-14 00:48:23 +03:00
if com . IsFile ( setting . CustomConf ) {
// Keeps custom settings if there is already something.
if err := cfg . Append ( setting . CustomConf ) ; err != nil {
log . Error ( 4 , "Fail to load custom conf '%s': %v" , setting . CustomConf , err )
}
}
2015-02-01 22:39:58 +03:00
cfg . Section ( "database" ) . Key ( "DB_TYPE" ) . SetValue ( models . DbCfg . Type )
cfg . Section ( "database" ) . Key ( "HOST" ) . SetValue ( models . DbCfg . Host )
cfg . Section ( "database" ) . Key ( "NAME" ) . SetValue ( models . DbCfg . Name )
cfg . Section ( "database" ) . Key ( "USER" ) . SetValue ( models . DbCfg . User )
cfg . Section ( "database" ) . Key ( "PASSWD" ) . SetValue ( models . DbCfg . Passwd )
cfg . Section ( "database" ) . Key ( "SSL_MODE" ) . SetValue ( models . DbCfg . SSLMode )
cfg . Section ( "database" ) . Key ( "PATH" ) . SetValue ( models . DbCfg . Path )
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 )
cfg . Section ( "server" ) . Key ( "DOMAIN" ) . SetValue ( form . Domain )
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" )
cfg . Section ( "server" ) . Key ( "SSH_PORT" ) . SetValue ( com . ToStr ( form . SSHPort ) )
}
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 )
2015-02-01 22:39:58 +03:00
cfg . Section ( "mailer" ) . Key ( "USER" ) . SetValue ( form . SMTPEmail )
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
}
2015-07-09 08:17:48 +03:00
cfg . Section ( "service" ) . Key ( "REGISTER_EMAIL_CONFIRM" ) . SetValue ( com . ToStr ( form . RegisterConfirm ) )
cfg . Section ( "service" ) . Key ( "ENABLE_NOTIFY_MAIL" ) . SetValue ( com . ToStr ( form . MailNotify ) )
cfg . Section ( "server" ) . Key ( "OFFLINE_MODE" ) . SetValue ( com . ToStr ( form . OfflineMode ) )
2015-08-29 19:22:26 +03:00
cfg . Section ( "picture" ) . Key ( "DISABLE_GRAVATAR" ) . SetValue ( com . ToStr ( form . DisableGravatar ) )
2016-08-07 20:27:38 +03:00
cfg . Section ( "picture" ) . Key ( "ENABLE_FEDERATED_AVATAR" ) . SetValue ( com . ToStr ( form . EnableFederatedAvatar ) )
2015-07-09 08:17:48 +03:00
cfg . Section ( "service" ) . Key ( "DISABLE_REGISTRATION" ) . SetValue ( com . ToStr ( form . DisableRegistration ) )
2015-09-13 19:14:32 +03:00
cfg . Section ( "service" ) . Key ( "ENABLE_CAPTCHA" ) . SetValue ( com . ToStr ( form . EnableCaptcha ) )
2015-07-09 08:17:48 +03:00
cfg . Section ( "service" ) . Key ( "REQUIRE_SIGNIN_VIEW" ) . SetValue ( com . ToStr ( form . RequireSignInView ) )
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
2015-02-01 22:39:58 +03:00
cfg . Section ( "log" ) . Key ( "MODE" ) . SetValue ( "file" )
2015-02-27 03:45:38 +03:00
cfg . Section ( "log" ) . Key ( "LEVEL" ) . SetValue ( "Info" )
2016-02-12 17:19:45 +03:00
cfg . Section ( "log" ) . Key ( "ROOT_PATH" ) . SetValue ( form . LogRootPath )
2014-08-27 12:39:36 +04:00
2015-02-01 22:39:58 +03:00
cfg . Section ( "security" ) . Key ( "INSTALL_LOCK" ) . SetValue ( "true" )
cfg . Section ( "security" ) . Key ( "SECRET_KEY" ) . SetValue ( base . GetRandomString ( 15 ) )
2014-03-30 01:50:51 +04:00
2016-11-10 13:02:01 +03:00
err := os . MkdirAll ( filepath . Dir ( setting . CustomConf ) , os . ModePerm )
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
}
2015-02-05 13:12:37 +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
}
GlobalInit ( )
2015-12-08 08:59:14 +03:00
// Create admin account
2015-07-08 14:47:56 +03:00
if len ( form . AdminName ) > 0 {
2015-12-08 08:59:14 +03:00
u := & models . 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
}
if err := models . CreateUser ( u ) ; err != nil {
2015-07-08 14:47:56 +03:00
if ! models . IsErrUserAlreadyExist ( err ) {
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" )
2015-12-08 08:59:14 +03:00
u , _ = models . GetUserByName ( u . Name )
2014-03-30 19:09:59 +04:00
}
2015-12-08 08:59:14 +03:00
// Auto-login for admin
2016-11-10 13:02:01 +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
}
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
}
2014-03-30 19:09:59 +04:00
}
2014-03-30 01:50:51 +04:00
log . Info ( "First-time run install finished!" )
2014-09-08 03:02:58 +04:00
ctx . Flash . Success ( ctx . Tr ( "install.install_success" ) )
2016-11-27 09:03:59 +03:00
ctx . Redirect ( form . AppURL + "user/login" )
2014-03-25 12:51:42 +04:00
}