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.

349 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. return
  151. if _, err := exec.LookPath("git"); err != nil {
  152. ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), INSTALL, &form)
  153. return
  154. }
  155. // Pass basic check, now test configuration.
  156. // Test database setting.
  157. dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3", "TiDB": "tidb"}
  158. models.DbCfg.Type = dbTypes[form.DbType]
  159. models.DbCfg.Host = form.DbHost
  160. models.DbCfg.User = form.DbUser
  161. models.DbCfg.Passwd = form.DbPasswd
  162. models.DbCfg.Name = form.DbName
  163. models.DbCfg.SSLMode = form.SSLMode
  164. models.DbCfg.Path = form.DbPath
  165. if (models.DbCfg.Type == "sqlite3" || models.DbCfg.Type == "tidb") &&
  166. len(models.DbCfg.Path) == 0 {
  167. ctx.Data["Err_DbPath"] = true
  168. ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), INSTALL, &form)
  169. return
  170. } else if models.DbCfg.Type == "tidb" &&
  171. strings.ContainsAny(path.Base(models.DbCfg.Path), ".-") {
  172. ctx.Data["Err_DbPath"] = true
  173. ctx.RenderWithErr(ctx.Tr("install.err_invalid_tidb_name"), INSTALL, &form)
  174. return
  175. }
  176. // Set test engine.
  177. var x *xorm.Engine
  178. if err := models.NewTestEngine(x); err != nil {
  179. if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
  180. ctx.Data["Err_DbType"] = true
  181. ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "http://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &form)
  182. } else {
  183. ctx.Data["Err_DbSetting"] = true
  184. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), INSTALL, &form)
  185. }
  186. return
  187. }
  188. // Test repository root path.
  189. if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
  190. ctx.Data["Err_RepoRootPath"] = true
  191. ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), INSTALL, &form)
  192. return
  193. }
  194. // Check run user.
  195. curUser := user.CurrentUsername()
  196. if form.RunUser != curUser {
  197. ctx.Data["Err_RunUser"] = true
  198. ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, curUser), INSTALL, &form)
  199. return
  200. }
  201. // Check logic loophole between disable self-registration and no admin account.
  202. if form.DisableRegistration && len(form.AdminName) == 0 {
  203. ctx.Data["Err_Services"] = true
  204. ctx.Data["Err_Admin"] = true
  205. ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), INSTALL, form)
  206. return
  207. }
  208. // Check admin password.
  209. if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 {
  210. ctx.Data["Err_Admin"] = true
  211. ctx.Data["Err_AdminPasswd"] = true
  212. ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), INSTALL, form)
  213. return
  214. }
  215. if form.AdminPasswd != form.AdminConfirmPasswd {
  216. ctx.Data["Err_Admin"] = true
  217. ctx.Data["Err_AdminPasswd"] = true
  218. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), INSTALL, form)
  219. return
  220. }
  221. if form.AppUrl[len(form.AppUrl)-1] != '/' {
  222. form.AppUrl += "/"
  223. }
  224. // Save settings.
  225. cfg := ini.Empty()
  226. if com.IsFile(setting.CustomConf) {
  227. // Keeps custom settings if there is already something.
  228. if err := cfg.Append(setting.CustomConf); err != nil {
  229. log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err)
  230. }
  231. }
  232. cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type)
  233. cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host)
  234. cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name)
  235. cfg.Section("database").Key("USER").SetValue(models.DbCfg.User)
  236. cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd)
  237. cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode)
  238. cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path)
  239. cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
  240. cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
  241. cfg.Section("").Key("RUN_USER").SetValue(form.RunUser)
  242. cfg.Section("server").Key("DOMAIN").SetValue(form.Domain)
  243. cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort)
  244. cfg.Section("server").Key("ROOT_URL").SetValue(form.AppUrl)
  245. if form.SSHPort == 0 {
  246. cfg.Section("server").Key("DISABLE_SSH").SetValue("true")
  247. } else {
  248. cfg.Section("server").Key("DISABLE_SSH").SetValue("false")
  249. cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(form.SSHPort))
  250. }
  251. if len(strings.TrimSpace(form.SMTPHost)) > 0 {
  252. cfg.Section("mailer").Key("ENABLED").SetValue("true")
  253. cfg.Section("mailer").Key("HOST").SetValue(form.SMTPHost)
  254. cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom)
  255. cfg.Section("mailer").Key("USER").SetValue(form.SMTPEmail)
  256. cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd)
  257. } else {
  258. cfg.Section("mailer").Key("ENABLED").SetValue("false")
  259. }
  260. cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(form.RegisterConfirm))
  261. cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(form.MailNotify))
  262. cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(form.OfflineMode))
  263. cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(form.DisableGravatar))
  264. cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration))
  265. cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha))
  266. cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView))
  267. cfg.Section("").Key("RUN_MODE").SetValue("prod")
  268. cfg.Section("session").Key("PROVIDER").SetValue("file")
  269. cfg.Section("log").Key("MODE").SetValue("file")
  270. cfg.Section("log").Key("LEVEL").SetValue("Info")
  271. cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
  272. cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15))
  273. os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
  274. if err := cfg.SaveTo(setting.CustomConf); err != nil {
  275. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &form)
  276. return
  277. }
  278. GlobalInit()
  279. // Create admin account.
  280. if len(form.AdminName) > 0 {
  281. if err := models.CreateUser(&models.User{
  282. Name: form.AdminName,
  283. Email: form.AdminEmail,
  284. Passwd: form.AdminPasswd,
  285. IsAdmin: true,
  286. IsActive: true,
  287. }); err != nil {
  288. if !models.IsErrUserAlreadyExist(err) {
  289. setting.InstallLock = false
  290. ctx.Data["Err_AdminName"] = true
  291. ctx.Data["Err_AdminEmail"] = true
  292. ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), INSTALL, &form)
  293. return
  294. }
  295. log.Info("Admin account already exist")
  296. }
  297. }
  298. log.Info("First-time run install finished!")
  299. ctx.Flash.Success(ctx.Tr("install.install_success"))
  300. ctx.Redirect(form.AppUrl + "user/login")
  301. }