Commit c194772a authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki Committed by Vincent Pelletier

erp5_credential: migrate to ERP5 Login authentication.

parent cd9feb3c
......@@ -4,7 +4,7 @@ send the password reset link by mail
portal = context.getPortalObject()
person = context.getDestinationDecisionValue(portal_type="Person")
reference = person.getReference()
reference = context.getReference()
if context.hasDocumentReference():
message_reference = context.getDocumentReference()
else:
......
......@@ -4,13 +4,14 @@ send the username mail
portal = context.getPortalObject()
person_list = context.getDestinationDecisionValueList(portal_type="Person")
usernames = []
login_list = []
for person in person_list:
usernames.append("%s" %person.getReference())
for login in person.objectValues(portal_type='ERP5 Login'):
if login.getValidationState() == 'validated':
login_list.append(login)
usernames = " ".join(usernames)
usernames = ' '.join(login.getReference() for login in login_list)
reference_list = [x.getReference() for x in person_list]
if context.hasDocumentReference():
message_reference = context.getDocumentReference()
else:
......
......@@ -12,27 +12,35 @@ portal = context.getPortalObject()
portal_preferences = context.portal_preferences
person = context.getDestinationDecisionValue(portal_type="Person")
login_list = [x for x in person.objectValues(portal_type='ERP5 Login') \
if x.getValidationState() == 'validated']
if len(login_list):
login = login_list[0]
else:
login = person.newContent(portal_type='ERP5 Login')
# Create user of the person only if not exist
user_id = person.Person_getUserId()
if user_id and person.hasPassword():
if user_id and login.hasPassword():
return user_id, None
# Set login
login = context.getReference()
if not person.hasReference():
if not login:
reference = context.getReference()
if not login.hasReference():
if not reference:
raise ValueError, "Impossible to create an account without login"
person.setReference(login)
login.setReference(reference)
if not person.hasReference():
person.setReference(reference)
else:
login = person.getReference()
reference = person.getReference()
password = None
# Set password if no password on the person
if not person.getPassword():
# Set password if no password on the Login
if not login.hasPassword():
if context.getPassword():
#User has fill a password
password = context.getPassword()
person.setEncodedPassword(password)
login.setEncodedPassword(password)
else:
if not portal_preferences.isPreferredSystemGeneratePassword():
# user will set it trough a credential recovery process
......@@ -40,24 +48,27 @@ if not person.getPassword():
module = portal.getDefaultModule(portal_type='Credential Recovery')
credential_recovery = module.newContent(
portal_type="Credential Recovery",
reference=login,
reference=reference,
destination_decision=person.getRelativeUrl(),
language=portal.Localizer.get_selected_language())
credential_recovery.submit()
else:
# system should generate a password
password = context.Person_generatePassword(alpha=5, numeric=3)
person.setPassword(password)
login.setPassword(password)
# create a global account
if context.ERP5Site_isSingleSignOnEnable():
#The master manage encoded password and clear password
person.Person_createNewGlobalUserAccount(password=password)
person.Person_validateGlobalUserAccount()
if login.getValidationState() == 'draft':
login.validate()
else:
#Person has an already an account
if context.ERP5Site_isSingleSignOnEnable():
#Check assignment for the current instance
person.Person_validateGlobalUserAccount()
return login, password
return reference, password
......@@ -4,5 +4,30 @@ Clear 'erp5_content_short' cache too."""
person = context.getDestinationDecisionValue(portal_type="Person")
if context.getPassword():
person.setEncodedPassword(context.getPassword())
login_list = person.objectValues(portal_type='ERP5 Login')
if login_list:
reference = context.getReference()
login_list = [login for login in person.objectValues(portal_type='ERP5 Login') \
if login.getValidationState() == 'validated']
if reference:
for login in login_list:
if login.getReference() == reference:
break
else:
raise RuntimeError, 'Person %s does not have a validated Login with reference %r' % \
(person.getRelativeUrl(), reference)
else: # BBB when login reference is not set in Credential Update document.
if login_list:
user_id = person.Person_getUserId()
login = sorted(login_list,
key=lambda x:x.getReference() == user_id, reverse=True)[0]
else:
raise RuntimeError, 'Person %s does not have a validated Login with reference %r' % \
(person.getRelativeUrl(), reference)
else:
# BBB
login = person
login.setEncodedPassword(context.getPassword())
context.portal_caches.clearCache(('erp5_content_short',))
return login.getReference()
......@@ -40,18 +40,20 @@ if default_email_text is not None:
else:
# Case for recovery of password
if person_list is None:
person_module = portal.getDefaultModule('Person')
result = person_module.searchFolder(reference={'query':reference, 'key':'ExactMatch'})
if len(result) != 1:
user_list = context.acl_users.searchUsers(
login=reference,
login_portal_type='ERP5 Login',
exact_match=True,
)
if len(user_list) != 1:
portal_status_message = portal.Base_translateString("Can't find corresponding person, it's not possible to recover your credentials.")
if web_site is not None:
return web_site.Base_redirect('', keep_items = dict(portal_status_message=portal_status_message ))
return portal.Base_redirect('', keep_items = dict(portal_status_message=portal_status_message ))
person_list = [result[0].getObject(),]
person = portal.restrictedTraverse(user_list[0]['path'])
else:
person = person_list[0]
# Check the response
person = person_list[0]
question_free_text = person.getDefaultCredentialQuestionQuestionFreeText()
question_title = person.getDefaultCredentialQuestionQuestionTitle()
question_answer = person.getDefaultCredentialQuestionAnswer()
......@@ -64,13 +66,13 @@ else:
if (question_title or question_free_text) and (answer == question_answer):
createCredentialRecovery(reference=reference,
default_credential_question_answer=default_credential_question_answer,
destination_decision_value_list=person_list,
destination_decision_value=person,
document_reference=document_reference,
language=portal.Localizer.get_selected_language())
elif (question_free_text is None and question_answer is None) or \
not portal_preferences.isPreferredAskCredentialQuestion():
createCredentialRecovery(reference=reference,
destination_decision_value_list=person_list,
destination_decision_value=person,
document_reference=document_reference,
language=portal.Localizer.get_selected_language())
else:
......
......@@ -45,7 +45,8 @@ credential_request.reindexObject(activate_kw=dict(tag='Person_setReference_%s' %
if not context.portal_membership.isAnonymousUser():
person = context.ERP5Site_getAuthenticatedMemberPersonValue()
destination_decision = []
if person.getReference() == reference:
if reference in [x.getReference() for x in person.objectValues(portal_type='ERP5 Login')
if x.getValidationState() == 'validated']:
destination_decision.append(person.getRelativeUrl())
if person.getDefaultCareerSubordinationTitle() == corporate_name:
destination_decision.append(person.getDefaultCareerSubordination())
......
"""Create a credential update in relation with the person object of current user"""
portal = context.getPortalObject()
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()
user = portal.portal_membership.getAuthenticatedMember()
person = user.getUserValue()
login = user.getLoginValue()
if person is None:
portal_status_message = "Can't find corresponding person, it's not possible to update your credentials."
elif login is None:
portal_status_message = "Can't find corresponding login, it's not possible to update your credentials."
else:
# create the credential update
module = portal.getDefaultModule(portal_type='Credential Update')
credential_update = module.newContent(
portal_type="Credential Update",
reference=login.getReference(),
first_name=first_name,
last_name=last_name,
gender=gender,
......@@ -44,10 +49,11 @@ else:
# within same transaction and update client side credentials cookie
username = person.getReference()
if password and username == str(portal.portal_membership.getAuthenticatedMember()):
credential_update.accept()
# The password is updated synchronously and the the rest of the credential Update is done later
login_reference = credential_update.Credential_updatePersonPassword()
portal.cookie_authentication.credentialsChanged(
person.Person_getUserId(),
username,
login_reference,
password,
)
portal_status_message = "Password changed."
......
......@@ -322,7 +322,6 @@ class TestERP5Credential(ERP5TypeTestCase):
from Products.PluggableAuthService.interfaces.plugins import\
IAuthenticationPlugin
uf = self.getUserFolder()
self.assertNotEquals(uf.getUserById(login, None), None)
for plugin_name, plugin in uf._getOb('plugins').listPlugins(
IAuthenticationPlugin):
if plugin.authenticateCredentials(
......@@ -430,6 +429,7 @@ class TestERP5Credential(ERP5TypeTestCase):
credential_update = credential_update_module.newContent(\
first_name='Homie',
last_name='Simpsons', # add a 's' to the end of the last_name
reference='homie',
password='new_password',
default_email_text='homie.simpsons@fox.com',
destination_decision=homie.getRelativeUrl())
......@@ -548,14 +548,21 @@ class TestERP5Credential(ERP5TypeTestCase):
person_module = portal.getDefaultModule('Person')
person = person_module.newContent(title='Barney',
reference='barney',
password='secret',
start_date=DateTime('1970/01/01'),
default_email_text='barney@duff.com')
# create an assignment
assignment = person.newContent(portal_type='Assignment',
function='member')
assignment.open()
# create a login
login = person.newContent(
portal_type='ERP5 Login',
reference=person.getReference() + '-login',
password='secret',
)
login.validate()
sequence.edit(person_reference=person.getReference(),
login_reference=login.getReference(),
default_email_text=person.getDefaultEmailText())
def stepCreateSameEmailPersonList(self, sequence=None, sequence_list=None,
......@@ -572,12 +579,18 @@ class TestERP5Credential(ERP5TypeTestCase):
person_module = portal.getDefaultModule('Person')
person = person_module.newContent(title=reference,
reference=reference,
password='secret',
default_email_text=default_email_text)
# create an assignment
assignment = person.newContent(portal_type='Assignment',
function='member')
assignment.open()
# create a login
login = person.newContent(
portal_type='ERP5 Login',
reference=person.getReference() + '-login',
password='secret',
)
login.validate()
person_list.append(person)
sequence.edit(person_list=person_list,
......@@ -590,11 +603,12 @@ class TestERP5Credential(ERP5TypeTestCase):
'''
portal = self.getPortalObject()
person_reference = sequence["person_reference"]
login_reference = sequence["login_reference"]
person = portal.portal_catalog.getResultValue(portal_type="Person",
reference=person_reference)
sequence.edit(barney=person)
# check barney can log in the system
self._assertUserExists('barney', 'secret')
self._assertUserExists('barney-login', 'secret')
self.login('barney')
from AccessControl import getSecurityManager
self.assertEqual(getSecurityManager().getUser().getIdOrUserName(), person.Person_getUserId())
......@@ -607,7 +621,7 @@ class TestERP5Credential(ERP5TypeTestCase):
# associate it with barney
credential_recovery.setDestinationDecisionValue(person)
credential_recovery.setReference(person.getReference())
credential_recovery.setReference(login_reference)
sequence.edit(credential_recovery=credential_recovery)
def stepCreateCredentialRecoveryForUsername(self, sequence=None, sequence_list=None,
......@@ -635,8 +649,8 @@ class TestERP5Credential(ERP5TypeTestCase):
def stepRequestCredentialRecoveryWithERP5Site_newCredentialRecovery(self,
sequence=None, sequence_list=None, **kw):
person_reference = sequence["person_reference"]
self.portal.ERP5Site_newCredentialRecovery(reference=person_reference)
login_reference = sequence["login_reference"]
self.portal.ERP5Site_newCredentialRecovery(reference=login_reference)
def stepRequestCredentialRecoveryWithERP5Site_newCredentialRecoveryByEmail(
self, sequence=None, sequence_list=None, **kw):
......@@ -656,9 +670,9 @@ class TestERP5Credential(ERP5TypeTestCase):
def stepCreateCredentialRecoveryWithSensitiveAnswer(self, sequence=None,
sequence_list=None, **kw):
person_reference = sequence["person_reference"]
login_reference = sequence["login_reference"]
result = self.portal.ERP5Site_newCredentialRecovery(
reference=person_reference,
reference=login_reference,
default_credential_question_question='credential/library_card_number',
default_credential_question_answer='ABCDeF',
)
......@@ -667,7 +681,7 @@ class TestERP5Credential(ERP5TypeTestCase):
self.tic()
self.login()
result_list = self.portal.portal_catalog(
portal_type='Credential Recovery', reference=person_reference)
portal_type='Credential Recovery', reference=login_reference)
self.assertEqual(1, len(result_list))
credential_recovery = result_list[0]
sequence.edit(credential_recovery=credential_recovery)
......@@ -681,9 +695,9 @@ class TestERP5Credential(ERP5TypeTestCase):
def stepCheckCredentialRecoveryCreation(self, sequence=None,
sequence_list=None, **kw):
person_reference = sequence["person_reference"]
login_reference = sequence["login_reference"]
result_list = self.portal.portal_catalog(
portal_type='Credential Recovery', reference=person_reference)
portal_type='Credential Recovery', reference=login_reference)
self.assertEqual(1, len(result_list))
credential_recovery = result_list[0]
person = credential_recovery.getDestinationDecisionValue()
......@@ -775,8 +789,8 @@ class TestERP5Credential(ERP5TypeTestCase):
self.assertTrue('reset_key' in parameters)
key = parameters['reset_key'][0]
# before changing, check that the user exists with 'secret' password
self._assertUserExists('barney', 'secret')
self.portal.portal_password.changeUserPassword(user_login="barney",
self._assertUserExists('barney-login', 'secret')
self.portal.portal_password.changeUserPassword(user_login="barney-login",
password="new_password",
password_confirm="new_password",
password_key=key)
......@@ -784,10 +798,10 @@ class TestERP5Credential(ERP5TypeTestCase):
# reset the cache
self.portal.portal_caches.clearAllCache()
# check we cannot login anymore with the previous password 'secret'
self._assertUserDoesNotExists('barney', 'secret')
self._assertUserDoesNotExists('barney-login', 'secret')
# check we can now login with the new password 'new_password'
self._assertUserExists('barney', 'new_password')
self._assertUserExists('barney-login', 'new_password')
def _createCredentialRequest(self, first_name="Barney",
last_name="Simpson",
......@@ -833,13 +847,13 @@ class TestERP5Credential(ERP5TypeTestCase):
def stepSetAssigneeRoleToCurrentPersonInCredentialUpdateModule(self,
sequence=None, sequence_list=None, **kw):
user, = self.portal.acl_users.searchUsers(login=sequence['person_reference'], exact_match=True)
user, = self.portal.acl_users.searchUsers(login=sequence['login_reference'], exact_match=True)
self.portal.credential_update_module.manage_setLocalRoles(user['id'],
['Assignor',])
def stepSetAssigneeRoleToCurrentPersonInCredentialRecoveryModule(self,
sequence=None, sequence_list=None, **kw):
user, = self.portal.acl_users.searchUsers(login=sequence['person_reference'], exact_match=True)
user, = self.portal.acl_users.searchUsers(login=sequence['login_reference'], exact_match=True)
self.portal.credential_recovery_module.manage_setLocalRoles(user['id'],
['Assignor',])
......@@ -1233,10 +1247,16 @@ class TestERP5Credential(ERP5TypeTestCase):
reference = self.id()
person = self.portal.person_module.newContent(portal_type='Person',
reference=reference,
password='secret',
role='internal')
assignment = person.newContent(portal_type='Assignment', function='manager')
assignment.open()
# create a login
login = person.newContent(
portal_type='ERP5 Login',
reference=person.getReference() + '-login',
password='secret',
)
login.validate()
self.commit()
credential_update = self.portal.credential_update_module.newContent(
portal_type='Credential Update',
......@@ -1254,13 +1274,20 @@ class TestERP5Credential(ERP5TypeTestCase):
person_module = self.portal.getDefaultModule('Person')
person = person_module.newContent(title='Barney',
reference='barney',
password='secret',
default_email_text='barney@duff.com')
# create an assignment
assignment = person.newContent(portal_type='Assignment',
function='member')
assignment.open()
sequence.edit(person_reference=person.getReference())
# create a login
login = person.newContent(
portal_type='ERP5 Login',
reference=person.getReference() + '-login',
password='secret',
)
login.validate()
sequence.edit(person_reference=person.getReference(),
login_reference=login.getReference())
def test_checkCredentialQuestionIsNotCaseSensitive(self):
'''
......
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