Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
iv
erp5
Commits
cd9feb3c
Commit
cd9feb3c
authored
Oct 27, 2016
by
Kazuhiko Shiozaki
Committed by
Vincent Pelletier
Dec 23, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
erp5_authentication_policy: migrate to ERP5 Login authentication.
parent
5ae11aeb
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
204 additions
and
189 deletions
+204
-189
bt5/erp5_authentication_policy/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
...rtalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_analyzePassword.py
...skins/erp5_authentication_policy/Login_analyzePassword.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_analyzePassword.xml
...kins/erp5_authentication_policy/Login_analyzePassword.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_getListboxUrl.py
...l_skins/erp5_authentication_policy/Login_getListboxUrl.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_getListboxUrl.xml
..._skins/erp5_authentication_policy/Login_getListboxUrl.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isLoginBlocked.py
..._skins/erp5_authentication_policy/Login_isLoginBlocked.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isLoginBlocked.xml
...skins/erp5_authentication_policy/Login_isLoginBlocked.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isPasswordExpired.py
...ins/erp5_authentication_policy/Login_isPasswordExpired.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isPasswordExpired.xml
...ns/erp5_authentication_policy/Login_isPasswordExpired.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isPasswordValid.py
...skins/erp5_authentication_policy/Login_isPasswordValid.py
+3
-17
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_isPasswordValid.xml
...kins/erp5_authentication_policy/Login_isPasswordValid.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_notifyLoginFailure.py
...ns/erp5_authentication_policy/Login_notifyLoginFailure.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_notifyLoginFailure.xml
...s/erp5_authentication_policy/Login_notifyLoginFailure.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_notifyPasswordExpire.py
.../erp5_authentication_policy/Login_notifyPasswordExpire.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_notifyPasswordExpire.xml
...erp5_authentication_policy/Login_notifyPasswordExpire.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_unblockLogin.py
...al_skins/erp5_authentication_policy/Login_unblockLogin.py
+0
-0
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Login_unblockLogin.xml
...l_skins/erp5_authentication_policy/Login_unblockLogin.xml
+1
-1
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml
...olicy/SystemEventModule_viewBlockUseLoginList/listbox.xml
+3
-3
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/interactions/changePassword.xml
...word_interaction_workflow/interactions/changePassword.xml
+8
-2
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/afterChangePassword.py
...sword_interaction_workflow/scripts/afterChangePassword.py
+7
-8
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/afterChangePassword.xml
...word_interaction_workflow/scripts/afterChangePassword.xml
+1
-1
bt5/erp5_authentication_policy/bt/template_portal_type_workflow_chain_list
...cation_policy/bt/template_portal_type_workflow_chain_list
+1
-1
bt5/erp5_system_event/SkinTemplateItem/portal_skins/erp5_system_event/PasswordEvent_view/my_destination_title.xml
..._system_event/PasswordEvent_view/my_destination_title.xml
+2
-2
bt5/erp5_system_event/SkinTemplateItem/portal_skins/erp5_system_event/PasswordEvent_view/my_source_title.xml
.../erp5_system_event/PasswordEvent_view/my_source_title.xml
+2
-2
product/ERP5/tests/testAuthenticationPolicy.py
product/ERP5/tests/testAuthenticationPolicy.py
+168
-144
No files found.
bt5/erp5_authentication_policy/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
View file @
cd9feb3c
<workflow_chain>
<chain>
<type>
Perso
n
</type>
<type>
ERP5 Logi
n
</type>
<workflow>
password_interaction_workflow
</workflow>
</chain>
</workflow_chain>
\ No newline at end of file
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_analyzePassword.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_analyzePassword.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_analyzePassword.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_analyzePassword.xml
View file @
cd9feb3c
...
...
@@ -62,7 +62,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_analyzePassword
</string>
</value>
<value>
<string>
Logi
n_analyzePassword
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_getListboxUrl.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_getListboxUrl.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_getListboxUrl.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_getListboxUrl.xml
View file @
cd9feb3c
...
...
@@ -54,7 +54,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_getListboxUrl
</string>
</value>
<value>
<string>
Logi
n_getListboxUrl
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_isLoginBlocked.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_isLoginBlocked.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_isLoginBlocked.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_isLoginBlocked.xml
View file @
cd9feb3c
...
...
@@ -62,7 +62,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_isLoginBlocked
</string>
</value>
<value>
<string>
Logi
n_isLoginBlocked
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_isPasswordExpired.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_isPasswordExpired.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_isPasswordExpired.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_isPasswordExpired.xml
View file @
cd9feb3c
...
...
@@ -62,7 +62,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_isPasswordExpired
</string>
</value>
<value>
<string>
Logi
n_isPasswordExpired
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Base
_isPasswordValid.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Login
_isPasswordValid.py
View file @
cd9feb3c
...
...
@@ -13,27 +13,13 @@ message_dict = { 0: 'Unknown error',
-
4
:
'You have already used this password.'
,
-
5
:
'You can not use any parts of your first and last name in password.'
}
def
doValidation
(
perso
n
,
password
):
def
doValidation
(
logi
n
,
password
):
# raise so Formulator shows proper message
result_code_list
=
person
.
Person_
analyzePassword
(
password
)
result_code_list
=
login
.
analyzePassword
(
password
)
if
result_code_list
!=
[]:
translateString
=
context
.
Base_translateString
message
=
' '
.
join
([
translateString
(
message_dict
[
x
])
for
x
in
result_code_list
])
raise
ValidationError
(
'external_validator_failed'
,
context
,
error_text
=
message
)
return
1
user_login
=
request
.
get
(
'field_user_login'
,
None
)
# find Person object (or authenticated member) and validate it on it (password recovered for an existing account)
person
=
context
.
ERP5Site_getAuthenticatedMemberPersonValue
(
user_login
)
if
person
is
not
None
:
return
doValidation
(
person
,
password
)
# use a temp object (new account created)
first_name
=
request
.
get
(
'field_your_first_name'
,
None
)
last_name
=
request
.
get
(
'field_your_last_name'
,
None
)
kw
=
{
'title'
:
'%s %s'
%
(
first_name
,
last_name
),
'first_name'
:
first_name
,
'last_name'
:
last_name
}
person
=
newTempBase
(
portal
,
kw
[
'title'
],
**
kw
)
return
doValidation
(
person
,
password
)
return
doValidation
(
context
,
password
)
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Base
_isPasswordValid.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Login
_isPasswordValid.xml
View file @
cd9feb3c
...
...
@@ -62,7 +62,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Base
_isPasswordValid
</string>
</value>
<value>
<string>
Login
_isPasswordValid
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_notifyLoginFailure.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_notifyLoginFailure.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_notifyLoginFailure.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_notifyLoginFailure.xml
View file @
cd9feb3c
...
...
@@ -63,7 +63,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_notifyLoginFailure
</string>
</value>
<value>
<string>
Logi
n_notifyLoginFailure
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_notifyPasswordExpire.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_notifyPasswordExpire.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_notifyPasswordExpire.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_notifyPasswordExpire.xml
View file @
cd9feb3c
...
...
@@ -63,7 +63,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_notifyPasswordExpire
</string>
</value>
<value>
<string>
Logi
n_notifyPasswordExpire
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_unblockLogin.py
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_unblockLogin.py
View file @
cd9feb3c
File moved
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Perso
n_unblockLogin.xml
→
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/
Logi
n_unblockLogin.xml
View file @
cd9feb3c
...
...
@@ -54,7 +54,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Perso
n_unblockLogin
</string>
</value>
<value>
<string>
Logi
n_unblockLogin
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml
View file @
cd9feb3c
...
...
@@ -174,15 +174,15 @@
<list>
<tuple>
<string>
title
</string>
<string>
Perso
n_getListboxUrl
</string>
<string>
Logi
n_getListboxUrl
</string>
</tuple>
<tuple>
<string>
reference
</string>
<string>
Perso
n_getListboxUrl
</string>
<string>
Logi
n_getListboxUrl
</string>
</tuple>
<tuple>
<string>
count
</string>
<string>
Perso
n_getListboxUrl
</string>
<string>
Logi
n_getListboxUrl
</string>
</tuple>
</list>
</value>
...
...
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/interactions/changePassword.xml
View file @
cd9feb3c
...
...
@@ -28,7 +28,7 @@
<key>
<string>
after_script_name
</string>
</key>
<value>
<list>
<string>
Person_c
hangePassword
</string>
<string>
afterC
hangePassword
</string>
</list>
</value>
</item>
...
...
@@ -72,10 +72,16 @@
<key>
<string>
portal_type_filter
</string>
</key>
<value>
<list>
<string>
Perso
n
</string>
<string>
ERP5 Logi
n
</string>
</list>
</value>
</item>
<item>
<key>
<string>
portal_type_group_filter
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
script_name
</string>
</key>
<value>
...
...
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/
Person_c
hangePassword.py
→
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/
afterC
hangePassword.py
View file @
cd9feb3c
from
DateTime
import
DateTime
portal
=
context
.
getPortalObject
()
person
=
state_change
[
'object'
]
login
=
state_change
[
'object'
]
portal
=
login
.
getPortalObject
()
# check preferences and save only if set
number_of_last_password_to_check
=
portal
.
portal_preferences
.
getPreferredNumberOfLastPasswordToCheck
()
if
number_of_last_password_to_check
is
not
None
and
number_of_last_password_to_check
:
# save password and modification date
current_password
=
perso
n
.
getPassword
()
current_password
=
logi
n
.
getPassword
()
if
current_password
is
not
None
:
password_event
=
portal
.
system_event_module
.
newContent
(
portal_type
=
'Password Event'
,
source_value
=
perso
n
,
destination_value
=
perso
n
,
password
=
current_password
)
password_event
=
portal
.
system_event_module
.
newContent
(
portal_type
=
'Password Event'
,
source_value
=
logi
n
,
destination_value
=
logi
n
,
password
=
current_password
)
password_event
.
confirm
()
# Person_isPasswordExpired cache the wrong result if document is not in catalog.
# As the document is created in the same transaction, it is possible to force reindexation
...
...
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/
Person_c
hangePassword.xml
→
bt5/erp5_authentication_policy/WorkflowTemplateItem/portal_workflow/password_interaction_workflow/scripts/
afterC
hangePassword.xml
View file @
cd9feb3c
...
...
@@ -63,7 +63,7 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Person_c
hangePassword
</string>
</value>
<value>
<string>
afterC
hangePassword
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/erp5_authentication_policy/bt/template_portal_type_workflow_chain_list
View file @
cd9feb3c
Person | password_interaction_workflow
\ No newline at end of file
ERP5 Login | password_interaction_workflow
\ No newline at end of file
bt5/erp5_system_event/SkinTemplateItem/portal_skins/erp5_system_event/PasswordEvent_view/my_destination_title.xml
View file @
cd9feb3c
...
...
@@ -102,8 +102,8 @@
<value>
<list>
<tuple>
<string>
Perso
n
</string>
<string>
Perso
n
</string>
<string>
ERP5 Logi
n
</string>
<string>
ERP5 Logi
n
</string>
</tuple>
</list>
</value>
...
...
bt5/erp5_system_event/SkinTemplateItem/portal_skins/erp5_system_event/PasswordEvent_view/my_source_title.xml
View file @
cd9feb3c
...
...
@@ -102,8 +102,8 @@
<value>
<list>
<tuple>
<string>
Perso
n
</string>
<string>
Perso
n
</string>
<string>
ERP5 Logi
n
</string>
<string>
ERP5 Logi
n
</string>
</tuple>
</list>
</value>
...
...
product/ERP5/tests/testAuthenticationPolicy.py
View file @
cd9feb3c
...
...
@@ -66,10 +66,12 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
reference
=
'test'
)
if
portal
.
portal_catalog
.
getResultValue
(
**
kw
)
is
None
:
# add a loggable Person
person
=
portal
.
person_module
.
newContent
(
password
=
'test'
,
first_name
=
'First'
,
last_name
=
'Last'
,
**
kw
)
person
=
self
.
createUser
(
kw
[
'reference'
],
password
=
'test'
,
person_kw
=
{
'first_name'
:
'First'
,
'last_name'
:
'Last'
},
)
person
.
validate
()
assignment
=
person
.
newContent
(
portal_type
=
'Assignment'
)
assignment
.
open
()
...
...
@@ -91,16 +93,33 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
'erp5_content_short'
,
# for authentication cache
))
def
_getPasswordEventList
(
self
,
perso
n
):
def
_getPasswordEventList
(
self
,
logi
n
):
return
[
x
.
getObject
()
for
x
in
self
.
portal
.
portal_catalog
(
portal_type
=
'Password Event'
,
default_destination_uid
=
perso
n
.
getUid
(),
default_destination_uid
=
logi
n
.
getUid
(),
sort_on
=
((
'creation_date'
,
'DESC'
,),))]
def
_cleanUp
Person
(
self
,
perso
n
):
self
.
portal
.
system_event_module
.
manage_delObjects
([
x
.
getId
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
def
_cleanUp
Login
(
self
,
logi
n
):
self
.
portal
.
system_event_module
.
manage_delObjects
([
x
.
getId
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
def
createUser
(
self
,
reference
,
password
=
None
,
person_kw
=
None
):
"""
Modified version from ERP5TypeTestCase, that does set reference as
password when password is None.
"""
if
person_kw
is
None
:
person_kw
=
{}
person
=
self
.
portal
.
person_module
.
newContent
(
portal_type
=
'Person'
,
reference
=
reference
,
**
person_kw
)
login
=
person
.
newContent
(
portal_type
=
'ERP5 Login'
,
reference
=
reference
,
password
=
password
)
login
.
validate
()
return
person
def
test_01_BlockLogin
(
self
):
"""
Test that a recataloging works for Web Site documents
...
...
@@ -110,73 +129,74 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
person
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'Person'
,
reference
=
'test'
)
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
# login should be allowed
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# file some failures so we should detect and block account
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
self
.
tic
()
# should be blocked
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
# set check back interval to actualy disable blocking
preference
.
setPreferredAuthenticationFailureCheckDuration
(
0
)
self
.
_clearCache
()
self
.
tic
()
time
.
sleep
(
1
)
# we need to give a moment
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# .. and revert it back
preference
.
setPreferredAuthenticationFailureCheckDuration
(
600
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
# increase failures attempts
preference
.
setPreferredMaxAuthenticationFailure
(
4
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# .. and revert it back
preference
.
setPreferredMaxAuthenticationFailure
(
3
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
# set short block interval so we can test it as well
preference
.
setPreferredAuthenticationFailureBlockDuration
(
3
)
self
.
_clearCache
()
self
.
tic
()
time
.
sleep
(
4
)
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# test multiple concurrent transactions without waiting for activities to be over
preference
.
setPreferredAuthenticationFailureCheckDuration
(
600
)
preference
.
setPreferredAuthenticationFailureBlockDuration
(
600
)
preference
.
setPreferredMaxAuthenticationFailure
(
3
)
person
.
Perso
n_unblockLogin
()
login
.
Logi
n_unblockLogin
()
self
.
_clearCache
()
self
.
tic
()
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
self
.
commit
()
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
# test unblock account
person
.
Perso
n_unblockLogin
()
login
.
Logi
n_unblockLogin
()
self
.
tic
()
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
def
test_02_PasswordHistory
(
self
):
...
...
@@ -186,61 +206,61 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
portal
=
self
.
getPortal
()
self
.
assertTrue
(
portal
.
portal_preferences
.
isAuthenticationPolicyEnabled
())
person
=
portal
.
person_module
.
newContent
(
portal_type
=
'Person'
,
reference
=
'test-02'
)
person
=
self
.
createUser
(
'test-02'
)
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
self
.
tic
()
# Check that last (X where X is set in preferences) passwords are saved.
self
.
assertEqual
([],
self
.
_getPasswordEventList
(
perso
n
))
self
.
assertEqual
([],
self
.
_getPasswordEventList
(
logi
n
))
preference
.
setPreferredNumberOfLastPasswordToCheck
(
10
)
self
.
tic
()
self
.
_clearCache
()
perso
n
.
setPassword
(
'12345678'
)
logi
n
.
setPassword
(
'12345678'
)
self
.
tic
()
# password change date should be saved as well hashed old password value
old_password
=
perso
n
.
getPassword
()
self
.
assertSameSet
([
old_password
],
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
old_password
=
logi
n
.
getPassword
()
self
.
assertSameSet
([
old_password
],
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
# .. test one more time to check history of password is saved in a list
perso
n
.
setPassword
(
'123456789'
)
logi
n
.
setPassword
(
'123456789'
)
self
.
tic
()
old_password1
=
perso
n
.
getPassword
()
old_password1
=
logi
n
.
getPassword
()
# password change date should be saved as well hashed old password value
self
.
assertSameSet
([
old_password1
,
old_password
],
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
self
.
assertSameSet
([
old_password1
,
old_password
],
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
# other methods (_setPassword)...
perso
n
.
_setPassword
(
'123456789-1'
)
logi
n
.
_setPassword
(
'123456789-1'
)
self
.
tic
()
old_password2
=
perso
n
.
getPassword
()
old_password2
=
logi
n
.
getPassword
()
self
.
assertSameSet
([
old_password2
,
old_password1
,
old_password
],
\
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
# other methods (_forceSetPassword)...
perso
n
.
_forceSetPassword
(
'123456789-2'
)
logi
n
.
_forceSetPassword
(
'123456789-2'
)
self
.
tic
()
old_password3
=
perso
n
.
getPassword
()
old_password3
=
logi
n
.
getPassword
()
self
.
assertSameSet
([
old_password3
,
old_password2
,
old_password1
,
old_password
],
\
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
# other methods (setEncodedPassword)...
perso
n
.
setEncodedPassword
(
'123456789-3'
)
logi
n
.
setEncodedPassword
(
'123456789-3'
)
self
.
tic
()
old_password4
=
perso
n
.
getPassword
()
old_password4
=
logi
n
.
getPassword
()
self
.
assertSameSet
([
old_password4
,
old_password3
,
old_password2
,
old_password1
,
old_password
],
\
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
# other methods (edit)...
perso
n
.
edit
(
password
=
'123456789-4'
)
logi
n
.
edit
(
password
=
'123456789-4'
)
self
.
tic
()
old_password5
=
perso
n
.
getPassword
()
old_password5
=
logi
n
.
getPassword
()
self
.
assertSameSet
([
old_password5
,
old_password4
,
old_password3
,
old_password2
,
old_password1
,
old_password
],
\
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
perso
n
)])
[
x
.
getPassword
()
for
x
in
self
.
_getPasswordEventList
(
logi
n
)])
def
test_03_PasswordValidity
(
self
):
...
...
@@ -258,105 +278,107 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
assertTrue
(
portal
.
portal_preferences
.
isAuthenticationPolicyEnabled
())
person
=
portal
.
person_module
.
newContent
(
portal_type
=
'Person'
,
reference
=
'test-03'
,
password
=
'test'
,
first_name
=
'First'
,
last_name
=
'Last'
)
person
=
self
.
createUser
(
'test-03'
,
password
=
'test'
,
person_kw
=
{
'first_name'
:
'First'
,
'last_name'
:
'Last'
},
)
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
self
.
tic
()
# by default an empty password if nothing set in preferences is OK
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
''
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
''
))
# Not long enough passwords used
self
.
_cleanUp
Person
(
perso
n
)
self
.
_cleanUp
Login
(
logi
n
)
preference
.
setPreferredMinPasswordLength
(
8
)
preference
.
setPreferredNumberOfLastPasswordToCheck
(
0
)
self
.
tic
()
self
.
_clearCache
()
self
.
assertEqual
([
-
1
],
perso
n
.
analyzePassword
(
''
))
self
.
assertEqual
([
-
1
],
perso
n
.
analyzePassword
(
'1234567'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'12345678'
))
self
.
assertEqual
([
-
1
],
logi
n
.
analyzePassword
(
''
))
self
.
assertEqual
([
-
1
],
logi
n
.
analyzePassword
(
'1234567'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'12345678'
))
# not changed in last x days
self
.
_cleanUp
Person
(
perso
n
)
self
.
_cleanUp
Login
(
logi
n
)
preference
.
setPreferredMinPasswordLifetimeDuration
(
24
)
preference
.
setPreferredNumberOfLastPasswordToCheck
(
3
)
self
.
tic
()
self
.
_clearCache
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'12345678'
))
perso
n
.
setPassword
(
'12345678'
)
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'12345678'
))
logi
n
.
setPassword
(
'12345678'
)
self
.
tic
()
# if we try to change now we should fail with any password
self
.
assertSameSet
([
-
3
],
perso
n
.
analyzePassword
(
'87654321'
))
self
.
assertSameSet
([
-
1
,
-
3
],
perso
n
.
analyzePassword
(
'short'
))
# multiple failures
self
.
assertFalse
(
perso
n
.
isPasswordValid
(
'short'
))
# multiple failures
self
.
assertRaises
(
ValueError
,
perso
n
.
setPassword
,
'87654321'
)
self
.
assertSameSet
([
-
3
],
logi
n
.
analyzePassword
(
'87654321'
))
self
.
assertSameSet
([
-
1
,
-
3
],
logi
n
.
analyzePassword
(
'short'
))
# multiple failures
self
.
assertFalse
(
logi
n
.
isPasswordValid
(
'short'
))
# multiple failures
self
.
assertRaises
(
ValueError
,
logi
n
.
setPassword
,
'87654321'
)
preference
.
setPreferredMinPasswordLifetimeDuration
(
0
)
# remove restriction
self
.
tic
()
self
.
_clearCache
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'87654321'
))
# it's OK to change
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'87654321'
))
# it's OK to change
# password not used in previous X passwords
preference
.
setPreferredMinPasswordLength
(
None
)
# disable for now
self
.
_cleanUp
Person
(
perso
n
)
self
.
_cleanUp
Login
(
logi
n
)
self
.
_clearCache
()
self
.
tic
()
perso
n
.
setPassword
(
'12345678-new'
)
logi
n
.
setPassword
(
'12345678-new'
)
self
.
tic
()
self
.
assertSameSet
([
-
4
],
perso
n
.
analyzePassword
(
'12345678-new'
))
# if we try to change now we should fail with this EXACT password
self
.
assertRaises
(
ValueError
,
perso
n
.
setPassword
,
'12345678-new'
)
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'12345678_'
))
# it's OK with another one not used yet
self
.
assertSameSet
([
-
4
],
logi
n
.
analyzePassword
(
'12345678-new'
))
# if we try to change now we should fail with this EXACT password
self
.
assertRaises
(
ValueError
,
logi
n
.
setPassword
,
'12345678-new'
)
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'12345678_'
))
# it's OK with another one not used yet
for
password
in
[
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
]:
# this sleep is not so beautiful, but mysql datetime columns has a
# precision of one second only, and we use creation_date to order
# "Password Event" objects. So without this sleep, the test is
# failing randomly.
time
.
sleep
(
1
)
perso
n
.
setPassword
(
password
)
logi
n
.
setPassword
(
password
)
self
.
tic
()
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'12345678-new'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'a'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'b'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'c'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'12345678-new'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'a'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'b'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'c'
))
# only last 3 (including current one are invalid)
self
.
assertSameSet
([
-
4
],
perso
n
.
analyzePassword
(
'd'
))
self
.
assertSameSet
([
-
4
],
perso
n
.
analyzePassword
(
'e'
))
self
.
assertSameSet
([
-
4
],
perso
n
.
analyzePassword
(
'f'
))
self
.
assertSameSet
([
-
4
],
logi
n
.
analyzePassword
(
'd'
))
self
.
assertSameSet
([
-
4
],
logi
n
.
analyzePassword
(
'e'
))
self
.
assertSameSet
([
-
4
],
logi
n
.
analyzePassword
(
'f'
))
# if we remove restricted then all password are usable
preference
.
setPreferredNumberOfLastPasswordToCheck
(
None
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'd'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'e'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'f'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'd'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'e'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'f'
))
# if we set only last password to check
preference
.
setPreferredNumberOfLastPasswordToCheck
(
1
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'c'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'd'
))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'e'
))
self
.
assertSameSet
([
-
4
],
perso
n
.
analyzePassword
(
'f'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'c'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'd'
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'e'
))
self
.
assertSameSet
([
-
4
],
logi
n
.
analyzePassword
(
'f'
))
preference
.
setPreferredRegularExpressionGroupList
(
regular_expression_list
)
preference
.
setPreferredMinPasswordLength
(
7
)
preference
.
setPreferredNumberOfLastPasswordToCheck
(
None
)
self
.
_cleanUp
Person
(
perso
n
)
self
.
_cleanUp
Login
(
logi
n
)
self
.
_clearCache
()
self
.
tic
()
...
...
@@ -370,47 +392,47 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
_clearCache
()
self
.
tic
()
for
password
in
four_group_password_list
:
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
password
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
password
))
for
password
in
three_group_password_list
+
two_group_password_list
+
one_group_password_list
:
self
.
assertSameSet
([
-
2
],
perso
n
.
analyzePassword
(
password
))
self
.
assertSameSet
([
-
2
],
logi
n
.
analyzePassword
(
password
))
# min 3 out of all groups
preference
.
setPreferredMinRegularExpressionGroupNumber
(
3
)
self
.
_clearCache
()
self
.
_cleanUp
Person
(
perso
n
)
self
.
_cleanUp
Login
(
logi
n
)
self
.
tic
()
for
password
in
four_group_password_list
+
three_group_password_list
:
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
password
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
password
))
for
password
in
two_group_password_list
+
one_group_password_list
:
self
.
assertSameSet
([
-
2
],
perso
n
.
analyzePassword
(
password
))
self
.
assertSameSet
([
-
2
],
logi
n
.
analyzePassword
(
password
))
# min 2 out of all groups
preference
.
setPreferredMinRegularExpressionGroupNumber
(
2
)
self
.
_clearCache
()
self
.
tic
()
for
password
in
four_group_password_list
+
three_group_password_list
+
two_group_password_list
:
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
password
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
password
))
for
password
in
one_group_password_list
:
self
.
assertSameSet
([
-
2
],
perso
n
.
analyzePassword
(
password
))
self
.
assertSameSet
([
-
2
],
logi
n
.
analyzePassword
(
password
))
# min 1 out of all groups
preference
.
setPreferredMinRegularExpressionGroupNumber
(
1
)
self
.
_clearCache
()
self
.
tic
()
for
password
in
four_group_password_list
+
three_group_password_list
+
two_group_password_list
+
one_group_password_list
:
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
password
))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
password
))
# not contain the full name of the user
preference
.
setPrefferedForceUsernameCheckInPassword
(
1
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertSameSet
([
-
5
],
perso
n
.
analyzePassword
(
'abAB#12_%s'
%
person
.
getFirstName
()))
self
.
assertSameSet
([
-
5
],
perso
n
.
analyzePassword
(
'abAB#12_%s'
%
person
.
getLastName
()))
self
.
assertSameSet
([
-
5
],
logi
n
.
analyzePassword
(
'abAB#12_%s'
%
person
.
getFirstName
()))
self
.
assertSameSet
([
-
5
],
logi
n
.
analyzePassword
(
'abAB#12_%s'
%
person
.
getLastName
()))
preference
.
setPrefferedForceUsernameCheckInPassword
(
0
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'abAB#12_%s'
%
person
.
getFirstName
()))
self
.
assertTrue
(
perso
n
.
isPasswordValid
(
'abAB#12_%s'
%
person
.
getLastName
()))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'abAB#12_%s'
%
person
.
getFirstName
()))
self
.
assertTrue
(
logi
n
.
isPasswordValid
(
'abAB#12_%s'
%
person
.
getLastName
()))
# check on temp objects just passworrd length( i.e. simulating a new user account creation)
first_name
=
'John'
...
...
@@ -425,8 +447,8 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
_clearCache
()
self
.
tic
()
# in this case which is basically used in new account creation only length of password matters
self
.
assertSameSet
([
-
1
],
temp_person
.
Perso
n_analyzePassword
(
'onlyNine1'
))
self
.
assertSameSet
([],
temp_person
.
Perso
n_analyzePassword
(
'longEnough1'
))
self
.
assertSameSet
([
-
1
],
temp_person
.
Logi
n_analyzePassword
(
'onlyNine1'
))
self
.
assertSameSet
([],
temp_person
.
Logi
n_analyzePassword
(
'longEnough1'
))
# make sure re check works on temp as well ( i.e. min 3 out of all groups)
preference
.
setPreferredRegularExpressionGroupList
(
regular_expression_list
)
...
...
@@ -435,22 +457,22 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
_clearCache
()
self
.
tic
()
for
password
in
four_group_password_list
+
three_group_password_list
:
self
.
assertSameSet
([],
temp_person
.
Perso
n_analyzePassword
(
password
))
self
.
assertSameSet
([],
temp_person
.
Logi
n_analyzePassword
(
password
))
for
password
in
two_group_password_list
+
one_group_password_list
:
self
.
assertSameSet
([
-
2
],
temp_person
.
Perso
n_analyzePassword
(
password
))
self
.
assertSameSet
([
-
2
],
temp_person
.
Logi
n_analyzePassword
(
password
))
# make sure peron's check on username works on temp as well (i.e. not contain the full name of the user)
preference
.
setPrefferedForceUsernameCheckInPassword
(
1
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertSameSet
([
-
5
],
temp_person
.
Perso
n_analyzePassword
(
'abAB#12_%s'
%
first_name
))
self
.
assertSameSet
([
-
5
],
temp_person
.
Perso
n_analyzePassword
(
'abAB#12_%s'
%
last_name
))
self
.
assertSameSet
([
-
5
],
temp_person
.
Logi
n_analyzePassword
(
'abAB#12_%s'
%
first_name
))
self
.
assertSameSet
([
-
5
],
temp_person
.
Logi
n_analyzePassword
(
'abAB#12_%s'
%
last_name
))
preference
.
setPrefferedForceUsernameCheckInPassword
(
0
)
self
.
_clearCache
()
self
.
tic
()
self
.
assertSameSet
([],
temp_person
.
Perso
n_analyzePassword
(
'abAB#12_%s'
%
first_name
))
self
.
assertSameSet
([],
temp_person
.
Perso
n_analyzePassword
(
'abAB#12_%s'
%
last_name
))
self
.
assertSameSet
([],
temp_person
.
Logi
n_analyzePassword
(
'abAB#12_%s'
%
first_name
))
self
.
assertSameSet
([],
temp_person
.
Logi
n_analyzePassword
(
'abAB#12_%s'
%
last_name
))
# check Base_isPasswordValid is able to work in Anonymous User fashion
# but with already create Person object (i.e. recover password case)
...
...
@@ -461,20 +483,20 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
_clearCache
()
self
.
tic
()
perso
n
.
setPassword
(
'used_ALREADY_1234'
)
logi
n
.
setPassword
(
'used_ALREADY_1234'
)
self
.
_clearCache
()
self
.
tic
()
# emulate Anonymous User
self
.
logout
()
request
.
set
(
'field_user_login'
,
perso
n
.
getReference
())
self
.
assertRaises
(
ValidationError
,
portal
.
Base
_isPasswordValid
,
'abAB#12_%s'
%
person
.
getFirstName
(),
request
)
# contains name
self
.
assertRaises
(
ValidationError
,
portal
.
Base
_isPasswordValid
,
'abAB#12_%s'
%
person
.
getLastName
(),
request
)
# contains name
self
.
assertRaises
(
ValidationError
,
portal
.
Base
_isPasswordValid
,
'abAB#1'
,
request
)
# too short
self
.
assertRaises
(
ValidationError
,
portal
.
Base
_isPasswordValid
,
'abABCDEFG'
,
request
)
# too few groups
self
.
assertRaises
(
ValidationError
,
portal
.
Base
_isPasswordValid
,
'used_ALREADY_1234'
,
request
)
# already used
self
.
assertEqual
(
1
,
portal
.
Base
_isPasswordValid
(
'abAB#12_'
,
request
))
self
.
assertEqual
(
1
,
portal
.
Base
_isPasswordValid
(
'not_used_ALREADY_1234'
,
request
))
request
.
set
(
'field_user_login'
,
logi
n
.
getReference
())
self
.
assertRaises
(
ValidationError
,
login
.
Login
_isPasswordValid
,
'abAB#12_%s'
%
person
.
getFirstName
(),
request
)
# contains name
self
.
assertRaises
(
ValidationError
,
login
.
Login
_isPasswordValid
,
'abAB#12_%s'
%
person
.
getLastName
(),
request
)
# contains name
self
.
assertRaises
(
ValidationError
,
login
.
Login
_isPasswordValid
,
'abAB#1'
,
request
)
# too short
self
.
assertRaises
(
ValidationError
,
login
.
Login
_isPasswordValid
,
'abABCDEFG'
,
request
)
# too few groups
self
.
assertRaises
(
ValidationError
,
login
.
Login
_isPasswordValid
,
'used_ALREADY_1234'
,
request
)
# already used
self
.
assertEqual
(
1
,
login
.
Login
_isPasswordValid
(
'abAB#12_'
,
request
))
self
.
assertEqual
(
1
,
login
.
Login
_isPasswordValid
(
'not_used_ALREADY_1234'
,
request
))
def
test_04_PasswordExpire
(
self
):
"""
...
...
@@ -485,16 +507,16 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
assertTrue
(
portal
.
portal_preferences
.
isAuthenticationPolicyEnabled
())
person
=
portal
.
person_module
.
newContent
(
portal_type
=
'Person
'
,
reference
=
'test-04'
,
password
=
'used_ALREADY_1234'
)
person
=
self
.
createUser
(
'test-04
'
,
password
=
'used_ALREADY_1234'
)
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
preference
.
setPreferredMaxPasswordLifetimeDuration
(
24
)
self
.
tic
()
self
.
_clearCache
()
self
.
assertFalse
(
perso
n
.
isPasswordExpired
())
self
.
assertFalse
(
logi
n
.
isPasswordExpired
())
self
.
assertFalse
(
request
[
'is_user_account_password_expired'
])
...
...
@@ -502,21 +524,21 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
preference
.
setPreferredMaxPasswordLifetimeDuration
(
4
*
24
)
# password expire in 4 days
self
.
tic
()
self
.
_clearCache
()
self
.
assertFalse
(
perso
n
.
isPasswordExpired
())
self
.
assertFalse
(
logi
n
.
isPasswordExpired
())
self
.
assertFalse
(
request
[
'is_user_account_password_expired'
])
# test early warning password expire notification is detected
preference
.
setPreferredPasswordLifetimeExpireWarningDuration
(
4
*
24
)
# password expire notification appear immediately
self
.
tic
()
self
.
_clearCache
()
self
.
assertFalse
(
perso
n
.
isPasswordExpired
())
self
.
assertFalse
(
logi
n
.
isPasswordExpired
())
self
.
assertTrue
(
request
[
'is_user_account_password_expired_expire_date'
])
# test early warning password expire notification is detected
preference
.
setPreferredPasswordLifetimeExpireWarningDuration
(
4
*
24
-
24
)
# password expire notification appear 3 days befor time
self
.
tic
()
self
.
_clearCache
()
self
.
assertFalse
(
perso
n
.
isPasswordExpired
())
self
.
assertFalse
(
logi
n
.
isPasswordExpired
())
self
.
assertFalse
(
request
[
'is_user_account_password_expired_expire_date'
])
def
test_05_HttpRequest
(
self
):
...
...
@@ -525,50 +547,52 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
"""
portal
=
self
.
getPortal
()
request
=
self
.
app
.
REQUEST
person
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'Person'
,
reference
=
'test'
)
person
=
self
.
createUser
(
'test-05'
)
assignment
=
person
.
newContent
(
portal_type
=
'Assignment'
)
assignment
.
open
()
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
perso
n
.
setPassword
(
'used_ALREADY_1234'
)
logi
n
.
setPassword
(
'used_ALREADY_1234'
)
self
.
tic
()
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test'
,
'used_ALREADY_1234'
)
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test
-05
'
,
'used_ALREADY_1234'
)
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
'Welcome to ERP5'
in
response
.
getBody
())
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# fail request #1
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test'
,
'bad_test'
)
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test
-05
'
,
'bad_test'
)
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
response
.
getHeader
(
"Location"
).
endswith
(
"login_form"
))
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# fail request #2
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
response
.
getHeader
(
"Location"
).
endswith
(
"login_form"
))
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# fail request #3
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
response
.
getHeader
(
"Location"
).
endswith
(
"login_form"
))
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
self
.
tic
()
# test message that account is blocked
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
path
=
portal
.
absolute_url_path
()
+
'/logged_in?__ac_name=%s&__ac_password=%s'
%
(
'test'
,
'used_ALREADY_1234'
)
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
path
=
portal
.
absolute_url_path
()
+
'/logged_in?__ac_name=%s&__ac_password=%s'
%
(
'test
-05
'
,
'used_ALREADY_1234'
)
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
response
.
getHeader
(
"Location"
).
endswith
(
"login_form?portal_status_message=Account is blocked."
))
# test expire password message, first unblock it
person
.
Perso
n_unblockLogin
()
login
.
Logi
n_unblockLogin
()
preference
.
setPreferredMaxPasswordLifetimeDuration
(
0
)
self
.
tic
()
self
.
_clearCache
()
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
response
.
getHeader
(
"Location"
).
endswith
(
"login_form?portal_status_message=Password is expired."
))
self
.
assertTrue
(
perso
n
.
isPasswordExpired
())
self
.
assertTrue
(
logi
n
.
isPasswordExpired
())
# test we're redirected to update password due to soon expire
preference
.
setPreferredMaxPasswordLifetimeDuration
(
24
)
...
...
@@ -584,7 +608,7 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
preference
.
setPreferredPasswordLifetimeExpireWarningDuration
(
12
)
self
.
tic
()
self
.
_clearCache
()
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test'
,
'used_ALREADY_1234'
)
path
=
portal
.
absolute_url_path
()
+
'/view?__ac_name=%s&__ac_password=%s'
%
(
'test
-05
'
,
'used_ALREADY_1234'
)
response
=
self
.
publish
(
path
)
self
.
assertTrue
(
'Welcome to ERP5'
in
response
.
getBody
())
...
...
@@ -593,18 +617,18 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
Check that expiring old Authentication Event list works.
"""
portal
=
self
.
getPortal
()
person
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'Person'
,
reference
=
'test'
)
person
=
self
.
createUser
(
'test-06'
)
login
=
person
.
objectValues
(
portal_type
=
'ERP5 Login'
)[
0
]
preference
=
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'System Preference'
,
title
=
'Authentication'
,)
# file some failures so we should detect and block account
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
perso
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
logi
n
.
notifyLoginFailure
()
self
.
tic
()
# should be blocked
self
.
assertTrue
(
perso
n
.
isLoginBlocked
())
self
.
assertTrue
(
logi
n
.
isLoginBlocked
())
# set 0 check interval
preference
.
setPreferredAuthenticationFailureCheckDuration
(
0
)
...
...
@@ -612,14 +636,14 @@ class TestAuthenticationPolicy(ERP5TypeTestCase):
self
.
_clearCache
()
time
.
sleep
(
1
)
# we need to give a moment
self
.
assertFalse
(
perso
n
.
isLoginBlocked
())
self
.
assertFalse
(
logi
n
.
isLoginBlocked
())
# expire manually old
portal
.
system_event_module
.
SystemEventModule_expireAuthenticationEventList
()
self
.
tic
()
self
.
assertEqual
(
3
,
len
(
portal
.
portal_catalog
(
portal_type
=
"Authentication Event"
,
default_destination_uid
=
perso
n
.
getUid
(),
default_destination_uid
=
logi
n
.
getUid
(),
validation_state
=
"expired"
)))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment