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.

418 lines
12 KiB

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