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.

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