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.

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