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.

install.go 11KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Add support for federated avatars (#3320) * Add support for federated avatars Fixes #3105 Removes avatar fetching duplication code Adds an "Enable Federated Avatar" checkbox in user settings (defaults to unchecked) Moves avatar settings all in the same form, making local and remote avatars mutually exclusive Renames UploadAvatarForm to AvatarForm as it's not anymore only for uploading * Run gofmt on all modified files * Move Avatar form in its own page * Add go-libravatar dependency to vendor/ dir Hopefully helps with accepting the contribution. See also #3214 * Revert "Add go-libravatar dependency to vendor/ dir" This reverts commit a8cb93ae640bbb90f7d25012fc257bda9fae9b82. * Make federated avatar setting a global configuration Removes the per-user setting * Move avatar handling back to base tool, disable federated avatar in offline mode * Format, handle error * Properly set fallback host * Use unsupported github.com mirror for importing go-libravatar * Remove comment showing life exists outside of github.com ... pity, but contribution would not be accepted otherwise * Use Combo for Get and Post methods over /avatar * FEDERATED_AVATAR -> ENABLE_FEDERATED_AVATAR * Fix persistance of federated avatar lookup checkbox at install time * Federated Avatars -> Enable Federated Avatars * Use len(string) == 0 instead of string == "" * Move import line where it belong See https://github.com/Unknwon/go-code-convention/blob/master/en-US/import_packages.md Pity the import url is still the unofficial one, but oh well... * Save a line (and waste much more expensive time) * Remove redundant parens * Remove an empty line * Remove empty lines * Reorder lines to make diff smaller * Remove another newline Unknwon review got me start a fight against newlines * Move DISABLE_GRAVATAR and ENABLE_FEDERATED_AVATAR after OFFLINE_MODE On re-reading the diff I figured what Unknwon meant here: https://github.com/gogits/gogs/pull/3320/files#r73741106 * Remove newlines that weren't there before my intervention
7 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
9 years ago
9 years ago
9 years ago
10 years ago
Add support for federated avatars (#3320) * Add support for federated avatars Fixes #3105 Removes avatar fetching duplication code Adds an "Enable Federated Avatar" checkbox in user settings (defaults to unchecked) Moves avatar settings all in the same form, making local and remote avatars mutually exclusive Renames UploadAvatarForm to AvatarForm as it's not anymore only for uploading * Run gofmt on all modified files * Move Avatar form in its own page * Add go-libravatar dependency to vendor/ dir Hopefully helps with accepting the contribution. See also #3214 * Revert "Add go-libravatar dependency to vendor/ dir" This reverts commit a8cb93ae640bbb90f7d25012fc257bda9fae9b82. * Make federated avatar setting a global configuration Removes the per-user setting * Move avatar handling back to base tool, disable federated avatar in offline mode * Format, handle error * Properly set fallback host * Use unsupported github.com mirror for importing go-libravatar * Remove comment showing life exists outside of github.com ... pity, but contribution would not be accepted otherwise * Use Combo for Get and Post methods over /avatar * FEDERATED_AVATAR -> ENABLE_FEDERATED_AVATAR * Fix persistance of federated avatar lookup checkbox at install time * Federated Avatars -> Enable Federated Avatars * Use len(string) == 0 instead of string == "" * Move import line where it belong See https://github.com/Unknwon/go-code-convention/blob/master/en-US/import_packages.md Pity the import url is still the unofficial one, but oh well... * Save a line (and waste much more expensive time) * Remove redundant parens * Remove an empty line * Remove empty lines * Reorder lines to make diff smaller * Remove another newline Unknwon review got me start a fight against newlines * Move DISABLE_GRAVATAR and ENABLE_FEDERATED_AVATAR after OFFLINE_MODE On re-reading the diff I figured what Unknwon meant here: https://github.com/gogits/gogs/pull/3320/files#r73741106 * Remove newlines that weren't there before my intervention
7 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. "code.gitea.io/gitea/models"
  16. "code.gitea.io/gitea/modules/auth"
  17. "code.gitea.io/gitea/modules/base"
  18. "code.gitea.io/gitea/modules/context"
  19. "code.gitea.io/gitea/modules/log"
  20. "code.gitea.io/gitea/modules/setting"
  21. "code.gitea.io/gitea/modules/user"
  22. )
  23. const (
  24. // tplInstall template for installation page
  25. tplInstall base.TplName = "install"
  26. )
  27. // InstallInit prepare for rendering installation page
  28. func InstallInit(ctx *context.Context) {
  29. if setting.InstallLock {
  30. ctx.Handle(404, "Install", errors.New("Installation is prohibited"))
  31. return
  32. }
  33. ctx.Data["Title"] = ctx.Tr("install.install")
  34. ctx.Data["PageIsInstall"] = true
  35. dbOpts := []string{"MySQL", "PostgreSQL"}
  36. if models.EnableSQLite3 {
  37. dbOpts = append(dbOpts, "SQLite3")
  38. }
  39. if models.EnableTiDB {
  40. dbOpts = append(dbOpts, "TiDB")
  41. }
  42. ctx.Data["DbOptions"] = dbOpts
  43. }
  44. // Install render installation page
  45. func Install(ctx *context.Context) {
  46. form := auth.InstallForm{}
  47. // Database settings
  48. form.DbHost = models.DbCfg.Host
  49. form.DbUser = models.DbCfg.User
  50. form.DbName = models.DbCfg.Name
  51. form.DbPath = models.DbCfg.Path
  52. ctx.Data["CurDbOption"] = "MySQL"
  53. switch models.DbCfg.Type {
  54. case "postgres":
  55. ctx.Data["CurDbOption"] = "PostgreSQL"
  56. case "sqlite3":
  57. if models.EnableSQLite3 {
  58. ctx.Data["CurDbOption"] = "SQLite3"
  59. }
  60. case "tidb":
  61. if models.EnableTiDB {
  62. ctx.Data["CurDbOption"] = "TiDB"
  63. }
  64. }
  65. // Application general settings
  66. form.AppName = setting.AppName
  67. form.RepoRootPath = setting.RepoRootPath
  68. // Note(unknwon): it's hard for Windows users change a running user,
  69. // so just use current one if config says default.
  70. if setting.IsWindows && setting.RunUser == "git" {
  71. form.RunUser = user.CurrentUsername()
  72. } else {
  73. form.RunUser = setting.RunUser
  74. }
  75. form.Domain = setting.Domain
  76. form.SSHPort = setting.SSH.Port
  77. form.HTTPPort = setting.HTTPPort
  78. form.AppURL = setting.AppURL
  79. form.LogRootPath = setting.LogRootPath
  80. // E-mail service settings
  81. if setting.MailService != nil {
  82. form.SMTPHost = setting.MailService.Host
  83. form.SMTPFrom = setting.MailService.From
  84. form.SMTPEmail = setting.MailService.User
  85. }
  86. form.RegisterConfirm = setting.Service.RegisterEmailConfirm
  87. form.MailNotify = setting.Service.EnableNotifyMail
  88. // Server and other services settings
  89. form.OfflineMode = setting.OfflineMode
  90. form.DisableGravatar = setting.DisableGravatar
  91. form.EnableFederatedAvatar = setting.EnableFederatedAvatar
  92. form.DisableRegistration = setting.Service.DisableRegistration
  93. form.EnableCaptcha = setting.Service.EnableCaptcha
  94. form.RequireSignInView = setting.Service.RequireSignInView
  95. auth.AssignForm(form, ctx.Data)
  96. ctx.HTML(200, tplInstall)
  97. }
  98. // InstallPost response for submit install items
  99. func InstallPost(ctx *context.Context, form auth.InstallForm) {
  100. var err error
  101. ctx.Data["CurDbOption"] = form.DbType
  102. if ctx.HasError() {
  103. if ctx.HasValue("Err_SMTPEmail") {
  104. ctx.Data["Err_SMTP"] = true
  105. }
  106. if ctx.HasValue("Err_AdminName") ||
  107. ctx.HasValue("Err_AdminPasswd") ||
  108. ctx.HasValue("Err_AdminEmail") {
  109. ctx.Data["Err_Admin"] = true
  110. }
  111. ctx.HTML(200, tplInstall)
  112. return
  113. }
  114. if _, err = exec.LookPath("git"); err != nil {
  115. ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), tplInstall, &form)
  116. return
  117. }
  118. // Pass basic check, now test configuration.
  119. // Test database setting.
  120. dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3", "TiDB": "tidb"}
  121. models.DbCfg.Type = dbTypes[form.DbType]
  122. models.DbCfg.Host = form.DbHost
  123. models.DbCfg.User = form.DbUser
  124. models.DbCfg.Passwd = form.DbPasswd
  125. models.DbCfg.Name = form.DbName
  126. models.DbCfg.SSLMode = form.SSLMode
  127. models.DbCfg.Path = form.DbPath
  128. if (models.DbCfg.Type == "sqlite3" || models.DbCfg.Type == "tidb") &&
  129. len(models.DbCfg.Path) == 0 {
  130. ctx.Data["Err_DbPath"] = true
  131. ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, &form)
  132. return
  133. } else if models.DbCfg.Type == "tidb" &&
  134. strings.ContainsAny(path.Base(models.DbCfg.Path), ".-") {
  135. ctx.Data["Err_DbPath"] = true
  136. ctx.RenderWithErr(ctx.Tr("install.err_invalid_tidb_name"), tplInstall, &form)
  137. return
  138. }
  139. // Set test engine.
  140. var x *xorm.Engine
  141. if err = models.NewTestEngine(x); err != nil {
  142. if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
  143. ctx.Data["Err_DbType"] = true
  144. ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://docs.gitea.io/installation/install_from_binary.html"), tplInstall, &form)
  145. } else {
  146. ctx.Data["Err_DbSetting"] = true
  147. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, &form)
  148. }
  149. return
  150. }
  151. // Test repository root path.
  152. form.RepoRootPath = strings.Replace(form.RepoRootPath, "\\", "/", -1)
  153. if err = os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
  154. ctx.Data["Err_RepoRootPath"] = true
  155. ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), tplInstall, &form)
  156. return
  157. }
  158. // Test log root path.
  159. form.LogRootPath = strings.Replace(form.LogRootPath, "\\", "/", -1)
  160. if err = os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil {
  161. ctx.Data["Err_LogRootPath"] = true
  162. ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), tplInstall, &form)
  163. return
  164. }
  165. currentUser, match := setting.IsRunUserMatchCurrentUser(form.RunUser)
  166. if !match {
  167. ctx.Data["Err_RunUser"] = true
  168. ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, currentUser), tplInstall, &form)
  169. return
  170. }
  171. // Check logic loophole between disable self-registration and no admin account.
  172. if form.DisableRegistration && len(form.AdminName) == 0 {
  173. ctx.Data["Err_Services"] = true
  174. ctx.Data["Err_Admin"] = true
  175. ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), tplInstall, form)
  176. return
  177. }
  178. // Check admin password.
  179. if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 {
  180. ctx.Data["Err_Admin"] = true
  181. ctx.Data["Err_AdminPasswd"] = true
  182. ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), tplInstall, form)
  183. return
  184. }
  185. if form.AdminPasswd != form.AdminConfirmPasswd {
  186. ctx.Data["Err_Admin"] = true
  187. ctx.Data["Err_AdminPasswd"] = true
  188. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplInstall, form)
  189. return
  190. }
  191. if form.AppURL[len(form.AppURL)-1] != '/' {
  192. form.AppURL += "/"
  193. }
  194. // Save settings.
  195. cfg := ini.Empty()
  196. if com.IsFile(setting.CustomConf) {
  197. // Keeps custom settings if there is already something.
  198. if err = cfg.Append(setting.CustomConf); err != nil {
  199. log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err)
  200. }
  201. }
  202. cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type)
  203. cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host)
  204. cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name)
  205. cfg.Section("database").Key("USER").SetValue(models.DbCfg.User)
  206. cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd)
  207. cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode)
  208. cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path)
  209. cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
  210. cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
  211. cfg.Section("").Key("RUN_USER").SetValue(form.RunUser)
  212. cfg.Section("server").Key("DOMAIN").SetValue(form.Domain)
  213. cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort)
  214. cfg.Section("server").Key("ROOT_URL").SetValue(form.AppURL)
  215. if form.SSHPort == 0 {
  216. cfg.Section("server").Key("DISABLE_SSH").SetValue("true")
  217. } else {
  218. cfg.Section("server").Key("DISABLE_SSH").SetValue("false")
  219. cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(form.SSHPort))
  220. }
  221. if len(strings.TrimSpace(form.SMTPHost)) > 0 {
  222. cfg.Section("mailer").Key("ENABLED").SetValue("true")
  223. cfg.Section("mailer").Key("HOST").SetValue(form.SMTPHost)
  224. cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom)
  225. cfg.Section("mailer").Key("USER").SetValue(form.SMTPEmail)
  226. cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd)
  227. } else {
  228. cfg.Section("mailer").Key("ENABLED").SetValue("false")
  229. }
  230. cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(form.RegisterConfirm))
  231. cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(form.MailNotify))
  232. cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(form.OfflineMode))
  233. cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(form.DisableGravatar))
  234. cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(com.ToStr(form.EnableFederatedAvatar))
  235. cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration))
  236. cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha))
  237. cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView))
  238. cfg.Section("").Key("RUN_MODE").SetValue("prod")
  239. cfg.Section("session").Key("PROVIDER").SetValue("file")
  240. cfg.Section("log").Key("MODE").SetValue("file")
  241. cfg.Section("log").Key("LEVEL").SetValue("Info")
  242. cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath)
  243. cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
  244. var secretKey string
  245. if secretKey, err = base.GetRandomString(10); err != nil {
  246. ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form)
  247. return
  248. }
  249. cfg.Section("security").Key("SECRET_KEY").SetValue(secretKey)
  250. err = os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
  251. if err != nil {
  252. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  253. return
  254. }
  255. if err = cfg.SaveTo(setting.CustomConf); err != nil {
  256. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  257. return
  258. }
  259. GlobalInit()
  260. // Create admin account
  261. if len(form.AdminName) > 0 {
  262. u := &models.User{
  263. Name: form.AdminName,
  264. Email: form.AdminEmail,
  265. Passwd: form.AdminPasswd,
  266. IsAdmin: true,
  267. IsActive: true,
  268. }
  269. if err = models.CreateUser(u); err != nil {
  270. if !models.IsErrUserAlreadyExist(err) {
  271. setting.InstallLock = false
  272. ctx.Data["Err_AdminName"] = true
  273. ctx.Data["Err_AdminEmail"] = true
  274. ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), tplInstall, &form)
  275. return
  276. }
  277. log.Info("Admin account already exist")
  278. u, _ = models.GetUserByName(u.Name)
  279. }
  280. // Auto-login for admin
  281. if err = ctx.Session.Set("uid", u.ID); err != nil {
  282. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  283. return
  284. }
  285. if err = ctx.Session.Set("uname", u.Name); err != nil {
  286. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  287. return
  288. }
  289. }
  290. log.Info("First-time run install finished!")
  291. ctx.Flash.Success(ctx.Tr("install.install_success"))
  292. ctx.Redirect(form.AppURL + "user/login")
  293. }