Merged in "reset password" functionality.

This commit is contained in:
Raoul Snyman 2010-02-16 22:19:26 +02:00
commit cfad76f615
7 changed files with 175 additions and 32 deletions

View File

@ -25,6 +25,8 @@ import string
import random import random
from datetime import datetime from datetime import datetime
from formencode.validators import Int
from scribeengine.lib.base import * from scribeengine.lib.base import *
from scribeengine.lib.validation.client import JSString, JSEmail from scribeengine.lib.validation.client import JSString, JSEmail
from scribeengine.lib.validation.server import UnicodeString, Email, FieldsMatch from scribeengine.lib.validation.server import UnicodeString, Email, FieldsMatch
@ -46,24 +48,24 @@ class AccountController(BaseController):
@jsvalidate(u'register-form') @jsvalidate(u'register-form')
def register_jsschema(self): def register_jsschema(self):
return { return {
u'email': JSEmail(required=True, message=u'You haven\'t typed in an e-mail address.'), u'register-email': JSEmail(required=True, message=u'You haven\'t typed in an e-mail address.'),
u'password': JSString(required=True, message=u'You haven\'t typed in a password.'), u'register-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
u'confirm-password': JSString(required=True, equalTo=u'#password', message=u'Your passwords don\'t match.') u'register-confirm': JSString(required=True, equalTo=u'#password', message=u'Your passwords don\'t match.')
} }
def register_schema(self): def register_schema(self):
return { return {
'email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in an e-mail address.'}), 'register-email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in an e-mail address.'}),
'password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}), 'register-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
'confirm': [FieldsMatch('password', 'confirm-passsword', messages={'invalid': u'Your passwords don\'t match.'})] 'confirm-password': [FieldsMatch('register-password', 'register-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
} }
def register_POST(self): def register_POST(self):
activation_code = u''.join(random.sample(string.letters + string.digits, 40)) activation_code = u''.join(random.sample(string.letters + string.digits, 40))
user = User( user = User(
nick=c.form_values[u'nick'], nick=c.form_values[u'register-nick'],
email=c.form_values[u'email'], email=c.form_values[u'register-email'],
password=utils.hash_password(c.form_values[u'password']), password=utils.hash_password(c.form_values[u'register-password']),
activation_key=activation_code activation_key=activation_code
) )
Session.add(user) Session.add(user)
@ -117,27 +119,115 @@ class AccountController(BaseController):
u'registration.', u'success') u'registration.', u'success')
h.redirect_to(h.url_for(controller=u'account', action=u'login')) h.redirect_to(h.url_for(controller=u'account', action=u'login'))
def reset(self):
c.page_title = u'Reset Password'
return render(u'/account/reset.mako')
@jsvalidate(u'account-reset')
def reset_jsschema(self):
return {
u'reset-email': JSEmail(required=True, message=u'You haven\'t typed in a valid e-mail address.')
}
def reset_schema(self):
return {
'reset-email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in a valid e-mail address.'})
}
def reset_POST(self):
email = c.form_values[u'reset-email']
user = Session.query(User).filter_by(email=email).first()
if not user:
h.flash.set_message(u'Your e-mail address is not in the system.', u'error')
else:
activation_code = u''.join(random.sample(string.letters + string.digits, 40))
user.activation_key = activation_code
user.modified = datetime.now()
Session.add(user)
Session.commit()
blog_mail = Session.query(Variable).get(u'blog mail')
blog_title = Session.query(Variable).get(u'blog title')
blog_host = Session.query(Variable).get(u'blog host')
if not blog_host:
url = u'%s://%s' % (request.environ[u'wsgi.url_scheme'],
request.environ[u'HTTP_HOST'])
blog_host = Variable(key=u'blog host', value=url)
Session.add(blog_host)
Session.commit()
utils.send_mail(u'/email/reset.mako', u'%s <%s>' % (user.nick, user.email),
u'%s <%s>' % (blog_mail.value, blog_title.value),
u'[%s] Reset your password!' % blog_title.value,
{
'user': user,
'blog_title': blog_title.value,
'blog_host': blog_host.value
})
h.flash.set_message(u'An e-mail has been sent to your e-mail address. '
u'Please reset your password by clicking on the link in your '
u'e-mail.', u'success')
h.redirect_to('/account/login')
def password(self, id=None):
if not id or not request.GET.get(u'code'):
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
c.user = Session.query(User).get(id)
if not c.user:
h.flash.set_message(u'There was a problem with your account, please reset your password again.', u'error')
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
if c.user.activation_key != request.GET.get(u'code'):
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
c.page_title = u'Change Password'
return render(u'/account/password.mako')
@jsvalidate(u'account-password')
def password_jsschema(self):
return {
u'password-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
u'password-confirm': JSString(required=True, equalTo=u'#password-password', message=u'Your passwords don\'t match.')
}
def password_schema(self):
return {
'password-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
'confirm-password': [FieldsMatch('password-password', 'password-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
}
def password_POST(self, id=None):
user = Session.query(User).get(id)
if not user:
h.flash.set_message(u'There was a problem with your account, please reset your password again.', u'error')
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
user.password = utils.hash_password(c.form_values[u'password-password'])
user.activation_key = None
user.modified = datetime.now()
Session.add(user)
Session.commit()
h.flash.set_message(u'Successfully updated your password. Please login with your new password.', u'success')
h.redirect_to('/account/login')
def login(self): def login(self):
c.page_title = u'Login' c.page_title = u'Login'
return render(u'/account/login.mako') return render(u'/account/login.mako')
@jsvalidate(u'login-form') @jsvalidate(u'account-login')
def login_jsschema(self): def login_jsschema(self):
return { return {
u'email': JSEmail(required=True, message=u'You haven\'t typed in an e-mail address.'), u'login-email': JSEmail(required=True, message=u'You haven\'t typed in an e-mail address.'),
u'password': JSString(required=True, message=u'You haven\'t typed in a password.') u'login-password': JSString(required=True, message=u'You haven\'t typed in a password.')
} }
def login_schema(self): def login_schema(self):
return { return {
'email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in an e-mail address.'}), 'login-email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in an e-mail address.'}),
'password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}) 'login-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'})
} }
def login_POST(self): def login_POST(self):
log.debug('Logging in as "%s" with password "%s"', c.form_values[u'email'], c.form_values[u'password']) log.debug('Logging in as "%s" with password "%s"', c.form_values[u'login-email'], c.form_values[u'login-password'])
user = Session.query(User).filter_by(email=c.form_values[u'email']).first() user = Session.query(User).filter_by(email=c.form_values[u'login-email']).first()
password = utils.hash_password(c.form_values[u'password']) password = utils.hash_password(c.form_values[u'login-password'])
if not user or user.password != password: if not user or user.password != password:
log.debug('Username or password are incorrect.') log.debug('Username or password are incorrect.')
h.flash.set_message(u'Your username or password are incorrect.', u'error') h.flash.set_message(u'Your username or password are incorrect.', u'error')

