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
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
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/Unknwon/macaron"
  14. "github.com/go-xorm/xorm"
  15. "gopkg.in/ini.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/social"
  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. social.NewOauthService()
  42. }
  43. // GlobalInit is for global configuration reload-able.
  44. func GlobalInit() {
  45. setting.NewConfigContext()
  46. log.Trace("Custom path: %s", setting.CustomPath)
  47. log.Trace("Log path: %s", setting.LogRootPath)
  48. mailer.NewMailerContext()
  49. models.LoadModelsConfig()
  50. NewServices()
  51. if setting.InstallLock {
  52. models.LoadRepoConfig()
  53. models.NewRepoContext()
  54. if err := models.NewEngine(); err != nil {
  55. log.Fatal(4, "Fail to initialize ORM engine: %v", err)
  56. }
  57. models.HasEngine = true
  58. cron.NewCronContext()
  59. models.InitDeliverHooks()
  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. }
  70. func InstallInit(ctx *middleware.Context) {
  71. if setting.InstallLock {
  72. ctx.Handle(404, "Install", errors.New("Installation is prohibited"))
  73. return
  74. }
  75. ctx.Data["Title"] = ctx.Tr("install.install")
  76. ctx.Data["PageIsInstall"] = true
  77. dbOpts := []string{"MySQL", "PostgreSQL"}
  78. if models.EnableSQLite3 {
  79. dbOpts = append(dbOpts, "SQLite3")
  80. }
  81. if models.EnableTidb {
  82. dbOpts = append(dbOpts, "TiDB")
  83. }
  84. ctx.Data["DbOptions"] = dbOpts
  85. }
  86. func Install(ctx *middleware.Context) {
  87. form := auth.InstallForm{}
  88. // Database settings
  89. form.DbHost = models.DbCfg.Host
  90. form.DbUser = models.DbCfg.User
  91. form.DbName = models.DbCfg.Name
  92. form.DbPath = models.DbCfg.Path
  93. ctx.Data["CurDbOption"] = "MySQL"
  94. switch models.DbCfg.Type {
  95. case "postgres":
  96. ctx.Data["CurDbOption"] = "PostgreSQL"
  97. case "sqlite3":
  98. if models.EnableSQLite3 {
  99. ctx.Data["CurDbOption"] = "SQLite3"
  100. }
  101. case "tidb":
  102. if models.EnableTidb {
  103. ctx.Data["CurDbOption"] = "TiDB"
  104. }
  105. }
  106. // Application general settings
  107. form.AppName = setting.AppName
  108. form.RepoRootPath = setting.RepoRootPath
  109. // Note(unknwon): it's hard for Windows users change a running user,
  110. // so just use current one if config says default.
  111. if setting.IsWindows && setting.RunUser == "git" {
  112. form.RunUser = user.CurrentUsername()
  113. } else {
  114. form.RunUser = setting.RunUser
  115. }
  116. form.Domain = setting.Domain
  117. form.SSHPort = setting.SSHPort
  118. form.HTTPPort = setting.HttpPort
  119. form.AppUrl = setting.AppUrl
  120. // E-mail service settings
  121. if setting.MailService != nil {
  122. form.SMTPHost = setting.MailService.Host
  123. form.SMTPFrom = setting.MailService.From
  124. form.SMTPEmail = setting.MailService.User
  125. }
  126. form.RegisterConfirm = setting.Service.RegisterEmailConfirm
  127. form.MailNotify = setting.Service.EnableNotifyMail
  128. // Server and other services settings
  129. form.OfflineMode = setting.OfflineMode
  130. form.DisableGravatar = setting.DisableGravatar
  131. form.DisableRegistration = setting.Service.DisableRegistration
  132. form.EnableCaptcha = setting.Service.EnableCaptcha
  133. form.RequireSignInView = setting.Service.RequireSignInView
  134. auth.AssignForm(form, ctx.Data)
  135. ctx.HTML(200, INSTALL)
  136. }
  137. func InstallPost(ctx *middleware.Context, form auth.InstallForm) {
  138. ctx.Data["CurDbOption"] = form.DbType
  139. if ctx.HasError() {
  140. if ctx.HasValue("Err_SMTPEmail") {
  141. ctx.Data["Err_SMTP"] = true
  142. }
  143. if ctx.HasValue("Err_AdminName") ||
  144. ctx.HasValue("Err_AdminPasswd") ||
  145. ctx.HasValue("Err_AdminEmail") {
  146. ctx.Data["Err_Admin"] = true
  147. }
  148. ctx.HTML(200, INSTALL)
  149. return
  150. }
  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. }