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.

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