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.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package user
  6. import (
  7. "errors"
  8. "fmt"
  9. "net/http"
  10. "net/url"
  11. "strings"
  12. "code.gitea.io/gitea/models"
  13. "code.gitea.io/gitea/modules/auth"
  14. "code.gitea.io/gitea/modules/auth/oauth2"
  15. "code.gitea.io/gitea/modules/base"
  16. "code.gitea.io/gitea/modules/context"
  17. "code.gitea.io/gitea/modules/log"
  18. "code.gitea.io/gitea/modules/recaptcha"
  19. "code.gitea.io/gitea/modules/setting"
  20. "code.gitea.io/gitea/modules/util"
  21. "github.com/go-macaron/captcha"
  22. "github.com/markbates/goth"
  23. "github.com/tstranex/u2f"
  24. )
  25. const (
  26. // tplSignIn template for sign in page
  27. tplSignIn base.TplName = "user/auth/signin"
  28. // tplSignUp template path for sign up page
  29. tplSignUp base.TplName = "user/auth/signup"
  30. // TplActivate template path for activate user
  31. TplActivate base.TplName = "user/auth/activate"
  32. tplForgotPassword base.TplName = "user/auth/forgot_passwd"
  33. tplResetPassword base.TplName = "user/auth/reset_passwd"
  34. tplTwofa base.TplName = "user/auth/twofa"
  35. tplTwofaScratch base.TplName = "user/auth/twofa_scratch"
  36. tplLinkAccount base.TplName = "user/auth/link_account"
  37. tplU2F base.TplName = "user/auth/u2f"
  38. )
  39. // AutoSignIn reads cookie and try to auto-login.
  40. func AutoSignIn(ctx *context.Context) (bool, error) {
  41. if !models.HasEngine {
  42. return false, nil
  43. }
  44. uname := ctx.GetCookie(setting.CookieUserName)
  45. if len(uname) == 0 {
  46. return false, nil
  47. }
  48. isSucceed := false
  49. defer func() {
  50. if !isSucceed {
  51. log.Trace("auto-login cookie cleared: %s", uname)
  52. ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL)
  53. ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL)
  54. }
  55. }()
  56. u, err := models.GetUserByName(uname)
  57. if err != nil {
  58. if !models.IsErrUserNotExist(err) {
  59. return false, fmt.Errorf("GetUserByName: %v", err)
  60. }
  61. return false, nil
  62. }
  63. if val, _ := ctx.GetSuperSecureCookie(
  64. base.EncodeMD5(u.Rands+u.Passwd), setting.CookieRememberName); val != u.Name {
  65. return false, nil
  66. }
  67. isSucceed = true
  68. ctx.Session.Set("uid", u.ID)
  69. ctx.Session.Set("uname", u.Name)
  70. ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL)
  71. return true, nil
  72. }
  73. func checkAutoLogin(ctx *context.Context) bool {
  74. // Check auto-login.
  75. isSucceed, err := AutoSignIn(ctx)
  76. if err != nil {
  77. ctx.ServerError("AutoSignIn", err)
  78. return true
  79. }
  80. redirectTo := ctx.Query("redirect_to")
  81. if len(redirectTo) > 0 {
  82. ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubURL)
  83. } else {
  84. redirectTo, _ = url.QueryUnescape(ctx.GetCookie("redirect_to"))
  85. }
  86. if isSucceed {
  87. ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
  88. ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL))
  89. return true
  90. }
  91. return false
  92. }
  93. // SignIn render sign in page
  94. func SignIn(ctx *context.Context) {
  95. ctx.Data["Title"] = ctx.Tr("sign_in")
  96. // Check auto-login.
  97. if checkAutoLogin(ctx) {
  98. return
  99. }
  100. orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers()
  101. if err != nil {
  102. ctx.ServerError("UserSignIn", err)
  103. return
  104. }
  105. ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
  106. ctx.Data["OAuth2Providers"] = oauth2Providers
  107. ctx.Data["Title"] = ctx.Tr("sign_in")
  108. ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
  109. ctx.Data["PageIsSignIn"] = true
  110. ctx.Data["PageIsLogin"] = true
  111. ctx.HTML(200, tplSignIn)
  112. }
  113. // SignInPost response for sign in request
  114. func SignInPost(ctx *context.Context, form auth.SignInForm) {
  115. ctx.Data["Title"] = ctx.Tr("sign_in")
  116. orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers()
  117. if err != nil {
  118. ctx.ServerError("UserSignIn", err)
  119. return
  120. }
  121. ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
  122. ctx.Data["OAuth2Providers"] = oauth2Providers
  123. ctx.Data["Title"] = ctx.Tr("sign_in")
  124. ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
  125. ctx.Data["PageIsSignIn"] = true
  126. ctx.Data["PageIsLogin"] = true
  127. if ctx.HasError() {
  128. ctx.HTML(200, tplSignIn)
  129. return
  130. }
  131. u, err := models.UserSignIn(form.UserName, form.Password)
  132. if err != nil {
  133. if models.IsErrUserNotExist(err) {
  134. ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
  135. log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
  136. } else if models.IsErrEmailAlreadyUsed(err) {
  137. ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
  138. log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
  139. } else {
  140. ctx.ServerError("UserSignIn", err)
  141. }
  142. return
  143. }
  144. // If this user is enrolled in 2FA, we can't sign the user in just yet.
  145. // Instead, redirect them to the 2FA authentication page.
  146. _, err = models.GetTwoFactorByUID(u.ID)
  147. if err != nil {
  148. if models.IsErrTwoFactorNotEnrolled(err) {
  149. handleSignIn(ctx, u, form.Remember)
  150. } else {
  151. ctx.ServerError("UserSignIn", err)
  152. }
  153. return
  154. }
  155. // User needs to use 2FA, save data and redirect to 2FA page.
  156. ctx.Session.Set("twofaUid", u.ID)
  157. ctx.Session.Set("twofaRemember", form.Remember)
  158. regs, err := models.GetU2FRegistrationsByUID(u.ID)
  159. if err == nil && len(regs) > 0 {
  160. ctx.Redirect(setting.AppSubURL + "/user/u2f")
  161. return
  162. }
  163. ctx.Redirect(setting.AppSubURL + "/user/two_factor")
  164. }
  165. // TwoFactor shows the user a two-factor authentication page.
  166. func TwoFactor(ctx *context.Context) {
  167. ctx.Data["Title"] = ctx.Tr("twofa")
  168. // Check auto-login.
  169. if checkAutoLogin(ctx) {
  170. return
  171. }
  172. // Ensure user is in a 2FA session.
  173. if ctx.Session.Get("twofaUid") == nil {
  174. ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
  175. return
  176. }
  177. ctx.HTML(200, tplTwofa)
  178. }
  179. // TwoFactorPost validates a user's two-factor authentication token.
  180. func TwoFactorPost(ctx *context.Context, form auth.TwoFactorAuthForm) {
  181. ctx.Data["Title"] = ctx.Tr("twofa")
  182. // Ensure user is in a 2FA session.
  183. idSess := ctx.Session.Get("twofaUid")
  184. if idSess == nil {
  185. ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
  186. return
  187. }
  188. id := idSess.(int64)
  189. twofa, err := models.GetTwoFactorByUID(id)
  190. if err != nil {
  191. ctx.ServerError("UserSignIn", err)
  192. return
  193. }
  194. // Validate the passcode with the stored TOTP secret.
  195. ok, err := twofa.ValidateTOTP(form.Passcode)
  196. if err != nil {
  197. ctx.ServerError("UserSignIn", err)
  198. return
  199. }
  200. if ok && twofa.LastUsedPasscode != form.Passcode {
  201. remember := ctx.Session.Get("twofaRemember").(bool)
  202. u, err := models.GetUserByID(id)
  203. if err != nil {
  204. ctx.ServerError("UserSignIn", err)
  205. return
  206. }
  207. if ctx.Session.Get("linkAccount") != nil {
  208. gothUser := ctx.Session.Get("linkAccountGothUser")
  209. if gothUser == nil {
  210. ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
  211. return
  212. }
  213. err = models.LinkAccountToUser(u, gothUser.(goth.User))
  214. if err != nil {
  215. ctx.ServerError("UserSignIn", err)
  216. return
  217. }
  218. }
  219. twofa.LastUsedPasscode = form.Passcode
  220. if err = models.UpdateTwoFactor(twofa); err != nil {
  221. ctx.ServerError("UserSignIn", err)
  222. return
  223. }
  224. handleSignIn(ctx, u, remember)
  225. return
  226. }
  227. ctx.RenderWithErr(ctx.Tr("auth.twofa_passcode_incorrect"), tplTwofa, auth.TwoFactorAuthForm{})
  228. }
  229. // TwoFactorScratch shows the scratch code form for two-factor authentication.
  230. func TwoFactorScratch(ctx *context.Context) {
  231. ctx.Data["Title"] = ctx.Tr("twofa_scratch")
  232. // Check auto-login.
  233. if checkAutoLogin(ctx) {
  234. return
  235. }
  236. // Ensure user is in a 2FA session.
  237. if ctx.Session.Get("twofaUid") == nil {
  238. ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
  239. return
  240. }
  241. ctx.HTML(200, tplTwofaScratch)
  242. }
  243. // TwoFactorScratchPost validates and invalidates a user's two-factor scratch token.
  244. func TwoFactorScratchPost(ctx *context.Context, form auth.TwoFactorScratchAuthForm) {
  245. ctx.Data["Title"] = ctx.Tr("twofa_scratch")
  246. // Ensure user is in a 2FA session.
  247. idSess := ctx.Session.Get("twofaUid")
  248. if idSess == nil {
  249. ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
  250. return
  251. }
  252. id := idSess.(int64)
  253. twofa, err := models.GetTwoFactorByUID(id)
  254. if err != nil {
  255. ctx.ServerError("UserSignIn", err)
  256. return
  257. }
  258. // Validate the passcode with the stored TOTP secret.
  259. if twofa.VerifyScratchToken(form.Token) {
  260. // Invalidate the scratch token.
  261. _, err = twofa.GenerateScratchToken()
  262. if err != nil {
  263. ctx.ServerError("UserSignIn", err)
  264. return
  265. }
  266. if err = models.UpdateTwoFactor(twofa); err != nil {
  267. ctx.ServerError("UserSignIn", err)
  268. return
  269. }
  270. remember := ctx.Session.Get("twofaRemember").(bool)
  271. u, err := models.GetUserByID(id)
  272. if err != nil {
  273. ctx.ServerError("UserSignIn", err)
  274. return
  275. }
  276. handleSignInFull(ctx, u, remember, false)
  277. ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
  278. ctx.Redirect(setting.AppSubURL + "/user/settings/security")
  279. return
  280. }
  281. ctx.RenderWithErr(ctx.Tr("auth.twofa_scratch_token_incorrect"), tplTwofaScratch, auth.TwoFactorScratchAuthForm{})
  282. }
  283. // U2F shows the U2F login page
  284. func U2F(ctx *context.Context) {
  285. ctx.Data["Title"] = ctx.Tr("twofa")
  286. ctx.Data["RequireU2F"] = true
  287. // Check auto-login.
  288. if checkAutoLogin(ctx) {
  289. return
  290. }
  291. // Ensure user is in a 2FA session.
  292. if ctx.Session.Get("twofaUid") == nil {
  293. ctx.ServerError("UserSignIn", errors.New("not in U2F session"))
  294. return
  295. }
  296. ctx.HTML(200, tplU2F)
  297. }
  298. // U2FChallenge submits a sign challenge to the browser
  299. func U2FChallenge(ctx *context.Context) {
  300. // Ensure user is in a U2F session.
  301. idSess := ctx.Session.Get("twofaUid")
  302. if idSess == nil {
  303. ctx.ServerError("UserSignIn", errors.New("not in U2F session"))
  304. return
  305. }
  306. id := idSess.(int64)
  307. regs, err := models.GetU2FRegistrationsByUID(id)
  308. if err != nil {
  309. ctx.ServerError("UserSignIn", err)
  310. return
  311. }
  312. if len(regs) == 0 {
  313. ctx.ServerError("UserSignIn", errors.New("no device registered"))
  314. return
  315. }
  316. challenge, err := u2f.NewChallenge(setting.U2F.AppID, setting.U2F.TrustedFacets)
  317. if err = ctx.Session.Set("u2fChallenge", challenge); err != nil {
  318. ctx.ServerError("UserSignIn", err)
  319. return
  320. }
  321. ctx.JSON(200, challenge.SignRequest(regs.ToRegistrations()))
  322. }
  323. // U2FSign authenticates the user by signResp
  324. func U2FSign(ctx *context.Context, signResp u2f.SignResponse) {
  325. challSess := ctx.Session.Get("u2fChallenge")
  326. idSess := ctx.Session.Get("twofaUid")
  327. if challSess == nil || idSess == nil {
  328. ctx.ServerError("UserSignIn", errors.New("not in U2F session"))
  329. return
  330. }
  331. challenge := challSess.(*u2f.Challenge)
  332. id := idSess.(int64)
  333. regs, err := models.GetU2FRegistrationsByUID(id)
  334. if err != nil {
  335. ctx.ServerError("UserSignIn", err)
  336. return
  337. }
  338. for _, reg := range regs {
  339. r, err := reg.Parse()
  340. if err != nil {
  341. log.Fatal(4, "parsing u2f registration: %v", err)
  342. continue
  343. }
  344. newCounter, authErr := r.Authenticate(signResp, *challenge, reg.Counter)
  345. if authErr == nil {
  346. reg.Counter = newCounter
  347. user, err := models.GetUserByID(id)
  348. if err != nil {
  349. ctx.ServerError("UserSignIn", err)
  350. return
  351. }
  352. remember := ctx.Session.Get("twofaRemember").(bool)
  353. if err := reg.UpdateCounter(); err != nil {
  354. ctx.ServerError("UserSignIn", err)
  355. return
  356. }
  357. if ctx.Session.Get("linkAccount") != nil {
  358. gothUser := ctx.Session.Get("linkAccountGothUser")
  359. if gothUser == nil {
  360. ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
  361. return
  362. }
  363. err = models.LinkAccountToUser(user, gothUser.(goth.User))
  364. if err != nil {
  365. ctx.ServerError("UserSignIn", err)
  366. return
  367. }
  368. }
  369. redirect := handleSignInFull(ctx, user, remember, false)
  370. if redirect == "" {
  371. redirect = setting.AppSubURL + "/"
  372. }
  373. ctx.PlainText(200, []byte(redirect))
  374. return
  375. }
  376. }
  377. ctx.Error(401)
  378. }
  379. // This handles the final part of the sign-in process of the user.
  380. func handleSignIn(ctx *context.Context, u *models.User, remember bool) {
  381. handleSignInFull(ctx, u, remember, true)
  382. }
  383. func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string {
  384. if remember {
  385. days := 86400 * setting.LogInRememberDays
  386. ctx.SetCookie(setting.CookieUserName, u.Name, days, setting.AppSubURL)
  387. ctx.SetSuperSecureCookie(base.EncodeMD5(u.Rands+u.Passwd),
  388. setting.CookieRememberName, u.Name, days, setting.AppSubURL)
  389. }
  390. ctx.Session.Delete("openid_verified_uri")
  391. ctx.Session.Delete("openid_signin_remember")
  392. ctx.Session.Delete("openid_determined_email")
  393. ctx.Session.Delete("openid_determined_username")
  394. ctx.Session.Delete("twofaUid")
  395. ctx.Session.Delete("twofaRemember")
  396. ctx.Session.Delete("u2fChallenge")
  397. ctx.Session.Delete("linkAccount")
  398. ctx.Session.Set("uid", u.ID)
  399. ctx.Session.Set("uname", u.Name)
  400. // Language setting of the user overwrites the one previously set
  401. // If the user does not have a locale set, we save the current one.
  402. if len(u.Language) == 0 {
  403. u.Language = ctx.Locale.Language()
  404. if err := models.UpdateUserCols(u, "language"); err != nil {
  405. log.Error(4, fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language))
  406. return setting.AppSubURL + "/"
  407. }
  408. }
  409. ctx.SetCookie("lang", u.Language, nil, setting.AppSubURL)
  410. // Clear whatever CSRF has right now, force to generate a new one
  411. ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL)
  412. // Register last login
  413. u.SetLastLogin()
  414. if err := models.UpdateUserCols(u, "last_login_unix"); err != nil {
  415. ctx.ServerError("UpdateUserCols", err)
  416. return setting.AppSubURL + "/"
  417. }
  418. if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) {
  419. ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
  420. if obeyRedirect {
  421. ctx.RedirectToFirst(redirectTo)
  422. }
  423. return redirectTo
  424. }
  425. if obeyRedirect {
  426. ctx.Redirect(setting.AppSubURL + "/")
  427. }
  428. return setting.AppSubURL + "/"
  429. }
  430. // SignInOAuth handles the OAuth2 login buttons
  431. func SignInOAuth(ctx *context.Context) {
  432. provider := ctx.Params(":provider")
  433. loginSource, err := models.GetActiveOAuth2LoginSourceByName(provider)
  434. if err != nil {
  435. ctx.ServerError("SignIn", err)
  436. return
  437. }
  438. // try to do a direct callback flow, so we don't authenticate the user again but use the valid accesstoken to get the user
  439. user, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req.Request, ctx.Resp)
  440. if err == nil && user != nil {
  441. // we got the user without going through the whole OAuth2 authentication flow again
  442. handleOAuth2SignIn(user, gothUser, ctx, err)
  443. return
  444. }
  445. err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp)
  446. if err != nil {
  447. ctx.ServerError("SignIn", err)
  448. }
  449. // redirect is done in oauth2.Auth
  450. }
  451. // SignInOAuthCallback handles the callback from the given provider
  452. func SignInOAuthCallback(ctx *context.Context) {
  453. provider := ctx.Params(":provider")
  454. // first look if the provider is still active
  455. loginSource, err := models.GetActiveOAuth2LoginSourceByName(provider)
  456. if err != nil {
  457. ctx.ServerError("SignIn", err)
  458. return
  459. }
  460. if loginSource == nil {
  461. ctx.ServerError("SignIn", errors.New("No valid provider found, check configured callback url in provider"))
  462. return
  463. }
  464. u, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req.Request, ctx.Resp)
  465. handleOAuth2SignIn(u, gothUser, ctx, err)
  466. }
  467. func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context, err error) {
  468. if err != nil {
  469. ctx.ServerError("UserSignIn", err)
  470. return
  471. }
  472. if u == nil {
  473. // no existing user is found, request attach or new account
  474. ctx.Session.Set("linkAccountGothUser", gothUser)
  475. ctx.Redirect(setting.AppSubURL + "/user/link_account")
  476. return
  477. }
  478. // If this user is enrolled in 2FA, we can't sign the user in just yet.
  479. // Instead, redirect them to the 2FA authentication page.
  480. _, err = models.GetTwoFactorByUID(u.ID)
  481. if err != nil {
  482. if models.IsErrTwoFactorNotEnrolled(err) {
  483. ctx.Session.Set("uid", u.ID)
  484. ctx.Session.Set("uname", u.Name)
  485. // Clear whatever CSRF has right now, force to generate a new one
  486. ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL)
  487. // Register last login
  488. u.SetLastLogin()
  489. if err := models.UpdateUserCols(u, "last_login_unix"); err != nil {
  490. ctx.ServerError("UpdateUserCols", err)
  491. return
  492. }
  493. if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
  494. ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
  495. ctx.RedirectToFirst(redirectTo)
  496. return
  497. }
  498. ctx.Redirect(setting.AppSubURL + "/")
  499. } else {
  500. ctx.ServerError("UserSignIn", err)
  501. }
  502. return
  503. }
  504. // User needs to use 2FA, save data and redirect to 2FA page.
  505. ctx.Session.Set("twofaUid", u.ID)
  506. ctx.Session.Set("twofaRemember", false)
  507. // If U2F is enrolled -> Redirect to U2F instead
  508. regs, err := models.GetU2FRegistrationsByUID(u.ID)
  509. if err == nil && len(regs) > 0 {
  510. ctx.Redirect(setting.AppSubURL + "/user/u2f")
  511. return
  512. }
  513. ctx.Redirect(setting.AppSubURL + "/user/two_factor")
  514. }
  515. // OAuth2UserLoginCallback attempts to handle the callback from the OAuth2 provider and if successful
  516. // login the user
  517. func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Request, response http.ResponseWriter) (*models.User, goth.User, error) {
  518. gothUser, err := oauth2.ProviderCallback(loginSource.Name, request, response)
  519. if err != nil {
  520. return nil, goth.User{}, err
  521. }
  522. user := &models.User{
  523. LoginName: gothUser.UserID,
  524. LoginType: models.LoginOAuth2,
  525. LoginSource: loginSource.ID,
  526. }
  527. hasUser, err := models.GetUser(user)
  528. if err != nil {
  529. return nil, goth.User{}, err
  530. }
  531. if hasUser {
  532. return user, goth.User{}, nil
  533. }
  534. // search in external linked users
  535. externalLoginUser := &models.ExternalLoginUser{
  536. ExternalID: gothUser.UserID,
  537. LoginSourceID: loginSource.ID,
  538. }
  539. hasUser, err = models.GetExternalLogin(externalLoginUser)
  540. if err != nil {
  541. return nil, goth.User{}, err
  542. }
  543. if hasUser {
  544. user, err = models.GetUserByID(externalLoginUser.UserID)
  545. return user, goth.User{}, err
  546. }
  547. // no user found to login
  548. return nil, gothUser, nil
  549. }
  550. // LinkAccount shows the page where the user can decide to login or create a new account
  551. func LinkAccount(ctx *context.Context) {
  552. ctx.Data["Title"] = ctx.Tr("link_account")
  553. ctx.Data["LinkAccountMode"] = true
  554. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  555. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  556. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  557. ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
  558. ctx.Data["ShowRegistrationButton"] = false
  559. // use this to set the right link into the signIn and signUp templates in the link_account template
  560. ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
  561. ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
  562. gothUser := ctx.Session.Get("linkAccountGothUser")
  563. if gothUser == nil {
  564. ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
  565. return
  566. }
  567. ctx.Data["user_name"] = gothUser.(goth.User).NickName
  568. ctx.Data["email"] = gothUser.(goth.User).Email
  569. ctx.HTML(200, tplLinkAccount)
  570. }
  571. // LinkAccountPostSignIn handle the coupling of external account with another account using signIn
  572. func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) {
  573. ctx.Data["Title"] = ctx.Tr("link_account")
  574. ctx.Data["LinkAccountMode"] = true
  575. ctx.Data["LinkAccountModeSignIn"] = true
  576. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  577. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  578. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  579. ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
  580. ctx.Data["ShowRegistrationButton"] = false
  581. // use this to set the right link into the signIn and signUp templates in the link_account template
  582. ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
  583. ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
  584. gothUser := ctx.Session.Get("linkAccountGothUser")
  585. if gothUser == nil {
  586. ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
  587. return
  588. }
  589. if ctx.HasError() {
  590. ctx.HTML(200, tplLinkAccount)
  591. return
  592. }
  593. u, err := models.UserSignIn(signInForm.UserName, signInForm.Password)
  594. if err != nil {
  595. if models.IsErrUserNotExist(err) {
  596. ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplLinkAccount, &signInForm)
  597. } else {
  598. ctx.ServerError("UserLinkAccount", err)
  599. }
  600. return
  601. }
  602. // If this user is enrolled in 2FA, we can't sign the user in just yet.
  603. // Instead, redirect them to the 2FA authentication page.
  604. _, err = models.GetTwoFactorByUID(u.ID)
  605. if err != nil {
  606. if models.IsErrTwoFactorNotEnrolled(err) {
  607. err = models.LinkAccountToUser(u, gothUser.(goth.User))
  608. if err != nil {
  609. ctx.ServerError("UserLinkAccount", err)
  610. } else {
  611. handleSignIn(ctx, u, signInForm.Remember)
  612. }
  613. } else {
  614. ctx.ServerError("UserLinkAccount", err)
  615. }
  616. return
  617. }
  618. // User needs to use 2FA, save data and redirect to 2FA page.
  619. ctx.Session.Set("twofaUid", u.ID)
  620. ctx.Session.Set("twofaRemember", signInForm.Remember)
  621. ctx.Session.Set("linkAccount", true)
  622. // If U2F is enrolled -> Redirect to U2F instead
  623. regs, err := models.GetU2FRegistrationsByUID(u.ID)
  624. if err == nil && len(regs) > 0 {
  625. ctx.Redirect(setting.AppSubURL + "/user/u2f")
  626. return
  627. }
  628. ctx.Redirect(setting.AppSubURL + "/user/two_factor")
  629. }
  630. // LinkAccountPostRegister handle the creation of a new account for an external account using signUp
  631. func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
  632. ctx.Data["Title"] = ctx.Tr("link_account")
  633. ctx.Data["LinkAccountMode"] = true
  634. ctx.Data["LinkAccountModeRegister"] = true
  635. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  636. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  637. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  638. ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
  639. ctx.Data["ShowRegistrationButton"] = false
  640. // use this to set the right link into the signIn and signUp templates in the link_account template
  641. ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
  642. ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
  643. gothUser := ctx.Session.Get("linkAccountGothUser")
  644. if gothUser == nil {
  645. ctx.ServerError("UserSignUp", errors.New("not in LinkAccount session"))
  646. return
  647. }
  648. if ctx.HasError() {
  649. ctx.HTML(200, tplLinkAccount)
  650. return
  651. }
  652. if setting.Service.DisableRegistration {
  653. ctx.Error(403)
  654. return
  655. }
  656. if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ImageCaptcha && !cpt.VerifyReq(ctx.Req) {
  657. ctx.Data["Err_Captcha"] = true
  658. ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form)
  659. return
  660. }
  661. if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ReCaptcha {
  662. valid, _ := recaptcha.Verify(form.GRecaptchaResponse)
  663. if !valid {
  664. ctx.Data["Err_Captcha"] = true
  665. ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form)
  666. return
  667. }
  668. }
  669. if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
  670. ctx.Data["Err_Password"] = true
  671. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
  672. return
  673. }
  674. if len(strings.TrimSpace(form.Password)) > 0 && len(form.Password) < setting.MinPasswordLength {
  675. ctx.Data["Err_Password"] = true
  676. ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
  677. return
  678. }
  679. loginSource, err := models.GetActiveOAuth2LoginSourceByName(gothUser.(goth.User).Provider)
  680. if err != nil {
  681. ctx.ServerError("CreateUser", err)
  682. }
  683. u := &models.User{
  684. Name: form.UserName,
  685. Email: form.Email,
  686. Passwd: form.Password,
  687. IsActive: !setting.Service.RegisterEmailConfirm,
  688. LoginType: models.LoginOAuth2,
  689. LoginSource: loginSource.ID,
  690. LoginName: gothUser.(goth.User).UserID,
  691. }
  692. if err := models.CreateUser(u); err != nil {
  693. switch {
  694. case models.IsErrUserAlreadyExist(err):
  695. ctx.Data["Err_UserName"] = true
  696. ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplLinkAccount, &form)
  697. case models.IsErrEmailAlreadyUsed(err):
  698. ctx.Data["Err_Email"] = true
  699. ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplLinkAccount, &form)
  700. case models.IsErrNameReserved(err):
  701. ctx.Data["Err_UserName"] = true
  702. ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), tplLinkAccount, &form)
  703. case models.IsErrNamePatternNotAllowed(err):
  704. ctx.Data["Err_UserName"] = true
  705. ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplLinkAccount, &form)
  706. default:
  707. ctx.ServerError("CreateUser", err)
  708. }
  709. return
  710. }
  711. log.Trace("Account created: %s", u.Name)
  712. // Auto-set admin for the only user.
  713. if models.CountUsers() == 1 {
  714. u.IsAdmin = true
  715. u.IsActive = true
  716. u.SetLastLogin()
  717. if err := models.UpdateUserCols(u, "is_admin", "is_active", "last_login_unix"); err != nil {
  718. ctx.ServerError("UpdateUser", err)
  719. return
  720. }
  721. }
  722. // Send confirmation email
  723. if setting.Service.RegisterEmailConfirm && u.ID > 1 {
  724. models.SendActivateAccountMail(ctx.Context, u)
  725. ctx.Data["IsSendRegisterMail"] = true
  726. ctx.Data["Email"] = u.Email
  727. ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
  728. ctx.HTML(200, TplActivate)
  729. if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
  730. log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
  731. }
  732. return
  733. }
  734. ctx.Redirect(setting.AppSubURL + "/user/login")
  735. }
  736. // SignOut sign out from login status
  737. func SignOut(ctx *context.Context) {
  738. ctx.Session.Delete("uid")
  739. ctx.Session.Delete("uname")
  740. ctx.Session.Delete("socialId")
  741. ctx.Session.Delete("socialName")
  742. ctx.Session.Delete("socialEmail")
  743. ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL)
  744. ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL)
  745. ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL)
  746. ctx.SetCookie("lang", "", -1, setting.AppSubURL) // Setting the lang cookie will trigger the middleware to reset the language ot previous state.
  747. ctx.Redirect(setting.AppSubURL + "/")
  748. }
  749. // SignUp render the register page
  750. func SignUp(ctx *context.Context) {
  751. ctx.Data["Title"] = ctx.Tr("sign_up")
  752. ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
  753. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  754. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  755. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  756. ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
  757. ctx.HTML(200, tplSignUp)
  758. }
  759. // SignUpPost response for sign up information submission
  760. func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
  761. ctx.Data["Title"] = ctx.Tr("sign_up")
  762. ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
  763. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  764. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  765. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  766. //Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
  767. if !setting.Service.ShowRegistrationButton {
  768. ctx.Error(403)
  769. return
  770. }
  771. if ctx.HasError() {
  772. ctx.HTML(200, tplSignUp)
  773. return
  774. }
  775. if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ImageCaptcha && !cpt.VerifyReq(ctx.Req) {
  776. ctx.Data["Err_Captcha"] = true
  777. ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUp, &form)
  778. return
  779. }
  780. if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ReCaptcha {
  781. valid, _ := recaptcha.Verify(form.GRecaptchaResponse)
  782. if !valid {
  783. ctx.Data["Err_Captcha"] = true
  784. ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUp, &form)
  785. return
  786. }
  787. }
  788. if form.Password != form.Retype {
  789. ctx.Data["Err_Password"] = true
  790. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplSignUp, &form)
  791. return
  792. }
  793. if len(form.Password) < setting.MinPasswordLength {
  794. ctx.Data["Err_Password"] = true
  795. ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplSignUp, &form)
  796. return
  797. }
  798. u := &models.User{
  799. Name: form.UserName,
  800. Email: form.Email,
  801. Passwd: form.Password,
  802. IsActive: !setting.Service.RegisterEmailConfirm,
  803. }
  804. if err := models.CreateUser(u); err != nil {
  805. switch {
  806. case models.IsErrUserAlreadyExist(err):
  807. ctx.Data["Err_UserName"] = true
  808. ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSignUp, &form)
  809. case models.IsErrEmailAlreadyUsed(err):
  810. ctx.Data["Err_Email"] = true
  811. ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignUp, &form)
  812. case models.IsErrNameReserved(err):
  813. ctx.Data["Err_UserName"] = true
  814. ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), tplSignUp, &form)
  815. case models.IsErrNamePatternNotAllowed(err):
  816. ctx.Data["Err_UserName"] = true
  817. ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplSignUp, &form)
  818. default:
  819. ctx.ServerError("CreateUser", err)
  820. }
  821. return
  822. }
  823. log.Trace("Account created: %s", u.Name)
  824. // Auto-set admin for the only user.
  825. if models.CountUsers() == 1 {
  826. u.IsAdmin = true
  827. u.IsActive = true
  828. u.SetLastLogin()
  829. if err := models.UpdateUserCols(u, "is_admin", "is_active", "last_login_unix"); err != nil {
  830. ctx.ServerError("UpdateUser", err)
  831. return
  832. }
  833. }
  834. // Send confirmation email, no need for social account.
  835. if setting.Service.RegisterEmailConfirm && u.ID > 1 {
  836. models.SendActivateAccountMail(ctx.Context, u)
  837. ctx.Data["IsSendRegisterMail"] = true
  838. ctx.Data["Email"] = u.Email
  839. ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
  840. ctx.HTML(200, TplActivate)
  841. if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
  842. log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
  843. }
  844. return
  845. }
  846. ctx.Redirect(setting.AppSubURL + "/user/login")
  847. }
  848. // Activate render activate user page
  849. func Activate(ctx *context.Context) {
  850. code := ctx.Query("code")
  851. if len(code) == 0 {
  852. ctx.Data["IsActivatePage"] = true
  853. if ctx.User.IsActive {
  854. ctx.Error(404)
  855. return
  856. }
  857. // Resend confirmation email.
  858. if setting.Service.RegisterEmailConfirm {
  859. if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
  860. ctx.Data["ResendLimited"] = true
  861. } else {
  862. ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
  863. models.SendActivateAccountMail(ctx.Context, ctx.User)
  864. if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
  865. log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
  866. }
  867. }
  868. } else {
  869. ctx.Data["ServiceNotEnabled"] = true
  870. }
  871. ctx.HTML(200, TplActivate)
  872. return
  873. }
  874. // Verify code.
  875. if user := models.VerifyUserActiveCode(code); user != nil {
  876. user.IsActive = true
  877. var err error
  878. if user.Rands, err = models.GetUserSalt(); err != nil {
  879. ctx.ServerError("UpdateUser", err)
  880. return
  881. }
  882. if err := models.UpdateUserCols(user, "is_active", "rands"); err != nil {
  883. if models.IsErrUserNotExist(err) {
  884. ctx.Error(404)
  885. } else {
  886. ctx.ServerError("UpdateUser", err)
  887. }
  888. return
  889. }
  890. log.Trace("User activated: %s", user.Name)
  891. ctx.Session.Set("uid", user.ID)
  892. ctx.Session.Set("uname", user.Name)
  893. ctx.Flash.Success(ctx.Tr("auth.account_activated"))
  894. ctx.Redirect(setting.AppSubURL + "/")
  895. return
  896. }
  897. ctx.Data["IsActivateFailed"] = true
  898. ctx.HTML(200, TplActivate)
  899. }
  900. // ActivateEmail render the activate email page
  901. func ActivateEmail(ctx *context.Context) {
  902. code := ctx.Query("code")
  903. emailStr := ctx.Query("email")
  904. // Verify code.
  905. if email := models.VerifyActiveEmailCode(code, emailStr); email != nil {
  906. if err := email.Activate(); err != nil {
  907. ctx.ServerError("ActivateEmail", err)
  908. }
  909. log.Trace("Email activated: %s", email.Email)
  910. ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
  911. }
  912. ctx.Redirect(setting.AppSubURL + "/user/settings/email")
  913. return
  914. }
  915. // ForgotPasswd render the forget pasword page
  916. func ForgotPasswd(ctx *context.Context) {
  917. ctx.Data["Title"] = ctx.Tr("auth.forgot_password_title")
  918. if setting.MailService == nil {
  919. ctx.Data["IsResetDisable"] = true
  920. ctx.HTML(200, tplForgotPassword)
  921. return
  922. }
  923. email := ctx.Query("email")
  924. ctx.Data["Email"] = email
  925. ctx.Data["IsResetRequest"] = true
  926. ctx.HTML(200, tplForgotPassword)
  927. }
  928. // ForgotPasswdPost response for forget password request
  929. func ForgotPasswdPost(ctx *context.Context) {
  930. ctx.Data["Title"] = ctx.Tr("auth.forgot_password_title")
  931. if setting.MailService == nil {
  932. ctx.NotFound("ForgotPasswdPost", nil)
  933. return
  934. }
  935. ctx.Data["IsResetRequest"] = true
  936. email := ctx.Query("email")
  937. ctx.Data["Email"] = email
  938. u, err := models.GetUserByEmail(email)
  939. if err != nil {
  940. if models.IsErrUserNotExist(err) {
  941. ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language())
  942. ctx.Data["IsResetSent"] = true
  943. ctx.HTML(200, tplForgotPassword)
  944. return
  945. }
  946. ctx.ServerError("user.ResetPasswd(check existence)", err)
  947. return
  948. }
  949. if !u.IsLocal() && !u.IsOAuth2() {
  950. ctx.Data["Err_Email"] = true
  951. ctx.RenderWithErr(ctx.Tr("auth.non_local_account"), tplForgotPassword, nil)
  952. return
  953. }
  954. if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) {
  955. ctx.Data["ResendLimited"] = true
  956. ctx.HTML(200, tplForgotPassword)
  957. return
  958. }
  959. models.SendResetPasswordMail(ctx.Context, u)
  960. if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
  961. log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
  962. }
  963. ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language())
  964. ctx.Data["IsResetSent"] = true
  965. ctx.HTML(200, tplForgotPassword)
  966. }
  967. // ResetPasswd render the reset password page
  968. func ResetPasswd(ctx *context.Context) {
  969. ctx.Data["Title"] = ctx.Tr("auth.reset_password")
  970. code := ctx.Query("code")
  971. if len(code) == 0 {
  972. ctx.Error(404)
  973. return
  974. }
  975. ctx.Data["Code"] = code
  976. ctx.Data["IsResetForm"] = true
  977. ctx.HTML(200, tplResetPassword)
  978. }
  979. // ResetPasswdPost response from reset password request
  980. func ResetPasswdPost(ctx *context.Context) {
  981. ctx.Data["Title"] = ctx.Tr("auth.reset_password")
  982. code := ctx.Query("code")
  983. if len(code) == 0 {
  984. ctx.Error(404)
  985. return
  986. }
  987. ctx.Data["Code"] = code
  988. if u := models.VerifyUserActiveCode(code); u != nil {
  989. // Validate password length.
  990. passwd := ctx.Query("password")
  991. if len(passwd) < setting.MinPasswordLength {
  992. ctx.Data["IsResetForm"] = true
  993. ctx.Data["Err_Password"] = true
  994. ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplResetPassword, nil)
  995. return
  996. }
  997. var err error
  998. if u.Rands, err = models.GetUserSalt(); err != nil {
  999. ctx.ServerError("UpdateUser", err)
  1000. return
  1001. }
  1002. if u.Salt, err = models.GetUserSalt(); err != nil {
  1003. ctx.ServerError("UpdateUser", err)
  1004. return
  1005. }
  1006. u.HashPassword(passwd)
  1007. if err := models.UpdateUserCols(u, "passwd", "rands", "salt"); err != nil {
  1008. ctx.ServerError("UpdateUser", err)
  1009. return
  1010. }
  1011. log.Trace("User password reset: %s", u.Name)
  1012. ctx.Redirect(setting.AppSubURL + "/user/login")
  1013. return
  1014. }
  1015. ctx.Data["IsResetFailed"] = true
  1016. ctx.HTML(200, tplResetPassword)
  1017. }