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.

354 lines
11 KiB

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