You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

install.go 11KB

10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
10 years ago
10 years ago
8 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package routers
  5. import (
  6. "errors"
  7. "os"
  8. "os/exec"
  9. "path"
  10. "path/filepath"
  11. "strings"
  12. "github.com/Unknwon/com"
  13. "github.com/go-xorm/xorm"
  14. "gopkg.in/ini.v1"
  15. "gopkg.in/macaron.v1"
  16. "github.com/gogits/git-shell"
  17. "github.com/gogits/gogs/models"
  18. "github.com/gogits/gogs/models/cron"
  19. "github.com/gogits/gogs/modules/auth"
  20. "github.com/gogits/gogs/modules/base"
  21. "github.com/gogits/gogs/modules/log"
  22. "github.com/gogits/gogs/modules/mailer"
  23. "github.com/gogits/gogs/modules/middleware"
  24. "github.com/gogits/gogs/modules/setting"
  25. "github.com/gogits/gogs/modules/ssh"
  26. "github.com/gogits/gogs/modules/user"
  27. )
  28. const (
  29. INSTALL base.TplName = "install"
  30. )
  31. func checkRunMode() {
  32. switch setting.Cfg.Section("").Key("RUN_MODE").String() {
  33. case "prod":
  34. macaron.Env = macaron.PROD
  35. macaron.ColorLog = false
  36. setting.ProdMode = true
  37. git.Debug = false
  38. }
  39. log.Info("Run Mode: %s", strings.Title(macaron.Env))
  40. }
  41. func NewServices() {
  42. setting.NewServices()
  43. mailer.NewContext()
  44. }
  45. // GlobalInit is for global configuration reload-able.
  46. func GlobalInit() {
  47. setting.NewContext()
  48. log.Trace("Custom path: %s", setting.CustomPath)
  49. log.Trace("Log path: %s", setting.LogRootPath)
  50. models.LoadConfigs()
  51. NewServices()
  52. if setting.InstallLock {
  53. models.LoadRepoConfig()
  54. models.NewRepoContext()
  55. if err := models.NewEngine(); err != nil {
  56. log.Fatal(4, "Fail to initialize ORM engine: %v", err)
  57. }
  58. models.HasEngine = true
  59. cron.NewContext()
  60. models.InitDeliverHooks()
  61. models.InitTestPullRequests()
  62. log.NewGitLogger(path.Join(setting.LogRootPath, "http.log"))
  63. }
  64. if models.EnableSQLite3 {
  65. log.Info("SQLite3 Supported")
  66. }
  67. if models.EnableTidb {
  68. log.Info("TiDB Supported")
  69. }
  70. checkRunMode()
  71. if setting.StartSSHServer {
  72. ssh.Listen(setting.SSHPort)
  73. log.Info("SSH server started on :%v", setting.SSHPort)
  74. }
  75. }
  76. func InstallInit(ctx *middleware.Context) {
  77. if setting.InstallLock {
  78. ctx.Handle(404, "Install", errors.New("Installation is prohibited"))
  79. return
  80. }
  81. ctx.Data["Title"] = ctx.Tr("install.install")
  82. ctx.Data["PageIsInstall"] = true
  83. dbOpts := []string{"MySQL", "PostgreSQL"}
  84. if models.EnableSQLite3 {
  85. dbOpts = append(dbOpts, "SQLite3")
  86. }
  87. if models.EnableTidb {
  88. dbOpts = append(dbOpts, "TiDB")
  89. }
  90. ctx.Data["DbOptions"] = dbOpts
  91. }
  92. func Install(ctx *middleware.Context) {
  93. form := auth.InstallForm{}
  94. // Database settings
  95. form.DbHost = models.DbCfg.Host
  96. form.DbUser = models.DbCfg.User
  97. form.DbName = models.DbCfg.Name
  98. form.DbPath = models.DbCfg.Path
  99. ctx.Data["CurDbOption"] = "MySQL"
  100. switch models.DbCfg.Type {
  101. case "postgres":
  102. ctx.Data["CurDbOption"] = "PostgreSQL"
  103. case "sqlite3":
  104. if models.EnableSQLite3 {
  105. ctx.Data["CurDbOption"] = "SQLite3"
  106. }
  107. case "tidb":
  108. if models.EnableTidb {
  109. ctx.Data["CurDbOption"] = "TiDB"
  110. }
  111. }
  112. // Application general settings
  113. form.AppName = setting.AppName
  114. form.RepoRootPath = setting.RepoRootPath
  115. // Note(unknwon): it's hard for Windows users change a running user,
  116. // so just use current one if config says default.
  117. if setting.IsWindows && setting.RunUser == "git" {
  118. form.RunUser = user.CurrentUsername()
  119. } else {
  120. form.RunUser = setting.RunUser
  121. }
  122. form.Domain = setting.Domain
  123. form.SSHPort = setting.SSHPort
  124. form.HTTPPort = setting.HttpPort
  125. form.AppUrl = setting.AppUrl
  126. // E-mail service settings
  127. if setting.MailService != nil {
  128. form.SMTPHost = setting.MailService.Host
  129. form.SMTPFrom = setting.MailService.From
  130. form.SMTPEmail = setting.MailService.User
  131. }
  132. form.RegisterConfirm = setting.Service.RegisterEmailConfirm
  133. form.MailNotify = setting.Service.EnableNotifyMail
  134. // Server and other services settings
  135. form.OfflineMode = setting.OfflineMode
  136. form.DisableGravatar = setting.DisableGravatar
  137. form.DisableRegistration = setting.Service.DisableRegistration
  138. form.EnableCaptcha = setting.Service.EnableCaptcha
  139. form.RequireSignInView = setting.Service.RequireSignInView
  140. auth.AssignForm(form, ctx.Data)
  141. ctx.HTML(200, INSTALL)
  142. }
  143. func InstallPost(ctx *middleware.Context, form auth.InstallForm) {
  144. ctx.Data["CurDbOption"] = form.DbType
  145. if ctx.HasError() {
  146. if ctx.HasValue("Err_SMTPEmail") {
  147. ctx.Data["Err_SMTP"] = true
  148. }
  149. if ctx.HasValue("Err_AdminName") ||
  150. ctx.HasValue("Err_AdminPasswd") ||
  151. ctx.HasValue("Err_AdminEmail") {
  152. ctx.Data["Err_Admin"] = true
  153. }
  154. ctx.HTML(200, INSTALL)
  155. return
  156. }
  157. if _, err := exec.LookPath("git"); err != nil {
  158. ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), INSTALL, &form)
  159. return
  160. }
  161. // Pass basic check, now test configuration.
  162. // Test database setting.
  163. dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3", "TiDB": "tidb"}
  164. models.DbCfg.Type = dbTypes[form.DbType]
  165. models.DbCfg.Host = form.DbHost
  166. models.DbCfg.User = form.DbUser
  167. models.DbCfg.Passwd = form.DbPasswd
  168. models.DbCfg.Name = form.DbName
  169. models.DbCfg.SSLMode = form.SSLMode
  170. models.DbCfg.Path = form.DbPath
  171. if (models.DbCfg.Type == "sqlite3" || models.DbCfg.Type == "tidb") &&
  172. len(models.DbCfg.Path) == 0 {
  173. ctx.Data["Err_DbPath"] = true
  174. ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), INSTALL, &form)
  175. return
  176. } else if models.DbCfg.Type == "tidb" &&
  177. strings.ContainsAny(path.Base(models.DbCfg.Path), ".-") {
  178. ctx.Data["Err_DbPath"] = true
  179. ctx.RenderWithErr(ctx.Tr("install.err_invalid_tidb_name"), INSTALL, &form)
  180. return
  181. }
  182. // Set test engine.
  183. var x *xorm.Engine
  184. if err := models.NewTestEngine(x); err != nil {
  185. if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
  186. ctx.Data["Err_DbType"] = true
  187. ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "http://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &form)
  188. } else {
  189. ctx.Data["Err_DbSetting"] = true
  190. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), INSTALL, &form)
  191. }
  192. return
  193. }
  194. // Test repository root path.
  195. form.RepoRootPath = strings.Replace(form.RepoRootPath, "\\", "/", -1)
  196. if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
  197. ctx.Data["Err_RepoRootPath"] = true
  198. ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), INSTALL, &form)
  199. return
  200. }
  201. // Check run user.
  202. curUser := user.CurrentUsername()
  203. if form.RunUser != curUser {
  204. ctx.Data["Err_RunUser"] = true
  205. ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, curUser), INSTALL, &form)
  206. return
  207. }
  208. // Check logic loophole between disable self-registration and no admin account.
  209. if form.DisableRegistration && len(form.AdminName) == 0 {
  210. ctx.Data["Err_Services"] = true
  211. ctx.Data["Err_Admin"] = true
  212. ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), INSTALL, form)
  213. return
  214. }
  215. // Check admin password.
  216. if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 {
  217. ctx.Data["Err_Admin"] = true
  218. ctx.Data["Err_AdminPasswd"] = true
  219. ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), INSTALL, form)
  220. return
  221. }
  222. if form.AdminPasswd != form.AdminConfirmPasswd {
  223. ctx.Data["Err_Admin"] = true
  224. ctx.Data["Err_AdminPasswd"] = true
  225. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), INSTALL, form)
  226. return
  227. }
  228. if form.AppUrl[len(form.AppUrl)-1] != '/' {
  229. form.AppUrl += "/"
  230. }
  231. // Save settings.
  232. cfg := ini.Empty()
  233. if com.IsFile(setting.CustomConf) {
  234. // Keeps custom settings if there is already something.
  235. if err := cfg.Append(setting.CustomConf); err != nil {
  236. log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err)
  237. }
  238. }
  239. cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type)
  240. cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host)
  241. cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name)
  242. cfg.Section("database").Key("USER").SetValue(models.DbCfg.User)
  243. cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd)
  244. cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode)
  245. cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path)
  246. cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
  247. cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
  248. cfg.Section("").Key("RUN_USER").SetValue(form.RunUser)
  249. cfg.Section("server").Key("DOMAIN").SetValue(form.Domain)
  250. cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort)
  251. cfg.Section("server").Key("ROOT_URL").SetValue(form.AppUrl)
  252. if form.SSHPort == 0 {
  253. cfg.Section("server").Key("DISABLE_SSH").SetValue("true")
  254. } else {
  255. cfg.Section("server").Key("DISABLE_SSH").SetValue("false")
  256. cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(form.SSHPort))
  257. }
  258. if len(strings.TrimSpace(form.SMTPHost)) > 0 {
  259. cfg.Section("mailer").Key("ENABLED").SetValue("true")
  260. cfg.Section("mailer").Key("HOST").SetValue(form.SMTPHost)
  261. cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom)
  262. cfg.Section("mailer").Key("USER").SetValue(form.SMTPEmail)
  263. cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd)
  264. } else {
  265. cfg.Section("mailer").Key("ENABLED").SetValue("false")
  266. }
  267. cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(form.RegisterConfirm))
  268. cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(form.MailNotify))
  269. cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(form.OfflineMode))
  270. cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(form.DisableGravatar))
  271. cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration))
  272. cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha))
  273. cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView))
  274. cfg.Section("").Key("RUN_MODE").SetValue("prod")
  275. cfg.Section("session").Key("PROVIDER").SetValue("file")
  276. cfg.Section("log").Key("MODE").SetValue("file")
  277. cfg.Section("log").Key("LEVEL").SetValue("Info")
  278. cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
  279. cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15))
  280. os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
  281. if err := cfg.SaveTo(setting.CustomConf); err != nil {
  282. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &form)
  283. return
  284. }
  285. GlobalInit()
  286. // Create admin account.
  287. if len(form.AdminName) > 0 {
  288. if err := models.CreateUser(&models.User{
  289. Name: form.AdminName,
  290. Email: form.AdminEmail,
  291. Passwd: form.AdminPasswd,
  292. IsAdmin: true,
  293. IsActive: true,
  294. }); err != nil {
  295. if !models.IsErrUserAlreadyExist(err) {
  296. setting.InstallLock = false
  297. ctx.Data["Err_AdminName"] = true
  298. ctx.Data["Err_AdminEmail"] = true
  299. ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), INSTALL, &form)
  300. return
  301. }
  302. log.Info("Admin account already exist")
  303. }
  304. }
  305. log.Info("First-time run install finished!")
  306. ctx.Flash.Success(ctx.Tr("install.install_success"))
  307. ctx.Redirect(form.AppUrl + "user/login")
  308. }