Commit 9094c222 authored by Adrien Di Mascio's avatar Adrien Di Mascio
Browse files

use standard CW-NotificationViews system to send emails

Operation is fired when a FPasswd is inserted.
parent 3af26f52265d
""" this module contains server side hooks for cleaning forgotpwd table
"""
from datetime import datetime
from cubicweb.selectors import implements
from cubicweb.server import hooksmanager
from cubicweb.sobjects.notification import NotificationView
_ = unicode
class ServerStartupHook(hooksmanager.Hook):
""" Delete old revocation key
"""
events = ('server_startup',)
def call(self, repo):
from datetime import datetime
def cleaning_revocation_key(repo):
session = repo.internal_session()
session.execute('DELETE Fpasswd F WHERE F revocation_date < %(date)s', {'date': datetime.now()})
......@@ -16,4 +20,40 @@ class ServerStartupHook(hooksmanager.Hook):
session.close()
# revocation keu must be deleted
cleaning_revocation_key(repo)
repo.looping_task(60 * 60, cleaning_revocation_key, repo)
# run looping task often enough to purge pwd-reset requests
limit = self.vreg.config['revocation-limit']
repo.looping_task(limit * 60, cleaning_revocation_key, repo)
class PasswordResetNotification(NotificationView):
id = 'notif_after_add_entity'
__select__ = implements('Fpasswd')
content = _('''There was recently a request to change the password on your account.
If you requested this password change, please set a new password by following
the link below:
%(resetlink)s
If you do not want to change your password, you may ignore this message. The
link expires in %(limit)s minutes.
See you soon on %(base_url)s !
''')
def subject(self):
return self.req._(u'Request to change your password')
def recipients(self):
fpasswd = self.rset.get_entity(0, 0)
user = fpasswd.reverse_has_fpasswd[0]
return [(user.get_email(), user.property_value('ui.language'))]
def context(self, **kwargs):
return {
'resetlink': self.req.get_shared_data('resetlink', pop=True),
# NOTE: it would probably be better to display the expiration date
# (with correct timezone)
'limit': self.vreg.config['revocation-limit'],
'base_url': self.req.base_url(),
}
......@@ -22,6 +22,8 @@ from cubes.registration.views import CaptchaWidget, encrypt, decrypt
from logilab.mtconverter import xml_escape
_ = unicode
# Login form
# ----------
......@@ -102,15 +104,19 @@ class ForgottenPasswordRequestForm(forms.FieldsForm):
upassword = ff.StringField(widget=wdg.PasswordInput(), required=True)
class ForgottenPasswordRequestView(form.FormViewMixIn, StartupView):
id = 'forgottenpasswordrequest'
def call(self):
def check_key(self):
try:
key = decrypt(self.req.form['key'], self.vreg.config['cypher-seed'])
return decrypt(self.req.form['key'], self.vreg.config['cypher-seed'])
except:
msg = self.req._(u'Invalid link. Please try again.')
raise Redirect(self.req.build_url(u'forgottenpassword', __message=msg))
def call(self):
key = self.check_key()
form = self.vreg['forms'].select('forgottenpasswordrequest', self.req)
form.form_add_hidden('use_email', key['use_email'])
form.form_add_hidden('revocation_id', key['revocation_id'])
......@@ -143,6 +149,7 @@ class ForgottenPasswordRequestConfirm(controller.Controller):
raise ValidationError(None, errors)
return data
# Monkey Patching
# ---------------
......@@ -158,47 +165,21 @@ def forgotpwd_send_email(self, data):
revocation_id = u''.join([random.choice(string.letters+string.digits) for x in range(10)])
revocation_date = datetime.now() + timedelta(minutes=revocation_limit)
try:
rset = session.execute('Any U, F, L WHERE U is CWUser, U primary_email E, E address %(email)s, U firstname F, U surname L',
{'email': data['use_email']})
if rset:
user = rset.get_entity(0,0)
firstname, lastname = rset[0][1], rset[0][2]
try:
rset = session.execute('INSERT Fpasswd X: X revocation_id %(a)s, X revocation_date %(b)s',
{'a':revocation_id, 'b':revocation_date})
session.execute('SET U has_fpasswd F WHERE U eid %(ueid)s, Y eid %(feid)s',
{'ueid':user.eid, 'feid':rset.get_entity(0,0).eid})
session.commit()
except:
msg = session._(u'You have already ask for a new password.')
raise CubicWebException
else:
msg = session._(u'An error occured, this email is unknown.')
raise CubicWebException
# send email
existing_requests = session.execute('Any F WHERE U primary_email E, E address %(e)s, U has_fpasswd F',
{'e': data['use_email']})
if existing_requests:
raise ValidationError(None, {None: session._('You have already asked for a new password.')})
rset = session.execute('INSERT Fpasswd X: X revocation_id %(a)s, X revocation_date %(b)s, '
'U has_fpasswd X WHERE U primary_email E, E address %(e)s',
{'a':revocation_id, 'b':revocation_date, 'e': data['use_email']})
if not rset:
raise ValidationError(None, {None: session._(u'An error occured, this email address is unknown.')})
data['revocation_id'] = revocation_id
key = encrypt(data, session.vreg.config['cypher-seed'])
url = session.build_url('forgottenpasswordrequest', key=key)
subject = session._(u'Request to change your password')
content = session._(u'''
There was recently a request to change the password on your account.
If you requested this password change, please set a new password by following
the link below:
%(url)s
If you do not want to change your password, you may ignore this message. The
link expires in %(limit)d minutes.
See you soon on %(base_url)s !
''') % {'url':url, 'limit':revocation_limit,'base_url':session.base_url()}
email = format_mail({}, [data['use_email']], content=content, subject=subject, config=session.vreg.config)
session.vreg.config.sendmails([(email, (data['use_email'],))])
msg = session._(u'An email has been sent, follow instructions in there to change your password.')
return msg
except CubicWebException:
return msg
session.set_shared_data('resetlink', url)
# mail is sent on commit
session.commit()
finally:
session.close()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment