# -*- coding: utf-8 -*-
#######################################################################################
# Plinn - http://plinn.org #
-# Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
+# © 2005-2013 Benoît PIN <pin@cri.ensmp.fr> #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
#######################################################################################
-""" Plinn registration tool: implements 3 modes to register members :
+""" Plinn registration tool: implements 3 modes to register members:
anonymous, manager, reviewed.
from Products.CMFDefault.RegistrationTool import RegistrationTool as BaseRegistrationTool
from AccessControl import ClassSecurityInfo, ModuleSecurityInfo
from AccessControl.Permission import Permission
+from BTrees.OOBTree import OOBTree
from Products.CMFCore.permissions import ManagePortal, AddPortalMember
from Products.CMFCore.exceptions import AccessControl_Unauthorized
from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.utils import getUtilityByInterfaceName
from Products.GroupUserFolder.GroupsToolPermissions import ManageGroups
+from Products.Plinn.utils import Message as _
+from DateTime import DateTime
from types import TupleType, ListType
+from uuid import uuid4
security = ModuleSecurityInfo('Products.Plinn.RegistrationTool')
MODE_ANONYMOUS = 'anonymous'
def __init__(self) :
self._mode = MODE_ANONYMOUS
self._chain = ''
+ self._passwordResetRequests = OOBTree()
security.declareProtected(ManagePortal, 'configureTool')
def configureTool(self, registration_mode, chain, REQUEST=None) :
""" notify member creation """
member.notifyWorkflowCreated()
member.indexObject()
+
+
+ security.declarePublic('requestPasswordReset')
+ def requestPasswordReset(self, userid):
+ """ add uuid / (userid, expiration) pair and return uuid """
+ self.clearExpiredPasswordResetRequests()
+ mtool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IMembershipTool')
+ if mtool.getMemberById(userid) :
+ uuid = str(uuid4())
+ self._passwordResetRequests[uuid] = (userid, DateTime() + 1)
+ return uuid
+
+ security.declarePrivate('clearExpiredPasswordResetRequests')
+ def clearExpiredPasswordResetRequests(self):
+ now = DateTime()
+ for uuid, record in self._passwordResetRequest.items() :
+ userid, date = record
+ if date < now :
+ del self._passwordResetRequests[uuid]
+
+
+ security.declarePublic('resetPassword')
+ def resetPassword(self, userid, uuid, password, confirm) :
+ record = self._passwordResetRequests.get(uuid)
+ if not record :
+ return _('Invalid reset password request.')
+
+ recUserid, expiration = record
+
+ if recUserid != userid :
+ return _('Invalid userid.')
+
+ if expiration < now :
+ self.clearExpiredPasswordResetRequests()
+ return _('Your reset password request has expired. You can ask a new one.')
+
+ msg = self.testPasswordValidity(password, confirm=confirm)
+ if not msg : # None if everything ok. Err message otherwise.
+ mtool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IMembershipTool')
+ member = mtool.getMemberById(userid)
+ if member :
+ member.setSecurityProfile(password=password)
+ del self._passwordResetRequests[uuid]
+ return _('Password successfully resetted.')
+ else :
+ return _('"%s" username not found.') % userid
+
InitializeClass(RegistrationTool)
\ No newline at end of file
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="here/main_template/macros/master">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
</head>
-<body>
-<div metal:fill-slot="main_no_tabs" i18n:domain="cmf_default">
-<div class="Desktop">
-<h1 class="Desktop" i18n:translate="">Log in</h1>
-
-<form action="" method="post" tal:attributes="action string:${here/portal_url}/logged_in">
-<input type="hidden" name="noAjax" value="1" />
-
-<!-- ****** Enable the automatic redirect ***** -->
-<span tal:condition="exists: request/came_from">
- <input type="hidden" name="came_from" value=""
- tal:attributes="value request/came_from" />
-</span>
-<!-- ****** Enable the automatic redirect ***** -->
-<input type="hidden" name="just_login" value="True" />
-<table class="FormLayout">
-<tr>
- <td align="left" valign="top">
- <strong i18n:translate="user_name">Login</strong>
+ <body>
+ <div metal:fill-slot="main_no_tabs" i18n:domain="cmf_default">
+ <div id="Desktop">
+ <h1 i18n:translate="">Log in</h1>
+ <form action="" method="post" tal:attributes="action string:${here/portal_url}/logged_in">
+ <input type="hidden" name="noAjax" value="1"/>
+ <!-- ****** Enable the automatic redirect ***** -->
+ <span tal:condition="exists: request/came_from">
+ <input type="hidden" name="came_from" value="" tal:attributes="value request/came_from"/>
+ </span>
+ <!-- ****** Enable the automatic redirect ***** -->
+ <input type="hidden" name="just_login" value="True"/>
+ <table class="TwoColumnForm">
+ <tr>
+ <th i18n:translate="user_name">Login</th>
+ <td>
+ <input type="text" name="__ac_name" size="20" value="" tal:attributes="value python: request.get('__ac_name') or ''"/>
</td>
- <td align="left" valign="top">
- <input type="text" name="__ac_name" size="20" value=""
- tal:attributes="value python: request.get('__ac_name') or ''" />
- </td>
-</tr>
-<tr>
- <td align="left" valign="top">
- <strong i18n:translate="">Password</strong>
- </td>
- <td align="left" valign="top">
- <input type="password" name="__ac_password" size="20" />
- </td>
-</tr>
-
-<tr valign="top" align="left">
-<td></td>
-<td><input type="checkbox" name="__ac_persistent" value="1" checked="checked"
- id="cb_remember" />
-<label for="cb_remember" i18n:translate="">Remember my name.</label>
-</td></tr>
-
-<tr>
- <td align="left" valign="top">
- </td>
- <td align="left" valign="top">
- <input type="submit" name="submit" value=" Login "
- i18n:attributes="value" />
- </td>
-</tr>
-
-</table>
-</form>
-
-<p><a href=""
- tal:attributes="href string:${here/portal_url}/mail_password_form"
- i18n:translate=""
- >Forgot your password?</a>
-</p>
-
-<p i18n:translate="">Having trouble logging in? Make sure to enable cookies in
- your web browser.
-</p>
-<p i18n:translate="">Don't forget to logout or exit your browser when you're
- done.
-</p>
-
-<p i18n:translate="">Setting the 'Remember my name' option will set a cookie
- with your username, so that when you next log in, your user name will
- already be filled in for you.
-</p>
-</div>
-</div>
-</body>
+ </tr>
+ <tr>
+ <th i18n:translate="">Password</th>
+ <td>
+ <input type="password" name="__ac_password" size="20"/>
+ </td>
+ </tr>
+ <tr>
+ <td><br/></td>
+ <td>
+ <input type="checkbox" name="__ac_persistent" value="1" checked="checked" id="cb_remember"/>
+ <label for="cb_remember" i18n:translate="">Remember my name.</label>
+ </td>
+ </tr>
+ <tr>
+ <td><br/></td>
+ <td>
+ <input type="submit" name="submit" value=" Login " i18n:attributes="value"/>
+ </td>
+ </tr>
+ </table>
+ </form>
+ <!-- <p>
+ <a href="" tal:attributes="href string:${here/portal_url}/request_password_reset_form" i18n:translate="">Forgot your password?</a>
+ </p> -->
+ <p i18n:translate="">
+ Having trouble logging in? Make sure to enable cookies in your web
+ browser.
+ </p>
+ <p i18n:translate="">
+ Don't forget to logout or exit your browser when you're done.
+ </p>
+ <p i18n:translate="">
+ Setting the 'Remember my name' option will set a cookie with your
+ username, so that when you next log in, your user name will already be
+ filled in for you.
+ </p>
+ </div>
+ </div>
+ </body>
</html>
-
--- /dev/null
+<html xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ metal:use-macro="here/main_template/macros/master">
+ <head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
+ </head>
+ <body>
+ <div metal:fill-slot="main_no_tabs" i18n:domain="plinn">
+ <div id="Desktop" tal:define="ptool here/portal_properties">
+ <h1 i18n:translate="">Password reset</h1>
+ <p i18n:translate="">
+ Enter your username below and click on the "Send" button. You will
+ receive an email with a link to reset your password.
+ </p>
+ <p i18n:translate="">
+ If this will not work for you (for example, if you forget your
+ username or didn't enter your email address) send email to <a
+ tal:attributes="href string:mailto:${ptool/email_from_address}"
+ tal:content="ptool/email_from_address" href="mailto:me@here.com"
+ i18n:name="admin_email">me@here.com</a>.
+ </p>
+ <form action="mail_password" tal:attributes="action string:${here/portal_url}/mail_password">
+ <input name="userid"/>
+ <input type="submit" value=" Send " i18n:attributes="value"/>
+ </form>
+ </div>
+ </div>
+ </body>
+</html>