Commit 66afc0bb authored by Jérome Perrin's avatar Jérome Perrin

Password tool was not supporting simultaneous password reset.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@26094 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 6bb77299
...@@ -33,12 +33,12 @@ from Globals import InitializeClass, DTMLFile, get_request ...@@ -33,12 +33,12 @@ from Globals import InitializeClass, DTMLFile, get_request
from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5 import _dtmldir from Products.ERP5 import _dtmldir
from zLOG import LOG from zLOG import LOG, INFO
import time, random, md5 import time, random, md5
from DateTime import DateTime from DateTime import DateTime
from Products.ERP5Type.Message import translateString from Products.ERP5Type.Message import translateString
from Acquisition import aq_base from Acquisition import aq_base
from BTrees.OOBTree import OOBTree from Globals import PersistentMapping
class PasswordTool(BaseTool): class PasswordTool(BaseTool):
""" """
...@@ -61,7 +61,7 @@ class PasswordTool(BaseTool): ...@@ -61,7 +61,7 @@ class PasswordTool(BaseTool):
password_request_dict = {} password_request_dict = {}
def __init__(self): def __init__(self):
self.password_request_dict = OOBTree() self.password_request_dict = PersistentMapping()
def mailPasswordResetRequest(self, user_login=None, REQUEST=None): def mailPasswordResetRequest(self, user_login=None, REQUEST=None):
""" """
...@@ -88,8 +88,17 @@ class PasswordTool(BaseTool): ...@@ -88,8 +88,17 @@ class PasswordTool(BaseTool):
url = "%s/portal_password/resetPassword?reset_key=%s" %(self.getPortalObject().absolute_url() , random_url) url = "%s/portal_password/resetPassword?reset_key=%s" %(self.getPortalObject().absolute_url() , random_url)
# generate expiration date # generate expiration date
expiration_date = DateTime() + self._expiration_day expiration_date = DateTime() + self._expiration_day
# XXX before r26093, password_request_dict was initialized by an OOBTree and
# replaced by a dict on each request, so if it's data structure is not up
# to date, we update it if needed
if not isinstance(self.password_request_dict, PersistentMapping):
LOG('ERP5.PasswordTool', INFO, 'Updating password_request_dict to'
' PersistentMapping')
self.password_request_dict = PersistentMapping()
# register request # register request
self.password_request_dict = {random_url : (user_login, expiration_date)} self.password_request_dict[random_url] = (user_login, expiration_date)
# send mail # send mail
subject = "[%s] Reset of your password" %(self.getPortalObject().getTitle()) subject = "[%s] Reset of your password" %(self.getPortalObject().getTitle())
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
############################################################################## ##############################################################################
import unittest import unittest
import transaction
from Testing import ZopeTestCase from Testing import ZopeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
...@@ -337,6 +338,64 @@ class TestPasswordTool(ERP5TypeTestCase): ...@@ -337,6 +338,64 @@ class TestPasswordTool(ERP5TypeTestCase):
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
sequence_list.play(self, quiet=quiet) sequence_list.play(self, quiet=quiet)
def test_two_concurrent_password_reset(self):
personA = self.portal.person_module.newContent(portal_type="Person",
reference="userA",
password="passwordA",
default_email_text="userA@example.invalid")
assignment = personA.newContent(portal_type='Assignment')
assignment.open()
personB = self.portal.person_module.newContent(portal_type="Person",
reference="userB",
password="passwordB",
default_email_text="userB@example.invalid")
assignment = personB.newContent(portal_type='Assignment')
assignment.open()
transaction.commit()
self.tic()
self._assertUserExists('userA', 'passwordA')
self._assertUserExists('userB', 'passwordB')
self.assertEquals(0, len(self.portal.portal_password.password_request_dict))
self.portal.portal_password.mailPasswordResetRequest(user_login="userA")
self.assertEquals(1, len(self.portal.portal_password.password_request_dict))
key_a = self.portal.portal_password.password_request_dict.keys()[0]
transaction.commit()
self.tic()
self.portal.portal_password.mailPasswordResetRequest(user_login="userB")
possible_key_list =\
self.portal.portal_password.password_request_dict.keys()
self.assertEquals(2, len(possible_key_list))
key_b = [k for k in possible_key_list if k != key_a][0]
transaction.commit()
self.tic()
self._assertUserExists('userA', 'passwordA')
self._assertUserExists('userB', 'passwordB')
self.portal.portal_password.changeUserPassword(user_login="userA",
password="newA",
password_confirmation="newA",
password_key=key_a)
transaction.commit()
self.tic()
self._assertUserExists('userA', 'newA')
self._assertUserExists('userB', 'passwordB')
self.portal.portal_password.changeUserPassword(user_login="userB",
password="newB",
password_confirmation="newB",
password_key=key_b)
transaction.commit()
self.tic()
self._assertUserExists('userA', 'newA')
self._assertUserExists('userB', 'newB')
class TestPasswordToolWithCRM(TestPasswordTool): class TestPasswordToolWithCRM(TestPasswordTool):
""" """
......
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