View File

@ -3,19 +3,23 @@
<div class="post"> <div class="post">
<h2 class="title">Log in</h2> <h2 class="title">Log in</h2>
<%include file="/errors.mako"/> <%include file="/errors.mako"/>
<form id="post-new" action="${h.url_for(controller=u'account', action=u'login')}" method="post"> <form id="account-login" action="${h.url_for(controller=u'account', action=u'login')}" method="post">
<fieldset> <fieldset>
<div class="form-item"> <div class="form-item">
<label for="login-email">E-mail:</label> <label for="login-email">E-mail:</label>
<input type="text" name="email" id="login-email" class="form-text" /> <input type="text" name="login-email" id="login-email" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<label for="login-password">Password:</label> <label for="login-password">Password:</label>
<input type="password" name="password" id="login-password" class="form-text" /> <input type="password" name="login-password" id="login-password" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<input type="submit" name="action" value="Login" class="form-button"/> <input type="submit" name="login-action" value="Login" class="form-button"/>
<span id="register-now">No account? <a href="${h.url_for(controller=u'account', action=u'register')}" title="register now">Register now!</a></span> <span id="register-now">
<a href="${h.url_for(controller=u'account', action=u'register')}" title="register now">Register now</a>
or
<a href="${h.url_for(controller=u'account', action=u'reset')}" title="reset password">reset your password</a>.
</span>
</div> </div>
</fieldset> </fieldset>
</form> </form>

View File

