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.

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