setting.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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. "bytes"
  7. "encoding/base64"
  8. "fmt"
  9. "html/template"
  10. "image/png"
  11. "io"
  12. "github.com/pkg/errors"
  13. "github.com/pquerna/otp"
  14. "github.com/pquerna/otp/totp"
  15. log "unknwon.dev/clog/v2"
  16. "gogs.io/gogs/internal/auth"
  17. "gogs.io/gogs/internal/conf"
  18. "gogs.io/gogs/internal/context"
  19. "gogs.io/gogs/internal/cryptoutil"
  20. "gogs.io/gogs/internal/db"
  21. "gogs.io/gogs/internal/email"
  22. "gogs.io/gogs/internal/form"
  23. "gogs.io/gogs/internal/tool"
  24. "gogs.io/gogs/internal/userutil"
  25. )
  26. const (
  27. SETTINGS_PROFILE = "user/settings/profile"
  28. SETTINGS_AVATAR = "user/settings/avatar"
  29. SETTINGS_PASSWORD = "user/settings/password"
  30. SETTINGS_EMAILS = "user/settings/email"
  31. SETTINGS_SSH_KEYS = "user/settings/sshkeys"
  32. SETTINGS_SECURITY = "user/settings/security"
  33. SETTINGS_TWO_FACTOR_ENABLE = "user/settings/two_factor_enable"
  34. SETTINGS_TWO_FACTOR_RECOVERY_CODES = "user/settings/two_factor_recovery_codes"
  35. SETTINGS_REPOSITORIES = "user/settings/repositories"
  36. SETTINGS_ORGANIZATIONS = "user/settings/organizations"
  37. SETTINGS_APPLICATIONS = "user/settings/applications"
  38. SETTINGS_DELETE = "user/settings/delete"
  39. NOTIFICATION = "user/notification"
  40. )
  41. func Settings(c *context.Context) {
  42. c.Title("settings.profile")
  43. c.PageIs("SettingsProfile")
  44. c.Data["origin_name"] = c.User.Name
  45. c.Data["name"] = c.User.Name
  46. c.Data["full_name"] = c.User.FullName
  47. c.Data["email"] = c.User.Email
  48. c.Data["website"] = c.User.Website
  49. c.Data["location"] = c.User.Location
  50. c.Success(SETTINGS_PROFILE)
  51. }
  52. func SettingsPost(c *context.Context, f form.UpdateProfile) {
  53. c.Title("settings.profile")
  54. c.PageIs("SettingsProfile")
  55. c.Data["origin_name"] = c.User.Name
  56. if c.HasError() {
  57. c.Success(SETTINGS_PROFILE)
  58. return
  59. }
  60. // Non-local users are not allowed to change their username
  61. if c.User.IsLocal() {
  62. // Check if the username (including cases) had been changed
  63. if c.User.Name != f.Name {
  64. err := db.Users.ChangeUsername(c.Req.Context(), c.User.ID, f.Name)
  65. if err != nil {
  66. c.FormErr("Name")
  67. var msg string
  68. switch {
  69. case db.IsErrUserAlreadyExist(errors.Cause(err)):
  70. msg = c.Tr("form.username_been_taken")
  71. case db.IsErrNameNotAllowed(errors.Cause(err)):
  72. msg = c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value())
  73. default:
  74. c.Error(err, "change user name")
  75. return
  76. }
  77. c.RenderWithErr(msg, SETTINGS_PROFILE, &f)
  78. return
  79. }
  80. log.Trace("Username changed: %s -> %s", c.User.Name, f.Name)
  81. }
  82. }
  83. err := db.Users.Update(
  84. c.Req.Context(),
  85. c.User.ID,
  86. db.UpdateUserOptions{
  87. FullName: &f.FullName,
  88. Website: &f.Website,
  89. Location: &f.Location,
  90. },
  91. )
  92. if err != nil {
  93. c.Error(err, "update user")
  94. return
  95. }
  96. c.Flash.Success(c.Tr("settings.update_profile_success"))
  97. c.RedirectSubpath("/user/settings")
  98. }
  99. // FIXME: limit upload size
  100. func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxUser *db.User) error {
  101. if f.Source == form.AvatarLookup && f.Gravatar != "" {
  102. avatar := cryptoutil.MD5(f.Gravatar)
  103. err := db.Users.Update(
  104. c.Req.Context(),
  105. ctxUser.ID,
  106. db.UpdateUserOptions{
  107. Avatar: &avatar,
  108. AvatarEmail: &f.Gravatar,
  109. },
  110. )
  111. if err != nil {
  112. return errors.Wrap(err, "update user")
  113. }
  114. err = db.Users.DeleteCustomAvatar(c.Req.Context(), c.User.ID)
  115. if err != nil {
  116. return errors.Wrap(err, "delete custom avatar")
  117. }
  118. return nil
  119. }
  120. if f.Avatar != nil && f.Avatar.Filename != "" {
  121. r, err := f.Avatar.Open()
  122. if err != nil {
  123. return fmt.Errorf("open avatar reader: %v", err)
  124. }
  125. defer func() { _ = r.Close() }()
  126. data, err := io.ReadAll(r)
  127. if err != nil {
  128. return fmt.Errorf("read avatar content: %v", err)
  129. }
  130. if !tool.IsImageFile(data) {
  131. return errors.New(c.Tr("settings.uploaded_avatar_not_a_image"))
  132. }
  133. err = db.Users.UseCustomAvatar(c.Req.Context(), ctxUser.ID, data)
  134. if err != nil {
  135. return errors.Wrap(err, "save avatar")
  136. }
  137. return nil
  138. }
  139. return nil
  140. }
  141. func SettingsAvatar(c *context.Context) {
  142. c.Title("settings.avatar")
  143. c.PageIs("SettingsAvatar")
  144. c.Success(SETTINGS_AVATAR)
  145. }
  146. func SettingsAvatarPost(c *context.Context, f form.Avatar) {
  147. if err := UpdateAvatarSetting(c, f, c.User); err != nil {
  148. c.Flash.Error(err.Error())
  149. } else {
  150. c.Flash.Success(c.Tr("settings.update_avatar_success"))
  151. }
  152. c.RedirectSubpath("/user/settings/avatar")
  153. }
  154. func SettingsDeleteAvatar(c *context.Context) {
  155. err := db.Users.DeleteCustomAvatar(c.Req.Context(), c.User.ID)
  156. if err != nil {
  157. c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err))
  158. }
  159. c.RedirectSubpath("/user/settings/avatar")
  160. }
  161. func SettingsPassword(c *context.Context) {
  162. c.Title("settings.password")
  163. c.PageIs("SettingsPassword")
  164. c.Success(SETTINGS_PASSWORD)
  165. }
  166. func SettingsPasswordPost(c *context.Context, f form.ChangePassword) {
  167. c.Title("settings.password")
  168. c.PageIs("SettingsPassword")
  169. if c.HasError() {
  170. c.Success(SETTINGS_PASSWORD)
  171. return
  172. }
  173. if !userutil.ValidatePassword(c.User.Password, c.User.Salt, f.OldPassword) {
  174. c.Flash.Error(c.Tr("settings.password_incorrect"))
  175. } else if f.Password != f.Retype {
  176. c.Flash.Error(c.Tr("form.password_not_match"))
  177. } else {
  178. err := db.Users.Update(
  179. c.Req.Context(),
  180. c.User.ID,
  181. db.UpdateUserOptions{
  182. Password: &f.Password,
  183. },
  184. )
  185. if err != nil {
  186. c.Errorf(err, "update user")
  187. return
  188. }
  189. c.Flash.Success(c.Tr("settings.change_password_success"))
  190. }
  191. c.RedirectSubpath("/user/settings/password")
  192. }
  193. func SettingsEmails(c *context.Context) {
  194. c.Title("settings.emails")
  195. c.PageIs("SettingsEmails")
  196. emails, err := db.Users.ListEmails(c.Req.Context(), c.User.ID)
  197. if err != nil {
  198. c.Errorf(err, "get email addresses")
  199. return
  200. }
  201. c.Data["Emails"] = emails
  202. c.Success(SETTINGS_EMAILS)
  203. }
  204. func SettingsEmailPost(c *context.Context, f form.AddEmail) {
  205. c.Title("settings.emails")
  206. c.PageIs("SettingsEmails")
  207. if c.Query("_method") == "PRIMARY" {
  208. err := db.Users.MarkEmailPrimary(c.Req.Context(), c.User.ID, c.Query("email"))
  209. if err != nil {
  210. c.Errorf(err, "make email primary")
  211. return
  212. }
  213. c.RedirectSubpath("/user/settings/email")
  214. return
  215. }
  216. // Add Email address.
  217. emails, err := db.Users.ListEmails(c.Req.Context(), c.User.ID)
  218. if err != nil {
  219. c.Errorf(err, "get email addresses")
  220. return
  221. }
  222. c.Data["Emails"] = emails
  223. if c.HasError() {
  224. c.Success(SETTINGS_EMAILS)
  225. return
  226. }
  227. err = db.Users.AddEmail(c.Req.Context(), c.User.ID, f.Email, !conf.Auth.RequireEmailConfirmation)
  228. if err != nil {
  229. if db.IsErrEmailAlreadyUsed(err) {
  230. c.RenderWithErr(c.Tr("form.email_been_used"), SETTINGS_EMAILS, &f)
  231. } else {
  232. c.Errorf(err, "add email address")
  233. }
  234. return
  235. }
  236. // Send confirmation email
  237. if conf.Auth.RequireEmailConfirmation {
  238. email.SendActivateEmailMail(c.Context, db.NewMailerUser(c.User), f.Email)
  239. if err := c.Cache.Put("MailResendLimit_"+c.User.LowerName, c.User.LowerName, 180); err != nil {
  240. log.Error("Set cache 'MailResendLimit' failed: %v", err)
  241. }
  242. c.Flash.Info(c.Tr("settings.add_email_confirmation_sent", f.Email, conf.Auth.ActivateCodeLives/60))
  243. } else {
  244. c.Flash.Success(c.Tr("settings.add_email_success"))
  245. }
  246. c.RedirectSubpath("/user/settings/email")
  247. }
  248. func DeleteEmail(c *context.Context) {
  249. email := c.Query("id") // The "id" here is the actual email address
  250. if c.User.Email == email {
  251. c.Flash.Error(c.Tr("settings.email_deletion_primary"))
  252. c.JSONSuccess(map[string]any{
  253. "redirect": conf.Server.Subpath + "/user/settings/email",
  254. })
  255. return
  256. }
  257. err := db.Users.DeleteEmail(c.Req.Context(), c.User.ID, email)
  258. if err != nil {
  259. c.Error(err, "delete email address")
  260. return
  261. }
  262. c.Flash.Success(c.Tr("settings.email_deletion_success"))
  263. c.JSONSuccess(map[string]any{
  264. "redirect": conf.Server.Subpath + "/user/settings/email",
  265. })
  266. }
  267. func SettingsSSHKeys(c *context.Context) {
  268. c.Title("settings.ssh_keys")
  269. c.PageIs("SettingsSSHKeys")
  270. keys, err := db.ListPublicKeys(c.User.ID)
  271. if err != nil {
  272. c.Errorf(err, "list public keys")
  273. return
  274. }
  275. c.Data["Keys"] = keys
  276. c.Success(SETTINGS_SSH_KEYS)
  277. }
  278. func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) {
  279. c.Title("settings.ssh_keys")
  280. c.PageIs("SettingsSSHKeys")
  281. keys, err := db.ListPublicKeys(c.User.ID)
  282. if err != nil {
  283. c.Errorf(err, "list public keys")
  284. return
  285. }
  286. c.Data["Keys"] = keys
  287. if c.HasError() {
  288. c.Success(SETTINGS_SSH_KEYS)
  289. return
  290. }
  291. content, err := db.CheckPublicKeyString(f.Content)
  292. if err != nil {
  293. if db.IsErrKeyUnableVerify(err) {
  294. c.Flash.Info(c.Tr("form.unable_verify_ssh_key"))
  295. } else {
  296. c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error()))
  297. c.RedirectSubpath("/user/settings/ssh")
  298. return
  299. }
  300. }
  301. if _, err = db.AddPublicKey(c.User.ID, f.Title, content); err != nil {
  302. c.Data["HasError"] = true
  303. switch {
  304. case db.IsErrKeyAlreadyExist(err):
  305. c.FormErr("Content")
  306. c.RenderWithErr(c.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &f)
  307. case db.IsErrKeyNameAlreadyUsed(err):
  308. c.FormErr("Title")
  309. c.RenderWithErr(c.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &f)
  310. default:
  311. c.Errorf(err, "add public key")
  312. }
  313. return
  314. }
  315. c.Flash.Success(c.Tr("settings.add_key_success", f.Title))
  316. c.RedirectSubpath("/user/settings/ssh")
  317. }
  318. func DeleteSSHKey(c *context.Context) {
  319. if err := db.DeletePublicKey(c.User, c.QueryInt64("id")); err != nil {
  320. c.Flash.Error("DeletePublicKey: " + err.Error())
  321. } else {
  322. c.Flash.Success(c.Tr("settings.ssh_key_deletion_success"))
  323. }
  324. c.JSONSuccess(map[string]any{
  325. "redirect": conf.Server.Subpath + "/user/settings/ssh",
  326. })
  327. }
  328. func SettingsSecurity(c *context.Context) {
  329. c.Title("settings.security")
  330. c.PageIs("SettingsSecurity")
  331. t, err := db.TwoFactors.GetByUserID(c.Req.Context(), c.UserID())
  332. if err != nil && !db.IsErrTwoFactorNotFound(err) {
  333. c.Errorf(err, "get two factor by user ID")
  334. return
  335. }
  336. c.Data["TwoFactor"] = t
  337. c.Success(SETTINGS_SECURITY)
  338. }
  339. func SettingsTwoFactorEnable(c *context.Context) {
  340. if db.TwoFactors.IsEnabled(c.Req.Context(), c.User.ID) {
  341. c.NotFound()
  342. return
  343. }
  344. c.Title("settings.two_factor_enable_title")
  345. c.PageIs("SettingsSecurity")
  346. var key *otp.Key
  347. var err error
  348. keyURL := c.Session.Get("twoFactorURL")
  349. if keyURL != nil {
  350. key, _ = otp.NewKeyFromURL(keyURL.(string))
  351. }
  352. if key == nil {
  353. key, err = totp.Generate(totp.GenerateOpts{
  354. Issuer: conf.App.BrandName,
  355. AccountName: c.User.Email,
  356. })
  357. if err != nil {
  358. c.Errorf(err, "generate TOTP")
  359. return
  360. }
  361. }
  362. c.Data["TwoFactorSecret"] = key.Secret()
  363. img, err := key.Image(240, 240)
  364. if err != nil {
  365. c.Errorf(err, "generate image")
  366. return
  367. }
  368. var buf bytes.Buffer
  369. if err = png.Encode(&buf, img); err != nil {
  370. c.Errorf(err, "encode image")
  371. return
  372. }
  373. c.Data["QRCode"] = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()))
  374. _ = c.Session.Set("twoFactorSecret", c.Data["TwoFactorSecret"])
  375. _ = c.Session.Set("twoFactorURL", key.String())
  376. c.Success(SETTINGS_TWO_FACTOR_ENABLE)
  377. }
  378. func SettingsTwoFactorEnablePost(c *context.Context) {
  379. secret, ok := c.Session.Get("twoFactorSecret").(string)
  380. if !ok {
  381. c.NotFound()
  382. return
  383. }
  384. if !totp.Validate(c.Query("passcode"), secret) {
  385. c.Flash.Error(c.Tr("settings.two_factor_invalid_passcode"))
  386. c.RedirectSubpath("/user/settings/security/two_factor_enable")
  387. return
  388. }
  389. if err := db.TwoFactors.Create(c.Req.Context(), c.UserID(), conf.Security.SecretKey, secret); err != nil {
  390. c.Flash.Error(c.Tr("settings.two_factor_enable_error", err))
  391. c.RedirectSubpath("/user/settings/security/two_factor_enable")
  392. return
  393. }
  394. _ = c.Session.Delete("twoFactorSecret")
  395. _ = c.Session.Delete("twoFactorURL")
  396. c.Flash.Success(c.Tr("settings.two_factor_enable_success"))
  397. c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes")
  398. }
  399. func SettingsTwoFactorRecoveryCodes(c *context.Context) {
  400. if !db.TwoFactors.IsEnabled(c.Req.Context(), c.User.ID) {
  401. c.NotFound()
  402. return
  403. }
  404. c.Title("settings.two_factor_recovery_codes_title")
  405. c.PageIs("SettingsSecurity")
  406. recoveryCodes, err := db.GetRecoveryCodesByUserID(c.UserID())
  407. if err != nil {
  408. c.Errorf(err, "get recovery codes by user ID")
  409. return
  410. }
  411. c.Data["RecoveryCodes"] = recoveryCodes
  412. c.Success(SETTINGS_TWO_FACTOR_RECOVERY_CODES)
  413. }
  414. func SettingsTwoFactorRecoveryCodesPost(c *context.Context) {
  415. if !db.TwoFactors.IsEnabled(c.Req.Context(), c.User.ID) {
  416. c.NotFound()
  417. return
  418. }
  419. if err := db.RegenerateRecoveryCodes(c.UserID()); err != nil {
  420. c.Flash.Error(c.Tr("settings.two_factor_regenerate_recovery_codes_error", err))
  421. } else {
  422. c.Flash.Success(c.Tr("settings.two_factor_regenerate_recovery_codes_success"))
  423. }
  424. c.RedirectSubpath("/user/settings/security/two_factor_recovery_codes")
  425. }
  426. func SettingsTwoFactorDisable(c *context.Context) {
  427. if !db.TwoFactors.IsEnabled(c.Req.Context(), c.User.ID) {
  428. c.NotFound()
  429. return
  430. }
  431. if err := db.DeleteTwoFactor(c.UserID()); err != nil {
  432. c.Errorf(err, "delete two factor")
  433. return
  434. }
  435. c.Flash.Success(c.Tr("settings.two_factor_disable_success"))
  436. c.JSONSuccess(map[string]any{
  437. "redirect": conf.Server.Subpath + "/user/settings/security",
  438. })
  439. }
  440. func SettingsRepos(c *context.Context) {
  441. c.Title("settings.repos")
  442. c.PageIs("SettingsRepositories")
  443. repos, err := db.GetUserAndCollaborativeRepositories(c.User.ID)
  444. if err != nil {
  445. c.Errorf(err, "get user and collaborative repositories")
  446. return
  447. }
  448. if err = db.RepositoryList(repos).LoadAttributes(); err != nil {
  449. c.Errorf(err, "load attributes")
  450. return
  451. }
  452. c.Data["Repos"] = repos
  453. c.Success(SETTINGS_REPOSITORIES)
  454. }
  455. func SettingsLeaveRepo(c *context.Context) {
  456. repo, err := db.GetRepositoryByID(c.QueryInt64("id"))
  457. if err != nil {
  458. c.NotFoundOrError(err, "get repository by ID")
  459. return
  460. }
  461. if err = repo.DeleteCollaboration(c.User.ID); err != nil {
  462. c.Errorf(err, "delete collaboration")
  463. return
  464. }
  465. c.Flash.Success(c.Tr("settings.repos.leave_success", repo.FullName()))
  466. c.JSONSuccess(map[string]any{
  467. "redirect": conf.Server.Subpath + "/user/settings/repositories",
  468. })
  469. }
  470. func SettingsOrganizations(c *context.Context) {
  471. c.Title("settings.orgs")
  472. c.PageIs("SettingsOrganizations")
  473. orgs, err := db.GetOrgsByUserID(c.User.ID, true)
  474. if err != nil {
  475. c.Errorf(err, "get organizations by user ID")
  476. return
  477. }
  478. c.Data["Orgs"] = orgs
  479. c.Success(SETTINGS_ORGANIZATIONS)
  480. }
  481. func SettingsLeaveOrganization(c *context.Context) {
  482. if err := db.RemoveOrgUser(c.QueryInt64("id"), c.User.ID); err != nil {
  483. if db.IsErrLastOrgOwner(err) {
  484. c.Flash.Error(c.Tr("form.last_org_owner"))
  485. } else {
  486. c.Errorf(err, "remove organization user")
  487. return
  488. }
  489. }
  490. c.JSONSuccess(map[string]any{
  491. "redirect": conf.Server.Subpath + "/user/settings/organizations",
  492. })
  493. }
  494. func SettingsApplications(c *context.Context) {
  495. c.Title("settings.applications")
  496. c.PageIs("SettingsApplications")
  497. tokens, err := db.AccessTokens.List(c.Req.Context(), c.User.ID)
  498. if err != nil {
  499. c.Errorf(err, "list access tokens")
  500. return
  501. }
  502. c.Data["Tokens"] = tokens
  503. c.Success(SETTINGS_APPLICATIONS)
  504. }
  505. func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) {
  506. c.Title("settings.applications")
  507. c.PageIs("SettingsApplications")
  508. if c.HasError() {
  509. tokens, err := db.AccessTokens.List(c.Req.Context(), c.User.ID)
  510. if err != nil {
  511. c.Errorf(err, "list access tokens")
  512. return
  513. }
  514. c.Data["Tokens"] = tokens
  515. c.Success(SETTINGS_APPLICATIONS)
  516. return
  517. }
  518. t, err := db.AccessTokens.Create(c.Req.Context(), c.User.ID, f.Name)
  519. if err != nil {
  520. if db.IsErrAccessTokenAlreadyExist(err) {
  521. c.Flash.Error(c.Tr("settings.token_name_exists"))
  522. c.RedirectSubpath("/user/settings/applications")
  523. } else {
  524. c.Errorf(err, "new access token")
  525. }
  526. return
  527. }
  528. c.Flash.Success(c.Tr("settings.generate_token_succees"))
  529. c.Flash.Info(t.Sha1)
  530. c.RedirectSubpath("/user/settings/applications")
  531. }
  532. func SettingsDeleteApplication(c *context.Context) {
  533. if err := db.AccessTokens.DeleteByID(c.Req.Context(), c.User.ID, c.QueryInt64("id")); err != nil {
  534. c.Flash.Error("DeleteAccessTokenByID: " + err.Error())
  535. } else {
  536. c.Flash.Success(c.Tr("settings.delete_token_success"))
  537. }
  538. c.JSONSuccess(map[string]any{
  539. "redirect": conf.Server.Subpath + "/user/settings/applications",
  540. })
  541. }
  542. func SettingsDelete(c *context.Context) {
  543. c.Title("settings.delete")
  544. c.PageIs("SettingsDelete")
  545. if c.Req.Method == "POST" {
  546. if _, err := db.Users.Authenticate(c.Req.Context(), c.User.Name, c.Query("password"), c.User.LoginSource); err != nil {
  547. if auth.IsErrBadCredentials(err) {
  548. c.RenderWithErr(c.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil)
  549. } else {
  550. c.Errorf(err, "authenticate user")
  551. }
  552. return
  553. }
  554. if err := db.Users.DeleteByID(c.Req.Context(), c.User.ID, false); err != nil {
  555. switch {
  556. case db.IsErrUserOwnRepos(err):
  557. c.Flash.Error(c.Tr("form.still_own_repo"))
  558. c.Redirect(conf.Server.Subpath + "/user/settings/delete")
  559. case db.IsErrUserHasOrgs(err):
  560. c.Flash.Error(c.Tr("form.still_has_org"))
  561. c.Redirect(conf.Server.Subpath + "/user/settings/delete")
  562. default:
  563. c.Errorf(err, "delete user")
  564. }
  565. } else {
  566. log.Trace("Account deleted: %s", c.User.Name)
  567. c.Redirect(conf.Server.Subpath + "/")
  568. }
  569. return
  570. }
  571. c.Success(SETTINGS_DELETE)
  572. }