diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 2710f60a0..e7335ec0e 100644 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -846,21 +846,22 @@ class ApiController(RedditController): emailer.password_email(user) res._success() - @Json - @validate(uid = VCacheKey('reset', 'key'), + @validate(user = VCacheKey('reset', ('key', 'name')), key= nop('key'), password = VPassword(['passwd', 'passwd2'])) - def POST_resetpassword(self, res, uid, key, password): + def POST_resetpassword(self, res, user, key, password): res._update('status', innerHTML = '') if res._chk_error(errors.BAD_PASSWORD): res._focus('passwd') elif res._chk_error(errors.BAD_PASSWORD_MATCH): res._focus('passwd2') - else: - user = Account._byID(uid, data=True) - change_password(user, user.password, password) + elif errors.BAD_USERNAME in c.errors: cache.delete(str('reset_%s' % key)) + return res._redirect('/password') + elif user: + cache.delete(str('reset_%s' % key)) + change_password(user, password) self._login(res, user, '/resetpassword') diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index 94910d510..616579328 100644 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -63,9 +63,9 @@ class FrontController(RedditController): """The 'what is my password' page""" return BoringPage(_("password"), content=Password()).render() - @validate(uid = VCacheKey('reset', 'key'), + @validate(user = VCacheKey('reset', ('key', 'name')), key = nop('key')) - def GET_resetpassword(self, uid, key): + def GET_resetpassword(self, user, key): """page hit once a user has been sent a password reset email to verify their identity before allowing them to update their password.""" @@ -73,7 +73,7 @@ class FrontController(RedditController): if not key and request.referer: referer_path = request.referer.split(c.domain)[-1] done = referer_path.startswith(request.fullpath) - elif not uid: + elif not user: return self.abort404() return BoringPage(_("reset password"), content=ResetPassword(key=key, done=done)).render() diff --git a/r2/r2/controllers/post.py b/r2/r2/controllers/post.py index b149a95b0..90a44835a 100644 --- a/r2/r2/controllers/post.py +++ b/r2/r2/controllers/post.py @@ -1,4 +1,4 @@ -# "The contents of this file are subject to the Common Public Attribution +# The contents of this file are subject to the Common Public Attribution # License Version 1.0. (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://code.reddit.com/LICENSE. The License is based on the Mozilla Public diff --git a/r2/r2/controllers/validator/validator.py b/r2/r2/controllers/validator/validator.py index adfe00ef2..d85c69df8 100644 --- a/r2/r2/controllers/validator/validator.py +++ b/r2/r2/controllers/validator/validator.py @@ -583,10 +583,17 @@ class VCacheKey(Validator): self.cache_prefix = cache_prefix Validator.__init__(self, param, *a, **kw) - def run(self, key): + def run(self, key, name): if key: - val = cache.get(str(self.cache_prefix + "_" + key)) - if val: return val + uid = cache.get(str(self.cache_prefix + "_" + key)) + try: + a = Account._byID(uid, data = True) + except NotFound: + return None + if name and a.name.lower() != name.lower(): + c.errors.add(errors.BAD_USERNAME) + if a: + return a c.errors.add(errors.EXPIRED) class VOneOf(Validator): diff --git a/r2/r2/lib/emailer.py b/r2/r2/lib/emailer.py index 1571fec7f..9bb90df5a 100644 --- a/r2/r2/lib/emailer.py +++ b/r2/r2/lib/emailer.py @@ -1,4 +1,4 @@ -# "The contents of this file are subject to the Common Public Attribution +# The contents of this file are subject to the Common Public Attribution # License Version 1.0. (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://code.reddit.com/LICENSE. The License is based on the Mozilla Public @@ -21,7 +21,7 @@ ################################################################################ from email.MIMEText import MIMEText from pylons import c,g -from pages import Password_Reset +from pages import PasswordReset from r2.models.account import passhash from r2.config import cache import os, random @@ -68,5 +68,5 @@ def password_email(user): cache.set("reset_%s" %key, user._id, time=1800) simple_email(user.email, 'reddit@reddit.com', 'reddit.com password reset', - Password_Reset(user=user, passlink=passlink).render()) + PasswordReset(user=user, passlink=passlink).render(style='email')) diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 2acb2de68..2781253ac 100644 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -631,7 +631,7 @@ class Password(Wrapped): def __init__(self, success=False): Wrapped.__init__(self, success = success) -class Password_Reset(Wrapped): +class PasswordReset(Wrapped): """Template for generating an email to the user who wishes to reset their password (step 2 of password recovery, after they have entered their user name in Password.)""" @@ -641,8 +641,7 @@ class ResetPassword(Wrapped): """Form for actually resetting a lost password, after the user has clicked on the link provided to them in the Password_Reset email (step 3 of password recovery.)""" - def __init__(self, key=''): - Wrapped.__init__(self, key = key) + pass class Captcha(Wrapped): diff --git a/r2/r2/models/account.py b/r2/r2/models/account.py index 7838074b7..3a56512ae 100644 --- a/r2/r2/models/account.py +++ b/r2/r2/models/account.py @@ -247,13 +247,10 @@ def passhash(username, password, salt = ''): tohash = '%s%s %s' % (salt, username, password) return salt + sha.new(tohash).hexdigest() -def change_password(user, password, newpassword): - if valid_password(user, password): - user.password = passhash(user.name, newpassword) - user._commit() - return True - return False - +def change_password(user, newpassword): + user.password = passhash(user.name, newpassword, True) + user._commit() + return True #TODO reset the cache def register(name, password): diff --git a/r2/r2/public/static/reddit.css b/r2/r2/public/static/reddit.css index 7a8e09921..497cabedf 100644 --- a/r2/r2/public/static/reddit.css +++ b/r2/r2/public/static/reddit.css @@ -1207,6 +1207,11 @@ a.star { text-decoration: none; color: #ff8b60 } .pretty-form.long-text textarea, .pretty-form.long-text input[type=password] {padding: 2px; width: 40em } +/*forgot password*/ +#passform h1 { margin: 0px; } +#passform p { font-size: smaller; color: orangered; margin-bottom: 7px} +#passform.pretty-form button { padding: 0px 1px; } + .prefleft { padding: 10px; font-weight: bold; vertical-align: top} .prefright { padding: 10px } diff --git a/r2/r2/templates/feedback.html b/r2/r2/templates/feedback.html index 555bd61a2..06d332a05 100644 --- a/r2/r2/templates/feedback.html +++ b/r2/r2/templates/feedback.html @@ -1,4 +1,4 @@ -## "The contents of this file are subject to the Common Public Attribution +## The contents of this file are subject to the Common Public Attribution ## License Version 1.0. (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License at ## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public diff --git a/r2/r2/templates/password.html b/r2/r2/templates/password.html index 971a0eeb6..b24e4a7c9 100644 --- a/r2/r2/templates/password.html +++ b/r2/r2/templates/password.html @@ -1,4 +1,4 @@ -## "The contents of this file are subject to the Common Public Attribution +## The contents of this file are subject to the Common Public Attribution ## License Version 1.0. (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License at ## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public @@ -21,27 +21,28 @@ ################################################################################ <%namespace file="utils.html" import="error_field, success_field"/> -

${_("what's my password?")}

-

- ${_("enter your user name below to receive your login information")} -

- ${success_field(_('you should receive an email shortly'), successful=thing.success, hide='passform')} -
+

${_("what's my password?")}

+

${_("enter your user name below to receive your login information")}

- - + + +
- ${_("username")}: + + + - + +
${error_field("USER_DOESNT_EXIST", "span")} ${error_field("NO_EMAIL_FOR_USER", "span")} diff --git a/r2/r2/templates/password_reset.html b/r2/r2/templates/passwordreset.email similarity index 94% rename from r2/r2/templates/password_reset.html rename to r2/r2/templates/passwordreset.email index c2a782627..ad12208d2 100644 --- a/r2/r2/templates/password_reset.html +++ b/r2/r2/templates/passwordreset.email @@ -1,4 +1,4 @@ -## "The contents of this file are subject to the Common Public Attribution +## The contents of this file are subject to the Common Public Attribution ## License Version 1.0. (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License at ## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public diff --git a/r2/r2/templates/resetpassword.html b/r2/r2/templates/resetpassword.html index 2a736f66e..a248a67d5 100644 --- a/r2/r2/templates/resetpassword.html +++ b/r2/r2/templates/resetpassword.html @@ -1,4 +1,4 @@ -## "The contents of this file are subject to the Common Public Attribution +## The contents of this file are subject to the Common Public Attribution ## License Version 1.0. (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License at ## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public @@ -25,17 +25,26 @@ %if thing.done:

your password has been reset and you've been logged in. Go use the site!

%else: -

reset your password

- ${error_field("EXPIRED", 'p')} - + +

reset your password

+ + + +
- ${_('new password')}: + ${_("username")} + + +
+ ${_("new password")}
- ${_('verify password')}: + ${_("verify password")}