You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

install.go 11 kB

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