/kai/controllers/accounts.py

https://bitbucket.org/bbangert/kai/ · Python · 200 lines · 169 code · 26 blank · 5 comment · 21 complexity · 501a18a0c5ae9765f2a881112f534a61 MD5 · raw file

  1. from datetime import datetime
  2. import logging
  3. from pylons import request, response, session, tmpl_context as c, url
  4. from pylons.controllers.util import abort, redirect
  5. from pylons.decorators import rest, secure, jsonify
  6. from kai.lib.base import BaseController, render
  7. from kai.lib.decorators import validate
  8. from kai.lib.helpers import failure_flash, success_flash
  9. from kai.lib.mail import EmailMessage
  10. from kai.model import Human, Paste, Traceback, forms
  11. log = logging.getLogger(__name__)
  12. class AccountsController(BaseController):
  13. def __before__(self):
  14. c.active_tab = True
  15. c.active_sub = True
  16. @rest.dispatch_on(POST='_forgot_password')
  17. def forgot_password(self):
  18. return render('/accounts/forgot_password.mako')
  19. def verify_email(self, token):
  20. users = list(Human.by_email_token(self.db)[token])
  21. if users:
  22. user = users[0]
  23. # If there's a email token issue (change email address), verify
  24. # its still valid
  25. if user.email_token_issue:
  26. diff = datetime.utcnow() - user.email_token_issue
  27. if diff.days > 1:
  28. failure_flash('This e-mail verification token has expired.')
  29. redirect(url('home'))
  30. # Valid e-mail token, remove it and log the user in
  31. user.email_token = user.email_token_issue = None
  32. user.process_login()
  33. success_flash('Your email has been verified, and you have been'
  34. ' logged into PylonsHQ')
  35. redirect(url('home'))
  36. else:
  37. # No valid e-mail token
  38. failure_flash('Invalid e-mail token')
  39. redirect(url('home'))
  40. @validate(form=forms.forgot_password_form, error_handler='forgot_password')
  41. @secure.authenticate_form
  42. def _forgot_password(self):
  43. user = list(Human.by_email(self.db)[self.form_result['email_address']])[0]
  44. user.password_token = user.generate_token()
  45. c.password_token = user.password_token
  46. user.password_token_issue = datetime.utcnow()
  47. user.store(self.db)
  48. message = EmailMessage(subject="PylonsHQ - Lost Password",
  49. body=render('/email/lost_password.mako'),
  50. from_email="PylonsHQ <pylonshq@groovie.org>",
  51. to=[self.form_result['email_address']])
  52. message.send(fail_silently=True)
  53. success_flash('An e-mail has been sent to your account to verify the password reset request.')
  54. redirect(url('account_login'))
  55. @rest.dispatch_on(POST='_change_password')
  56. def change_password(self, token):
  57. c.token = token
  58. users = list(Human.by_password_token(self.db)[token])
  59. if not users:
  60. failure_flash('That password token is no longer valid.')
  61. redirect(url('account_login'))
  62. user = users[0]
  63. diff = datetime.utcnow() - user.password_token_issue
  64. if diff.days > 1 or diff.seconds > 3600:
  65. failure_flash('Password token is no longer valid, please make a new password reset request.')
  66. redirect(url('forgot_password'))
  67. return render('/accounts/change_password.mako')
  68. @validate(form=forms.change_password_form, error_handler='change_password')
  69. @secure.authenticate_form
  70. def _change_password(self, token):
  71. users = list(Human.by_password_token(self.db)[token]) or abort(401)
  72. user = users[0]
  73. diff = datetime.utcnow() - user.password_token_issue
  74. if diff.days > 1 or diff.seconds > 3600:
  75. failure_flash('Password token is no longer valid, please make a new password reset request.')
  76. redirect(url('forgot_password'))
  77. user.password_token = user.password_token_issue = None
  78. user.password = user.hash_password(self.form_result['password'])
  79. user.store(self.db)
  80. success_flash('Your password has been reset successfully')
  81. redirect(url('account_login'))
  82. def logout(self):
  83. c.user.session_id = None
  84. c.user.store(self.db)
  85. session.clear()
  86. session.expire()
  87. session.save()
  88. redir = request.GET.get('redir')
  89. success_flash('You have logged out of your session')
  90. if redir:
  91. redirect(url(str(redir)))
  92. else:
  93. redirect(url('home'))
  94. @rest.dispatch_on(POST='_process_login')
  95. def login(self):
  96. redir = request.GET.get('redir')
  97. if redir and redir.startswith('/') and redir != url('account_login'):
  98. session['redirect'] = str(redir)
  99. session.save()
  100. return render('/accounts/login.mako')
  101. @validate(form=forms.login_form, error_handler='login')
  102. @secure.authenticate_form
  103. def _process_login(self):
  104. user = self.form_result['user']
  105. user.process_login()
  106. success_flash('You have logged into PylonsHQ')
  107. if session.get('redirect'):
  108. redir_url = session.pop('redirect')
  109. session.save()
  110. redirect(url(redir_url))
  111. redirect(url('home'))
  112. @rest.dispatch_on(POST='_process_openid_associate')
  113. def openid_associate(self):
  114. openid_url = session.get('openid_identity')
  115. if not openid_url:
  116. redirect(url('account_register'))
  117. c.openid = openid_url
  118. return render('/accounts/associate.mako')
  119. @validate(form=forms.login_form, error_handler='login')
  120. def _process_openid_associate(self):
  121. openid_url = session.get('openid_identity')
  122. user = self.form_result['user']
  123. if user.openids:
  124. user.openids.append(openid_url)
  125. else:
  126. user.openids = [openid_url]
  127. user.process_login()
  128. success_flash('You have associated your OpenID to your account, and signed in')
  129. if session.get('redirect'):
  130. redir_url = session.pop('redirect')
  131. session.save()
  132. redirect(url(redir_url))
  133. redirect(url('home'))
  134. @rest.dispatch_on(POST='_process_openid_registration')
  135. def openid_register(self):
  136. openid_url = session.get('openid_identity')
  137. if not openid_url:
  138. redirect(url('account_register'))
  139. c.openid = session.get('openid_identity')
  140. c.defaults = {}
  141. return render('/accounts/register.mako')
  142. @validate(form=forms.openid_registration_form, error_handler='openid_register')
  143. def _process_openid_registration(self):
  144. new_user = Human(displayname=self.form_result['displayname'],
  145. timezone = self.form_result['timezone'],
  146. email=self.form_result['email_address'])
  147. new_user.openids = [session['openid_identity']]
  148. return self._finish_registration(new_user)
  149. @rest.dispatch_on(POST='_process_registration')
  150. def register(self):
  151. return render('/accounts/register.mako')
  152. @validate(form=forms.registration_form, error_handler='register')
  153. @secure.authenticate_form
  154. def _process_registration(self):
  155. new_user = Human(displayname=self.form_result['displayname'],
  156. timezone = self.form_result['timezone'],
  157. email=self.form_result['email_address'])
  158. new_user.password = Human.hash_password(self.form_result['password'])
  159. return self._finish_registration(new_user)
  160. def _finish_registration(self, user):
  161. user.email_token = c.email_token = user.generate_token()
  162. user.email_token_issue = datetime.utcnow()
  163. user.store(self.db)
  164. Paste.associate_pasties(user)
  165. Traceback.associate_tracebacks(user)
  166. # Send out the welcome email with the reg token
  167. message = EmailMessage(subject="PylonsHQ - Registration Confirmation",
  168. body=render('/email/register.mako'),
  169. from_email="PylonsHQ <pylonshq@groovie.org>",
  170. to=[self.form_result['email_address']])
  171. message.send(fail_silently=True)
  172. success_flash("User account '%s' created successfully. An e-mail has"
  173. " been sent to activate your account." % user.displayname)
  174. redirect(url('home'))