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.

setting.go 13 kB

11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
9 years ago
9 years ago
9 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 user
  5. import (
  6. "errors"
  7. "fmt"
  8. "io/ioutil"
  9. "os"
  10. "strings"
  11. "github.com/Unknwon/com"
  12. "github.com/gogits/gogs/models"
  13. "github.com/gogits/gogs/modules/auth"
  14. "github.com/gogits/gogs/modules/base"
  15. "github.com/gogits/gogs/modules/log"
  16. "github.com/gogits/gogs/modules/mailer"
  17. "github.com/gogits/gogs/modules/middleware"
  18. "github.com/gogits/gogs/modules/setting"
  19. )
  20. const (
  21. SETTINGS_PROFILE base.TplName = "user/settings/profile"
  22. SETTINGS_PASSWORD base.TplName = "user/settings/password"
  23. SETTINGS_EMAILS base.TplName = "user/settings/email"
  24. SETTINGS_SSH_KEYS base.TplName = "user/settings/sshkeys"
  25. SETTINGS_SOCIAL base.TplName = "user/settings/social"
  26. SETTINGS_APPLICATIONS base.TplName = "user/settings/applications"
  27. SETTINGS_DELETE base.TplName = "user/settings/delete"
  28. NOTIFICATION base.TplName = "user/notification"
  29. SECURITY base.TplName = "user/security"
  30. )
  31. func Settings(ctx *middleware.Context) {
  32. ctx.Data["Title"] = ctx.Tr("settings")
  33. ctx.Data["PageIsSettingsProfile"] = true
  34. ctx.HTML(200, SETTINGS_PROFILE)
  35. }
  36. func handleUsernameChange(ctx *middleware.Context, newName string) {
  37. // Non-local users are not allowed to change their username.
  38. if len(newName) == 0 || !ctx.User.IsLocal() {
  39. return
  40. }
  41. // Check if user name has been changed
  42. if ctx.User.LowerName != strings.ToLower(newName) {
  43. if err := models.ChangeUserName(ctx.User, newName); err != nil {
  44. switch {
  45. case models.IsErrUserAlreadyExist(err):
  46. ctx.Flash.Error(ctx.Tr("newName_been_taken"))
  47. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  48. case models.IsErrEmailAlreadyUsed(err):
  49. ctx.Flash.Error(ctx.Tr("form.email_been_used"))
  50. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  51. case models.IsErrNameReserved(err):
  52. ctx.Flash.Error(ctx.Tr("user.newName_reserved"))
  53. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  54. case models.IsErrNamePatternNotAllowed(err):
  55. ctx.Flash.Error(ctx.Tr("user.newName_pattern_not_allowed"))
  56. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  57. default:
  58. ctx.Handle(500, "ChangeUserName", err)
  59. }
  60. return
  61. }
  62. log.Trace("User name changed: %s -> %s", ctx.User.Name, newName)
  63. }
  64. // In case it's just a case change
  65. ctx.User.Name = newName
  66. ctx.User.LowerName = strings.ToLower(newName)
  67. }
  68. func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) {
  69. ctx.Data["Title"] = ctx.Tr("settings")
  70. ctx.Data["PageIsSettingsProfile"] = true
  71. if ctx.HasError() {
  72. ctx.HTML(200, SETTINGS_PROFILE)
  73. return
  74. }
  75. handleUsernameChange(ctx, form.Name)
  76. if ctx.Written() {
  77. return
  78. }
  79. ctx.User.FullName = form.FullName
  80. ctx.User.Email = form.Email
  81. ctx.User.Website = form.Website
  82. ctx.User.Location = form.Location
  83. if len(form.Gravatar) > 0 {
  84. ctx.User.Avatar = base.EncodeMD5(form.Gravatar)
  85. ctx.User.AvatarEmail = form.Gravatar
  86. }
  87. if err := models.UpdateUser(ctx.User); err != nil {
  88. ctx.Handle(500, "UpdateUser", err)
  89. return
  90. }
  91. log.Trace("User settings updated: %s", ctx.User.Name)
  92. ctx.Flash.Success(ctx.Tr("settings.update_profile_success"))
  93. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  94. }
  95. // FIXME: limit size.
  96. func UpdateAvatarSetting(ctx *middleware.Context, form auth.UploadAvatarForm, ctxUser *models.User) error {
  97. ctxUser.UseCustomAvatar = form.Enable
  98. if form.Avatar != nil {
  99. fr, err := form.Avatar.Open()
  100. if err != nil {
  101. return fmt.Errorf("Avatar.Open: %v", err)
  102. }
  103. defer fr.Close()
  104. data, err := ioutil.ReadAll(fr)
  105. if err != nil {
  106. return fmt.Errorf("ioutil.ReadAll: %v", err)
  107. }
  108. if _, ok := base.IsImageFile(data); !ok {
  109. return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image"))
  110. }
  111. if err = ctxUser.UploadAvatar(data); err != nil {
  112. return fmt.Errorf("UploadAvatar: %v", err)
  113. }
  114. } else {
  115. // No avatar is uploaded but setting has been changed to enable,
  116. // generate a random one when needed.
  117. if form.Enable && !com.IsFile(ctxUser.CustomAvatarPath()) {
  118. if err := ctxUser.GenerateRandomAvatar(); err != nil {
  119. log.Error(4, "GenerateRandomAvatar[%d]: %v", ctxUser.Id, err)
  120. }
  121. }
  122. }
  123. if err := models.UpdateUser(ctxUser); err != nil {
  124. return fmt.Errorf("UpdateUser: %v", err)
  125. }
  126. return nil
  127. }
  128. func SettingsAvatar(ctx *middleware.Context, form auth.UploadAvatarForm) {
  129. if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil {
  130. ctx.Flash.Error(err.Error())
  131. } else {
  132. ctx.Flash.Success(ctx.Tr("settings.update_avatar_success"))
  133. }
  134. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  135. }
  136. func SettingsDeleteAvatar(ctx *middleware.Context) {
  137. os.Remove(ctx.User.CustomAvatarPath())
  138. ctx.User.UseCustomAvatar = false
  139. if err := models.UpdateUser(ctx.User); err != nil {
  140. ctx.Flash.Error(fmt.Sprintf("UpdateUser: %v", err))
  141. }
  142. ctx.Redirect(setting.AppSubUrl + "/user/settings")
  143. }
  144. func SettingsPassword(ctx *middleware.Context) {
  145. ctx.Data["Title"] = ctx.Tr("settings")
  146. ctx.Data["PageIsSettingsPassword"] = true
  147. ctx.HTML(200, SETTINGS_PASSWORD)
  148. }
  149. func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) {
  150. ctx.Data["Title"] = ctx.Tr("settings")
  151. ctx.Data["PageIsSettingsPassword"] = true
  152. if ctx.HasError() {
  153. ctx.HTML(200, SETTINGS_PASSWORD)
  154. return
  155. }
  156. if !ctx.User.ValidatePassword(form.OldPassword) {
  157. ctx.Flash.Error(ctx.Tr("settings.password_incorrect"))
  158. } else if form.Password != form.Retype {
  159. ctx.Flash.Error(ctx.Tr("form.password_not_match"))
  160. } else {
  161. ctx.User.Passwd = form.Password
  162. ctx.User.Salt = models.GetUserSalt()
  163. ctx.User.EncodePasswd()
  164. if err := models.UpdateUser(ctx.User); err != nil {
  165. ctx.Handle(500, "UpdateUser", err)
  166. return
  167. }
  168. log.Trace("User password updated: %s", ctx.User.Name)
  169. ctx.Flash.Success(ctx.Tr("settings.change_password_success"))
  170. }
  171. ctx.Redirect(setting.AppSubUrl + "/user/settings/password")
  172. }
  173. func SettingsEmails(ctx *middleware.Context) {
  174. ctx.Data["Title"] = ctx.Tr("settings")
  175. ctx.Data["PageIsSettingsEmails"] = true
  176. emails, err := models.GetEmailAddresses(ctx.User.Id)
  177. if err != nil {
  178. ctx.Handle(500, "GetEmailAddresses", err)
  179. return
  180. }
  181. ctx.Data["Emails"] = emails
  182. ctx.HTML(200, SETTINGS_EMAILS)
  183. }
  184. func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) {
  185. ctx.Data["Title"] = ctx.Tr("settings")
  186. ctx.Data["PageIsSettingsEmails"] = true
  187. // Make emailaddress primary.
  188. if ctx.Query("_method") == "PRIMARY" {
  189. if err := models.MakeEmailPrimary(&models.EmailAddress{ID: ctx.QueryInt64("id")}); err != nil {
  190. ctx.Handle(500, "MakeEmailPrimary", err)
  191. return
  192. }
  193. log.Trace("Email made primary: %s", ctx.User.Name)
  194. ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
  195. return
  196. }
  197. // Add Email address.
  198. emails, err := models.GetEmailAddresses(ctx.User.Id)
  199. if err != nil {
  200. ctx.Handle(500, "GetEmailAddresses", err)
  201. return
  202. }
  203. ctx.Data["Emails"] = emails
  204. if ctx.HasError() {
  205. ctx.HTML(200, SETTINGS_EMAILS)
  206. return
  207. }
  208. e := &models.EmailAddress{
  209. UID: ctx.User.Id,
  210. Email: form.Email,
  211. IsActivated: !setting.Service.RegisterEmailConfirm,
  212. }
  213. if err := models.AddEmailAddress(e); err != nil {
  214. if models.IsErrEmailAlreadyUsed(err) {
  215. ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form)
  216. return
  217. }
  218. ctx.Handle(500, "AddEmailAddress", err)
  219. return
  220. }
  221. // Send confirmation e-mail
  222. if setting.Service.RegisterEmailConfirm {
  223. mailer.SendActivateEmailMail(ctx.Context, ctx.User, e)
  224. if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
  225. log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
  226. }
  227. ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", e.Email, setting.Service.ActiveCodeLives/60))
  228. } else {
  229. ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
  230. }
  231. log.Trace("Email address added: %s", e.Email)
  232. ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
  233. }
  234. func DeleteEmail(ctx *middleware.Context) {
  235. if err := models.DeleteEmailAddress(&models.EmailAddress{ID: ctx.QueryInt64("id")}); err != nil {
  236. ctx.Handle(500, "DeleteEmail", err)
  237. return
  238. }
  239. log.Trace("Email address deleted: %s", ctx.User.Name)
  240. ctx.Flash.Success(ctx.Tr("settings.email_deletion_success"))
  241. ctx.JSON(200, map[string]interface{}{
  242. "redirect": setting.AppSubUrl + "/user/settings/email",
  243. })
  244. }
  245. func SettingsSSHKeys(ctx *middleware.Context) {
  246. ctx.Data["Title"] = ctx.Tr("settings")
  247. ctx.Data["PageIsSettingsSSHKeys"] = true
  248. keys, err := models.ListPublicKeys(ctx.User.Id)
  249. if err != nil {
  250. ctx.Handle(500, "ListPublicKeys", err)
  251. return
  252. }
  253. ctx.Data["Keys"] = keys
  254. ctx.HTML(200, SETTINGS_SSH_KEYS)
  255. }
  256. func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) {
  257. ctx.Data["Title"] = ctx.Tr("settings")
  258. ctx.Data["PageIsSettingsSSHKeys"] = true
  259. keys, err := models.ListPublicKeys(ctx.User.Id)
  260. if err != nil {
  261. ctx.Handle(500, "ListPublicKeys", err)
  262. return
  263. }
  264. ctx.Data["Keys"] = keys
  265. if ctx.HasError() {
  266. ctx.HTML(200, SETTINGS_SSH_KEYS)
  267. return
  268. }
  269. content, err := models.CheckPublicKeyString(form.Content)
  270. if err != nil {
  271. if models.IsErrKeyUnableVerify(err) {
  272. ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
  273. } else {
  274. ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
  275. ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh")
  276. return
  277. }
  278. }
  279. if _, err = models.AddPublicKey(ctx.User.Id, form.Title, content); err != nil {
  280. ctx.Data["HasError"] = true
  281. switch {
  282. case models.IsErrKeyAlreadyExist(err):
  283. ctx.Data["Err_Content"] = true
  284. ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form)
  285. case models.IsErrKeyNameAlreadyUsed(err):
  286. ctx.Data["Err_Title"] = true
  287. ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &form)
  288. default:
  289. ctx.Handle(500, "AddPublicKey", err)
  290. }
  291. return
  292. }
  293. ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
  294. ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh")
  295. }
  296. func DeleteSSHKey(ctx *middleware.Context) {
  297. if err := models.DeletePublicKey(ctx.User, ctx.QueryInt64("id")); err != nil {
  298. ctx.Flash.Error("DeletePublicKey: " + err.Error())
  299. } else {
  300. ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
  301. }
  302. ctx.JSON(200, map[string]interface{}{
  303. "redirect": setting.AppSubUrl + "/user/settings/ssh",
  304. })
  305. }
  306. func SettingsApplications(ctx *middleware.Context) {
  307. ctx.Data["Title"] = ctx.Tr("settings")
  308. ctx.Data["PageIsSettingsApplications"] = true
  309. tokens, err := models.ListAccessTokens(ctx.User.Id)
  310. if err != nil {
  311. ctx.Handle(500, "ListAccessTokens", err)
  312. return
  313. }
  314. ctx.Data["Tokens"] = tokens
  315. ctx.HTML(200, SETTINGS_APPLICATIONS)
  316. }
  317. func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenForm) {
  318. ctx.Data["Title"] = ctx.Tr("settings")
  319. ctx.Data["PageIsSettingsApplications"] = true
  320. if ctx.HasError() {
  321. tokens, err := models.ListAccessTokens(ctx.User.Id)
  322. if err != nil {
  323. ctx.Handle(500, "ListAccessTokens", err)
  324. return
  325. }
  326. ctx.Data["Tokens"] = tokens
  327. ctx.HTML(200, SETTINGS_APPLICATIONS)
  328. return
  329. }
  330. t := &models.AccessToken{
  331. UID: ctx.User.Id,
  332. Name: form.Name,
  333. }
  334. if err := models.NewAccessToken(t); err != nil {
  335. ctx.Handle(500, "NewAccessToken", err)
  336. return
  337. }
  338. ctx.Flash.Success(ctx.Tr("settings.generate_token_succees"))
  339. ctx.Flash.Info(t.Sha1)
  340. ctx.Redirect(setting.AppSubUrl + "/user/settings/applications")
  341. }
  342. func SettingsDeleteApplication(ctx *middleware.Context) {
  343. if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id")); err != nil {
  344. ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
  345. } else {
  346. ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
  347. }
  348. ctx.JSON(200, map[string]interface{}{
  349. "redirect": setting.AppSubUrl + "/user/settings/applications",
  350. })
  351. }
  352. func SettingsDelete(ctx *middleware.Context) {
  353. ctx.Data["Title"] = ctx.Tr("settings")
  354. ctx.Data["PageIsSettingsDelete"] = true
  355. if ctx.Req.Method == "POST" {
  356. if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
  357. if models.IsErrUserNotExist(err) {
  358. ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil)
  359. } else {
  360. ctx.Handle(500, "UserSignIn", err)
  361. }
  362. return
  363. }
  364. if err := models.DeleteUser(ctx.User); err != nil {
  365. switch {
  366. case models.IsErrUserOwnRepos(err):
  367. ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
  368. ctx.Redirect(setting.AppSubUrl + "/user/settings/delete")
  369. case models.IsErrUserHasOrgs(err):
  370. ctx.Flash.Error(ctx.Tr("form.still_has_org"))
  371. ctx.Redirect(setting.AppSubUrl + "/user/settings/delete")
  372. default:
  373. ctx.Handle(500, "DeleteUser", err)
  374. }
  375. } else {
  376. log.Trace("Account deleted: %s", ctx.User.Name)
  377. ctx.Redirect(setting.AppSubUrl + "/")
  378. }
  379. return
  380. }
  381. ctx.HTML(200, SETTINGS_DELETE)
  382. }