@ -0,0 +1,21 @@
<%inherit file="/base.mako"/>
<%include file="/flash.mako"/>
<div class="post">
<h2 class="title">New password</h2>
<%include file="/errors.mako"/>
<form id="account-password" action="${h.url_for(controller=u'account', action=u'password', id=c.user.id)}" method="post">
<fieldset>
<div class="form-item">
<label for="password-password">Password:</label>
<input type="password" name="password-password" id="password-password" class="form-text" />
</div>
<div class="form-item">
<label for="password-confirm">Confirm password:</label>
<input type="password" name="password-confirm" id="password-confirm" class="form-text" />
</div>
<div class="form-item">
<input type="submit" name="password-action" value="Change password" class="form-button"/>
</div>
</fieldset>
</form>
</div>

View File

@ -3,26 +3,26 @@
<div class="post"> <div class="post">
<h2 class="title">Register</h2> <h2 class="title">Register</h2>
<%include file="/errors.mako"/> <%include file="/errors.mako"/>
<form id="post-new" action="${h.url_for(controller=u'account', action=u'register')}" method="post"> <form id="account-register" action="${h.url_for(controller=u'account', action=u'register')}" method="post">
<fieldset> <fieldset>
<div class="form-item"> <div class="form-item">
<label for="register-nick">Nick:</label> <label for="register-nick">Nick:</label>
<input type="text" name="nick" id="register-nick" class="form-text" /> <input type="text" name="register-nick" id="register-nick" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<label for="register-email">E-mail:</label> <label for="register-email">E-mail:</label>
<input type="text" name="email" id="register-email" class="form-text" /> <input type="text" name="register-email" id="register-email" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<label for="register-password">Password:</label> <label for="register-password">Password:</label>
<input type="password" name="password" id="register-password" class="form-text" /> <input type="password" name="register-password" id="register-password" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<label for="register-confirm-password">Confirm Password:</label> <label for="register-confirm">Confirm Password:</label>
<input type="password" name="confirm-password" id="register-confirm-password" class="form-text" /> <input type="password" name="register-confirm" id="register-confirm" class="form-text" />
</div> </div>
<div class="form-item"> <div class="form-item">
<input type="submit" name="action" value="Register" class="form-button" /> <input type="submit" name="register-action" value="Register" class="form-button" />
</div> </div>
</fieldset> </fieldset>
</form> </form>

View File

@ -0,0 +1,17 @@
<%inherit file="/base.mako"/>
<%include file="/flash.mako"/>
<div class="post">
<h2 class="title">Reset your password</h2>
<%include file="/errors.mako"/>
<form id="account-reset" action="${h.url_for(controller=u'account', action=u'reset')}" method="post">
<fieldset>
<div class="form-item">
<label for="reset-email">E-mail:</label>
<input type="text" name="reset-email" id="reset-email" class="form-text" />
</div>
<div class="form-item">
<input type="submit" name="reset-action" value="Reset password" class="form-button"/>
</div>
</fieldset>
</form>
</div>

View File

@ -4,14 +4,14 @@ You have just registered on ${c.blog_title}, but before you continue, you will
need to activate your account. You can do this by simply clicking on the link need to activate your account. You can do this by simply clicking on the link
below, or copying and pasting it into your browser. below, or copying and pasting it into your browser.
${c.blog_host}${h.url_for(controller=u'admin', action=u'activate', id=c.user.id, code=c.user.activation_key)} ${c.blog_host}${h.url_for(controller=u'account', action=u'activate', id=c.user.id, code=c.user.activation_key)}
If this is not you, simply leave this e-mail, and the account will expire after If this is not you, simply leave this e-mail, and the account will expire after
72 hours. If you left this e-mail for too long and want to continue with the 72 hours. If you left this e-mail for too long and want to continue with the
registration process, click on the link below, type in your e-mail addres, and registration process, click on the link below, type in your e-mail address, and
another e-mail will be sent to you to activate your account. another e-mail will be sent to you to activate your account.
${c.blog_host}${h.url_for(controller=u'admin', action=u'reset', id=c.user.id)} ${c.blog_host}${h.url_for(controller=u'account', action=u'reset', id=c.user.id)}
Once you have completed the registration process you will be able to comment on Once you have completed the registration process you will be able to comment on
the posts on the site. the posts on the site.

View File

@ -0,0 +1,11 @@
Dear ${c.user.nick},
You have just reset your password on ${c.blog_title}, but before you continue,
you will need to activate your account. You can do this by simply clicking on
the link below, or copying and pasting it into your browser.
${c.blog_host}${h.url_for(controller=u'account', action=u'password', id=c.user.id, code=c.user.activation_key)}
Kind regards,
${c.blog_title} Team