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"
2014-03-30 01:50:51 +04:00
"strings"
2014-07-26 08:24:27 +04:00
"github.com/Unknwon/com"
2014-03-30 01:50:51 +04:00
"github.com/Unknwon/goconfig"
2014-07-26 08:24:27 +04:00
"github.com/Unknwon/macaron"
2014-04-18 17:35:09 +04:00
"github.com/go-xorm/xorm"
2014-03-28 15:26:22 +04:00
"github.com/gogits/gogs/models"
2014-03-29 02:40:31 +04:00
"github.com/gogits/gogs/modules/auth"
2014-03-28 15:26:22 +04:00
"github.com/gogits/gogs/modules/base"
2014-04-13 05:30:09 +04:00
"github.com/gogits/gogs/modules/cron"
2014-03-30 01:50:51 +04:00
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/mailer"
2014-03-28 15:26:22 +04:00
"github.com/gogits/gogs/modules/middleware"
2014-05-26 04:11:25 +04:00
"github.com/gogits/gogs/modules/setting"
2014-04-14 02:12:07 +04:00
"github.com/gogits/gogs/modules/social"
2014-03-28 15:26:22 +04:00
)
2014-06-22 21:14:03 +04:00
const (
INSTALL base . TplName = "install"
)
2014-03-30 01:50:51 +04:00
func checkRunMode ( ) {
2014-05-26 04:11:25 +04:00
switch setting . Cfg . MustValue ( "" , "RUN_MODE" ) {
2014-03-30 01:50:51 +04:00
case "prod" :
2014-07-26 08:24:27 +04:00
macaron . Env = macaron . PROD
2014-05-26 04:11:25 +04:00
setting . ProdMode = true
2014-03-30 01:50:51 +04:00
case "test" :
2014-07-26 08:24:27 +04:00
macaron . Env = macaron . TEST
2014-03-30 01:50:51 +04:00
}
2014-07-26 08:24:27 +04:00
log . Info ( "Run Mode: %s" , strings . Title ( macaron . Env ) )
2014-03-30 01:50:51 +04:00
}
2014-04-14 02:12:07 +04:00
func NewServices ( ) {
2014-05-26 04:11:25 +04:00
setting . NewServices ( )
2014-04-14 02:12:07 +04:00
social . NewOauthService ( )
}
2014-03-30 01:50:51 +04:00
// GlobalInit is for global configuration reload-able.
func GlobalInit ( ) {
2014-05-26 04:11:25 +04:00
setting . NewConfigContext ( )
2014-05-26 04:57:01 +04:00
log . Trace ( "Custom path: %s" , setting . CustomPath )
2014-05-30 14:34:24 +04:00
log . Trace ( "Log path: %s" , setting . LogRootPath )
2014-03-30 01:50:51 +04:00
mailer . NewMailerContext ( )
models . LoadModelsConfig ( )
2014-04-20 06:13:22 +04:00
NewServices ( )
2014-03-30 18:47:08 +04:00
2014-05-26 04:11:25 +04:00
if setting . InstallLock {
2014-07-27 02:37:18 +04:00
models . LoadRepoConfig ( )
models . NewRepoContext ( )
2014-03-30 18:47:08 +04:00
if err := models . NewEngine ( ) ; err != nil {
2014-07-26 08:24:27 +04:00
log . Fatal ( 4 , "Fail to initialize ORM engine: %v" , err )
2014-03-30 18:47:08 +04:00
}
models . HasEngine = true
2014-04-13 05:30:09 +04:00
cron . NewCronContext ( )
2014-06-20 09:14:54 +04:00
log . NewGitLogger ( path . Join ( setting . LogRootPath , "http.log" ) )
2014-03-30 01:50:51 +04:00
}
2014-05-31 03:19:30 +04:00
if models . EnableSQLite3 {
log . Info ( "SQLite3 Enabled" )
}
2014-03-30 01:50:51 +04:00
checkRunMode ( )
}
2014-04-27 08:34:48 +04:00
func renderDbOption ( ctx * middleware . Context ) {
ctx . Data [ "DbOptions" ] = [ ] string { "MySQL" , "PostgreSQL" , "SQLite3" }
}
2014-06-22 21:14:03 +04:00
// @router /install [get]
2014-04-11 00:36:50 +04:00
func Install ( ctx * middleware . Context , form auth . InstallForm ) {
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
2014-11-24 17:54:08 +03:00
// FIXME: when i'm ckeching length here? should they all be 0 no matter when?
2014-05-05 21:08:01 +04:00
// Get and assign values to install form.
2014-09-08 03:02:58 +04:00
if len ( form . DbHost ) == 0 {
form . DbHost = models . DbCfg . Host
2014-04-10 22:37:43 +04:00
}
2014-09-08 03:02:58 +04:00
if len ( form . DbUser ) == 0 {
form . DbUser = models . DbCfg . User
2014-04-10 22:37:43 +04:00
}
2014-09-08 03:02:58 +04:00
if len ( form . DbPasswd ) == 0 {
form . DbPasswd = models . DbCfg . Pwd
2014-04-10 22:37:43 +04:00
}
if len ( form . DatabaseName ) == 0 {
form . DatabaseName = models . DbCfg . Name
}
if len ( form . DatabasePath ) == 0 {
form . DatabasePath = models . DbCfg . Path
}
2014-03-30 01:50:51 +04:00
2014-04-10 22:37:43 +04:00
if len ( form . RepoRootPath ) == 0 {
2014-05-26 04:11:25 +04:00
form . RepoRootPath = setting . RepoRootPath
2014-04-10 22:37:43 +04:00
}
if len ( form . RunUser ) == 0 {
2014-11-24 17:54:08 +03:00
// Note: it's not normall to use SSH in windows so current user can be first option(not git).
if setting . IsWindows && setting . RunUser == "git" {
form . RunUser = os . Getenv ( "USER" )
if len ( form . RunUser ) == 0 {
form . RunUser = os . Getenv ( "USERNAME" )
}
} else {
form . RunUser = setting . RunUser
}
2014-04-10 22:37:43 +04:00
}
if len ( form . Domain ) == 0 {
2014-05-26 04:11:25 +04:00
form . Domain = setting . Domain
2014-04-10 22:37:43 +04:00
}
if len ( form . AppUrl ) == 0 {
2014-05-26 04:11:25 +04:00
form . AppUrl = setting . AppUrl
2014-04-10 22:37:43 +04:00
}
2014-03-30 01:50:51 +04:00
2014-04-27 08:34:48 +04:00
renderDbOption ( ctx )
2014-05-05 21:08:01 +04:00
curDbOp := ""
2014-04-27 08:34:48 +04:00
if models . EnableSQLite3 {
2014-05-05 21:08:01 +04:00
curDbOp = "SQLite3" // Default when enabled.
2014-04-27 08:34:48 +04:00
}
2014-05-05 21:08:01 +04:00
ctx . Data [ "CurDbOption" ] = curDbOp
2014-04-27 08:34:48 +04:00
2014-04-10 22:37:43 +04:00
auth . AssignForm ( form , ctx . Data )
2014-06-22 21:14:03 +04:00
ctx . HTML ( 200 , INSTALL )
2014-04-10 22:37:43 +04:00
}
2014-04-11 00:36:50 +04:00
func InstallPost ( ctx * middleware . Context , form auth . InstallForm ) {
2014-05-26 04:11:25 +04:00
if setting . InstallLock {
2014-09-08 03:02:58 +04:00
ctx . Handle ( 404 , "InstallPost" , errors . New ( "Installation is prohibited" ) )
2014-03-28 15:26:22 +04:00
return
}
2014-03-30 01:50:51 +04:00
2014-09-08 03:02:58 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "install.install" )
2014-04-10 22:37:43 +04:00
ctx . Data [ "PageIsInstall" ] = true
2014-04-27 08:34:48 +04:00
renderDbOption ( ctx )
2014-05-05 21:08:01 +04:00
ctx . Data [ "CurDbOption" ] = form . Database
2014-04-27 08:34:48 +04:00
2014-03-30 01:50:51 +04:00
if ctx . HasError ( ) {
2014-06-22 21:14:03 +04:00
ctx . HTML ( 200 , INSTALL )
2014-03-30 01:50:51 +04:00
return
}
2014-04-08 23:27:35 +04:00
if _ , err := exec . LookPath ( "git" ) ; err != nil {
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.test_git_failed" , err ) , INSTALL , & 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.
2014-04-27 08:34:48 +04:00
dbTypes := map [ string ] string { "MySQL" : "mysql" , "PostgreSQL" : "postgres" , "SQLite3" : "sqlite3" }
2014-03-30 01:50:51 +04:00
models . DbCfg . Type = dbTypes [ form . Database ]
2014-09-08 03:02:58 +04:00
models . DbCfg . Host = form . DbHost
models . DbCfg . User = form . DbUser
models . DbCfg . Pwd = form . DbPasswd
2014-03-30 01:50:51 +04:00
models . DbCfg . Name = form . DatabaseName
models . DbCfg . SslMode = form . SslMode
models . DbCfg . Path = form . DatabasePath
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-11-10 13:30:07 +03:00
// FIXME: should use core.QueryDriver (github.com/go-xorm/core)
2014-03-30 19:09:59 +04:00
if strings . Contains ( err . Error ( ) , ` Unknown database type: sqlite3 ` ) {
2014-11-10 13:30:07 +03:00
ctx . RenderWithErr ( ctx . Tr ( "install.sqlite3_not_available" , "http://gogs.io/docs/installation/install_from_binary.html" ) , INSTALL , & form )
2014-03-30 17:39:44 +04:00
} else {
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_db_setting" , err ) , INSTALL , & form )
2014-03-30 17:39:44 +04:00
}
2014-03-30 01:50:51 +04:00
return
}
// Test repository root path.
if err := os . MkdirAll ( form . RepoRootPath , os . ModePerm ) ; err != nil {
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_RepoRootPath" ] = true
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_repo_path" , err ) , INSTALL , & form )
2014-03-30 01:50:51 +04:00
return
}
2014-03-30 19:58:21 +04:00
// Check run user.
2014-04-12 07:52:08 +04:00
curUser := os . Getenv ( "USER" )
2014-03-30 19:58:21 +04:00
if len ( curUser ) == 0 {
2014-04-12 07:52:08 +04:00
curUser = os . Getenv ( "USERNAME" )
2014-03-30 19:58:21 +04:00
}
// Does not check run user when the install lock is off.
if form . RunUser != curUser {
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_RunUser" ] = true
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.run_user_not_match" , form . RunUser , curUser ) , INSTALL , & form )
return
}
// Check admin password.
if form . AdminPasswd != form . ConfirmPasswd {
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_AdminPasswd" ] = true
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "form.password_not_match" ) , INSTALL , form )
2014-03-30 19:58:21 +04:00
return
}
2014-03-30 01:50:51 +04:00
// Save settings.
2014-05-26 04:11:25 +04:00
setting . Cfg . SetValue ( "database" , "DB_TYPE" , models . DbCfg . Type )
setting . Cfg . SetValue ( "database" , "HOST" , models . DbCfg . Host )
setting . Cfg . SetValue ( "database" , "NAME" , models . DbCfg . Name )
setting . Cfg . SetValue ( "database" , "USER" , models . DbCfg . User )
setting . Cfg . SetValue ( "database" , "PASSWD" , models . DbCfg . Pwd )
setting . Cfg . SetValue ( "database" , "SSL_MODE" , models . DbCfg . SslMode )
setting . Cfg . SetValue ( "database" , "PATH" , models . DbCfg . Path )
setting . Cfg . SetValue ( "repository" , "ROOT" , form . RepoRootPath )
setting . Cfg . SetValue ( "" , "RUN_USER" , form . RunUser )
setting . Cfg . SetValue ( "server" , "DOMAIN" , form . Domain )
setting . Cfg . SetValue ( "server" , "ROOT_URL" , form . AppUrl )
2014-03-30 01:50:51 +04:00
2014-03-31 00:34:23 +04:00
if len ( strings . TrimSpace ( form . SmtpHost ) ) > 0 {
2014-05-26 04:11:25 +04:00
setting . Cfg . SetValue ( "mailer" , "ENABLED" , "true" )
setting . Cfg . SetValue ( "mailer" , "HOST" , form . SmtpHost )
setting . Cfg . SetValue ( "mailer" , "USER" , form . SmtpEmail )
setting . Cfg . SetValue ( "mailer" , "PASSWD" , form . SmtpPasswd )
2014-03-30 01:50:51 +04:00
2014-07-26 08:24:27 +04:00
setting . Cfg . SetValue ( "service" , "REGISTER_EMAIL_CONFIRM" , com . ToStr ( form . RegisterConfirm == "on" ) )
setting . Cfg . SetValue ( "service" , "ENABLE_NOTIFY_MAIL" , com . ToStr ( form . MailNotify == "on" ) )
2014-03-30 01:50:51 +04:00
}
2014-05-26 04:11:25 +04:00
setting . Cfg . SetValue ( "" , "RUN_MODE" , "prod" )
2014-03-30 19:58:21 +04:00
2014-08-27 12:39:36 +04:00
setting . Cfg . SetValue ( "log" , "MODE" , "file" )
2014-05-26 04:11:25 +04:00
setting . Cfg . SetValue ( "security" , "INSTALL_LOCK" , "true" )
2014-10-19 07:26:55 +04:00
setting . Cfg . SetValue ( "security" , "SECRET_KEY" , base . GetRandomString ( 15 ) )
2014-03-30 01:50:51 +04:00
2014-03-30 19:58:21 +04:00
os . MkdirAll ( "custom/conf" , os . ModePerm )
2014-05-26 04:11:25 +04:00
if err := goconfig . SaveConfigFile ( setting . Cfg , path . Join ( setting . CustomPath , "conf/app.ini" ) ) ; err != nil {
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.save_config_failed" , err ) , INSTALL , & form )
2014-03-30 01:50:51 +04:00
return
}
GlobalInit ( )
2014-03-30 19:09:59 +04:00
// Create admin account.
2014-07-26 08:24:27 +04:00
if err := models . CreateUser ( & models . User { Name : form . AdminName , Email : form . AdminEmail , Passwd : form . AdminPasswd ,
2014-03-30 19:09:59 +04:00
IsAdmin : true , IsActive : true } ) ; err != nil {
if err != models . ErrUserAlreadyExist {
2014-05-26 04:11:25 +04:00
setting . InstallLock = false
2014-09-15 03:22:52 +04:00
ctx . Data [ "Err_AdminName" ] = true
ctx . Data [ "Err_AdminEmail" ] = true
2014-09-08 03:02:58 +04:00
ctx . RenderWithErr ( ctx . Tr ( "install.invalid_admin_setting" , err ) , INSTALL , & form )
2014-03-30 19:09:59 +04:00
return
}
2014-03-31 00:01:50 +04:00
log . Info ( "Admin account already exist" )
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" ) )
2014-09-20 04:11:34 +04:00
ctx . Redirect ( setting . AppSubUrl + "/user/login" )
2014-03-25 12:51:42 +04:00
}