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.

446 lines
12 KiB

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