[Checkins] SVN: z3c.password/trunk/ merge branch adamg-tooManyLoginFailures
Adam Groszer
agroszer at gmail.com
Fri Jan 29 12:28:55 EST 2010
Log message for revision 108644:
merge branch adamg-tooManyLoginFailures
Changed:
U z3c.password/trunk/CHANGES.txt
U z3c.password/trunk/setup.py
U z3c.password/trunk/src/z3c/password/README.txt
U z3c.password/trunk/src/z3c/password/interfaces.py
U z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.mo
U z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.po
U z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.mo
U z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.po
U z3c.password/trunk/src/z3c/password/locales/z3c.password.pot
U z3c.password/trunk/src/z3c/password/password.py
U z3c.password/trunk/src/z3c/password/principal.py
U z3c.password/trunk/src/z3c/password/principal.txt
U z3c.password/trunk/src/z3c/password/testing.py
-=-
Modified: z3c.password/trunk/CHANGES.txt
===================================================================
--- z3c.password/trunk/CHANGES.txt 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/CHANGES.txt 2010-01-29 17:28:55 UTC (rev 108644)
@@ -5,8 +5,13 @@
0.8.0 (unreleased)
------------------
-- ...
+- Feature: ``failedAttemptCheck``
+ * increment failedAttempts on all/any request (this is the default)
+ * increment failedAttempts only on non-resource requests
+ * increment failedAttempts only on POST requests
+- Feature: more specific exceptions on new password verification.
+
0.7.4 (2009-12-22)
------------------
Modified: z3c.password/trunk/setup.py
===================================================================
--- z3c.password/trunk/setup.py 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/setup.py 2010-01-29 17:28:55 UTC (rev 108644)
@@ -64,6 +64,7 @@
'zope.i18nmessageid',
'zope.interface',
'zope.schema',
+ 'zope.security',
],
zip_safe = False,
)
\ No newline at end of file
Modified: z3c.password/trunk/src/z3c/password/README.txt
===================================================================
--- z3c.password/trunk/src/z3c/password/README.txt 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/README.txt 2010-01-29 17:28:55 UTC (rev 108644)
@@ -167,12 +167,12 @@
>>> pwd.verify('FOOBAR123')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersLowerLetter
>>> pwd.verify('foobAR123')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersLowerLetter
>>> pwd.verify('foobaR123')
@@ -191,12 +191,12 @@
>>> pwd.verify('foobar123')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersUpperLetter
>>> pwd.verify('FOOBar123')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersUpperLetter
>>> pwd.verify('fOOBAR123')
@@ -215,12 +215,12 @@
>>> pwd.verify('foobar123')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersDigits
>>> pwd.verify('FOOBa1234')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersDigits
>>> pwd.verify('fOBA12345')
@@ -239,12 +239,12 @@
>>> pwd.verify('foo(bar)')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersSpecials
>>> pwd.verify('FO.#(Ba1)')
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersSpecials
>>> pwd.verify('fO.,;()5')
@@ -262,12 +262,12 @@
>>> pwd.verify('foobar'+unichr(0x0c3)+unichr(0x0c4))
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersOthers
>>> pwd.verify('foobar'+unichr(0x0c3)+unichr(0x0c4)+unichr(0x0e1))
Traceback (most recent call last):
...
- TooFewGroupCharacters
+ TooFewGroupCharactersOthers
>>> pwd.verify('fOO'+unichr(0x0e1)*5)
Modified: z3c.password/trunk/src/z3c/password/interfaces.py
===================================================================
--- z3c.password/trunk/src/z3c/password/interfaces.py 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/interfaces.py 2010-01-29 17:28:55 UTC (rev 108644)
@@ -43,6 +43,25 @@
class TooFewGroupCharacters(InvalidPassword):
__doc__ = _('''Password does not contain enough characters of one group.''')
+class TooFewGroupCharactersLowerLetter(TooFewGroupCharacters):
+ __doc__ = _(
+ '''Password does not contain enough characters of lowercase letters.''')
+
+class TooFewGroupCharactersUpperLetter(TooFewGroupCharacters):
+ __doc__ = _(
+ '''Password does not contain enough characters of uppercase letters.''')
+
+class TooFewGroupCharactersDigits(TooFewGroupCharacters):
+ __doc__ = _('''Password does not contain enough characters of digits.''')
+
+class TooFewGroupCharactersSpecials(TooFewGroupCharacters):
+ __doc__ = _(
+ '''Password does not contain enough characters of special characters.''')
+
+class TooFewGroupCharactersOthers(TooFewGroupCharacters):
+ __doc__ = _(
+ '''Password does not contain enough characters of other characters.''')
+
class TooFewUniqueCharacters(InvalidPassword):
__doc__ = _('''Password does not contain enough unique characters.''')
@@ -70,6 +89,10 @@
self.principal = principal
Exception.__init__(self, self.__doc__)
+TML_CHECK_ALL = None
+TML_CHECK_NONRESOURCE = 'nonres'
+TML_CHECK_POSTONLY = 'post'
+
class AccountLocked(Exception):
__doc__ = _('The account is locked, because the password was '
'entered incorrectly too often.')
@@ -302,6 +325,14 @@
required=False,
default=None)
+ failedAttemptCheck = zope.schema.Choice(
+ title=_(u'Failed password check method'),
+ description=_(u'Failed password check method. '
+ 'All requests, non-reqource requests, POST requests.'),
+ required=False,
+ values=[TML_CHECK_ALL, TML_CHECK_NONRESOURCE, TML_CHECK_POSTONLY],
+ default=TML_CHECK_ALL )
+
disallowPasswordReuse = zope.schema.Bool(
title=_(u'Disallow Password Reuse'),
description=_(u'Do not allow to set a previously set password again.'),
Modified: z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.mo
===================================================================
(Binary files differ)
Modified: z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.po
===================================================================
--- z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.po 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/locales/de/LC_MESSAGES/z3c.password.po 2010-01-29 17:28:55 UTC (rev 108644)
@@ -11,193 +11,242 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
+# #############################################################################
# Stephan Richter <stephan.richter at tufts.edu>, 2006.
-# #############################################################################
+# Adam Groszer <agroszer at gmail.com>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: z3c.password\n"
-"POT-Creation-Date: Thu Aug 6 16:10:14 2009\n"
-"PO-Revision-Date: 2009-08-06 18:59+0100\n"
-"Last-Translator: Michael Laubacher <michael.laubacher at refline.ch>\n"
-"Language-Team: German <zope3-dev at zope.org>\n"
+"POT-Creation-Date: Fri Jan 29 17:24:33 2010\n"
+"PO-Revision-Date: 2010-01-29 17:26+0100\n"
+"Last-Translator: Adam Groszer <agroszer at gmail.com>\n"
+"Language-Team: American English <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: zope/app/locales/extract.py\n"
-"X-Generator: KBabel 1.11.4\n"
+"X-Generator: Lokalize 1.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/z3c/password/interfaces.py:122
+#: z3c/password/interfaces.py:114
+msgid "Description"
+msgstr "Beschreibung"
+
+#: z3c/password/interfaces.py:115
+msgid "A description of the password utility."
+msgstr "Eine Beschreibung des Passwortdienstes."
+
+#: z3c/password/interfaces.py:145
msgid "Minimum Length"
msgstr "Minimale Länge"
-#: src/z3c/password/interfaces.py:123
+#: z3c/password/interfaces.py:146
msgid "The minimum length of the password."
msgstr "Die minimale Länge des Passwortes."
-#: src/z3c/password/interfaces.py:128
+#: z3c/password/interfaces.py:151
msgid "Maximum Length"
msgstr "Maximale Länge"
-#: src/z3c/password/interfaces.py:129
+#: z3c/password/interfaces.py:152
msgid "The maximum length of the password."
msgstr "Die maximale Länge des Passwortes."
-#: src/z3c/password/interfaces.py:141
+#: z3c/password/interfaces.py:164
msgid "Maximum Characters of Group"
msgstr "Maximale Zeichen einer Gruppe"
-#: src/z3c/password/interfaces.py:142
-msgid "The maximum amount of characters that a password can have from one group. The groups are: digits, letters, punctuation."
-msgstr "Die maximale Anzahl von Zeichen welche das Passwort von einer Gruppe enthalten darf. Die Gruppen sind: Zahlen, Buchstaben, Zeichen."
+#: z3c/password/interfaces.py:165
+msgid ""
+"The maximum amount of characters that a password can have from one group. "
+"The groups are: digits, letters, punctuation."
+msgstr ""
+"Die maximale Anzahl von Zeichen welche das Passwort von einer Gruppe "
+"enthalten darf. Die Gruppen sind: Zahlen, Buchstaben, Zeichen."
-#: src/z3c/password/interfaces.py:149
+#: z3c/password/interfaces.py:172
msgid "Old/New Similarity"
msgstr "Alt/Neu Ãhnlichkeit"
-#: src/z3c/password/interfaces.py:155
+#: z3c/password/interfaces.py:178
msgid "Minimum Number of Lowercase letters"
msgstr "Die minimale Anzahl Kleinbuchstaben"
-#: src/z3c/password/interfaces.py:156
+#: z3c/password/interfaces.py:179
msgid "The minimum amount of lowercase letters that a password must have."
msgstr "Die minimale Anzahl Kleinbuchstaben"
-#: src/z3c/password/interfaces.py:162
+#: z3c/password/interfaces.py:185
msgid "Minimum Number of Uppercase letters"
msgstr "Die minimale Anzahl Grossbuchstaben"
-#: src/z3c/password/interfaces.py:163
+#: z3c/password/interfaces.py:186
msgid "The minimum amount of uppercase letters that a password must have."
msgstr "Die minimale Anzahl Grossbuchstaben"
-#: src/z3c/password/interfaces.py:169
+#: z3c/password/interfaces.py:192
msgid "Minimum Number of Numeric digits"
msgstr "Die minimale Anzahl unterschiedlicher Zahlen"
-#: src/z3c/password/interfaces.py:170
+#: z3c/password/interfaces.py:193
msgid "The minimum amount of numeric digits that a password must have."
msgstr "Die minimale Menge Nummern, die ein Passwort haben muss."
-#: src/z3c/password/interfaces.py:176
+#: z3c/password/interfaces.py:199
msgid "Minimum Number of Special characters"
msgstr "Die minimale Anzahl unterschiedlicher Sonderzeichen"
-#: src/z3c/password/interfaces.py:177
+#: z3c/password/interfaces.py:200
msgid "The minimum amount of special characters that a password must have."
msgstr "Die minimale Anzahl unterschiedlicher Sonderzeichen"
-#: src/z3c/password/interfaces.py:184
+#: z3c/password/interfaces.py:207
msgid "Minimum Number of Other characters"
msgstr "Die minimale Anzahl unterschiedlicher Zeichen"
-#: src/z3c/password/interfaces.py:185
+#: z3c/password/interfaces.py:208
msgid "The minimum amount of other characters that a password must have."
-msgstr "Die minimale Menge unterschiedlicher Zeichen, die ein Passwort enthalten muss."
+msgstr ""
+"Die minimale Menge unterschiedlicher Zeichen, die ein Passwort enthalten "
+"muss."
-#: src/z3c/password/interfaces.py:236
+#: z3c/password/interfaces.py:259
msgid "Minimum Number of Unique letters"
msgstr "Die minimale Anzahl unterschiedlicher Buchstaben"
-#: src/z3c/password/interfaces.py:237
-msgid "The minimum amount of unique letters that a password must have. This is against passwords like `aAaA0000`. All characters taken lowercase."
+#: z3c/password/interfaces.py:260
+msgid ""
+"The minimum amount of unique letters that a password must have. This is "
+"against passwords like `aAaA0000`. All characters taken lowercase."
msgstr "Die minimale Anzahl unterschiedlicher Buchstaben"
-#: src/z3c/password/interfaces.py:253
+#: z3c/password/interfaces.py:276
msgid "Minimum Number of Unique characters"
msgstr "Die minimale Anzahl unterschiedlicher Zeichen"
-#: src/z3c/password/interfaces.py:254
-msgid "The minimum amount of unique characters that a password must have. This is against passwords like `aAaA0000`. All characters taken lowercase."
+#: z3c/password/interfaces.py:277
+msgid ""
+"The minimum amount of unique characters that a password must have. This is "
+"against passwords like `aAaA0000`. All characters taken lowercase."
msgstr "Die minimale Anzahl unterschiedlicher Zeichen"
-#: src/z3c/password/interfaces.py:279
-#: src/z3c/password/interfaces.py:280
+#: z3c/password/interfaces.py:29
+msgid "No new password specified."
+msgstr "Es wurde kein neues Passwort eingegeben."
+
+#: z3c/password/interfaces.py:302 z3c/password/interfaces.py:303
msgid "Password must be changed on next login"
msgstr "Das Passwort muss beim nächsten Login geändert werden."
-#: src/z3c/password/interfaces.py:285
-#: src/z3c/password/interfaces.py:286
+#: z3c/password/interfaces.py:308 z3c/password/interfaces.py:309
msgid "Password expires after (days)"
msgstr "Das Passwort läuft aus nach (Tage)"
-#: src/z3c/password/interfaces.py:29
-msgid "No new password specified."
-msgstr "Es wurde kein neues Passwort eingegeben."
-
-#: src/z3c/password/interfaces.py:291
+#: z3c/password/interfaces.py:314
msgid "Lockout period (minutes)"
msgstr "Dauer Passwortsperrung (Minuten)"
-#: src/z3c/password/interfaces.py:292
-msgid "Lockout the user after too many failed password entriesfor this many minutes. The user can try again after."
-msgstr "Der Benutzer wird nach zu vielen Fehlversuchen gesperrt und kann nach dieser Anzahl Minuten nochmals versuchen."
+#: z3c/password/interfaces.py:315
+msgid ""
+"Lockout the user after too many failed password entriesfor this many "
+"minutes. The user can try again after."
+msgstr ""
+"Der Benutzer wird nach zu vielen Fehlversuchen gesperrt und kann nach dieser "
+"Anzahl Minuten nochmals versuchen."
-#: src/z3c/password/interfaces.py:298
+#: z3c/password/interfaces.py:32
+msgid "Password is too short."
+msgstr "Passwort ist zu kurz."
+
+#: z3c/password/interfaces.py:321
msgid "Max. number of failed password entries before account is locked"
msgstr "Gibt die Anzahl Fehlversuche an, bevor das Passwort gesperrt wird."
-#: src/z3c/password/interfaces.py:299
-msgid "Specifies the amount of failed attempts allowed to check the password before the password is locked and no new password can be provided."
+#: z3c/password/interfaces.py:322
+msgid ""
+"Specifies the amount of failed attempts allowed to check the password before "
+"the password is locked and no new password can be provided."
msgstr "Gibt die Anzahl Fehlversuche an, bevor das Passwort gesperrt wird."
-#: src/z3c/password/interfaces.py:306
+#: z3c/password/interfaces.py:329
+msgid "Failed password check method"
+msgstr ""
+
+#: z3c/password/interfaces.py:330
+msgid ""
+"Failed password check method. All requests, non-reqource requests, POST "
+"requests."
+msgstr ""
+
+#: z3c/password/interfaces.py:337
msgid "Disallow Password Reuse"
msgstr "Erlaubt nicht ein bisheriges Passwort wiederzuverwenden."
-#: src/z3c/password/interfaces.py:307
+#: z3c/password/interfaces.py:338
msgid "Do not allow to set a previously set password again."
msgstr "Erlaubt nicht ein bisheriges Passwort wiederzuverwenden."
-#: src/z3c/password/interfaces.py:32
-msgid "Password is too short."
-msgstr "Passwort ist zu kurz."
-
-#: src/z3c/password/interfaces.py:35
+#: z3c/password/interfaces.py:35
msgid "Password is too long."
msgstr "Passwort ist zu lang."
-#: src/z3c/password/interfaces.py:38
+#: z3c/password/interfaces.py:38
msgid "Password is too similar to old one."
msgstr "Das Passwort ist gleich oder zu ähnlich wie das bisherige."
-#: src/z3c/password/interfaces.py:41
+#: z3c/password/interfaces.py:41
msgid "Password contains too many characters of one group."
msgstr "Passwort enthält zu viele Zeichen einer Gruppe."
-#: src/z3c/password/interfaces.py:44
+#: z3c/password/interfaces.py:44
msgid "Password does not contain enough characters of one group."
msgstr "Das Passwort besteht nicht aus genügend Zeichen einer Zeichen-Gruppe."
-#: src/z3c/password/interfaces.py:47
+#: z3c/password/interfaces.py:47
+msgid "Password does not contain enough characters of lowercase letters."
+msgstr "Das Passwort besteht nicht aus genügend Kleinbuchstaben."
+
+#: z3c/password/interfaces.py:51
+msgid "Password does not contain enough characters of uppercase letters."
+msgstr "Das Passwort besteht nicht aus genügend Zeichen Grossbuchstaben."
+
+#: z3c/password/interfaces.py:55
+msgid "Password does not contain enough characters of digits."
+msgstr "Das Passwort besteht nicht aus genügend Zahlen."
+
+#: z3c/password/interfaces.py:58
+msgid "Password does not contain enough characters of special characters."
+msgstr "Das Passwort besteht nicht aus genügend Sonderzeichen."
+
+#: z3c/password/interfaces.py:62
+msgid "Password does not contain enough characters of other characters."
+msgstr "Das Passwort besteht nicht aus genügend andere Zeichen."
+
+#: z3c/password/interfaces.py:66
msgid "Password does not contain enough unique characters."
msgstr "Das Passwort besteht nicht aus genügend unterschiedlichen Zeichen."
-#: src/z3c/password/interfaces.py:50
+#: z3c/password/interfaces.py:69
msgid "Password does not contain enough unique letters."
msgstr "Das Passwort besteht nicht aus genügend unterschiedlichen Zeichen."
-#: src/z3c/password/interfaces.py:53
+#: z3c/password/interfaces.py:72
msgid "The password has expired."
msgstr "Das Passwort ist abgelaufen."
-#: src/z3c/password/interfaces.py:60
+#: z3c/password/interfaces.py:79
msgid "The password set was already used before."
msgstr "Dieses Passwort wurde bereits verwendet."
-#: src/z3c/password/interfaces.py:67
+#: z3c/password/interfaces.py:86
msgid "The password was entered incorrectly too often."
msgstr "Das Passwort wurde zu oft falsch eingegeben."
-#: src/z3c/password/interfaces.py:74
-msgid "The account is locked, because the password was entered incorrectly too often."
-msgstr "Das Passwort wurde zu häufig falsch eingegeben. Der Benutzer wurde gesperrt und kann vom Administrator wieder freigegeben werden."
+#: z3c/password/interfaces.py:97
+msgid ""
+"The account is locked, because the password was entered incorrectly too "
+"often."
+msgstr ""
+"Das Passwort wurde zu häufig falsch eingegeben. Der Benutzer wurde gesperrt "
+"und kann vom Administrator wieder freigegeben werden."
-#: src/z3c/password/interfaces.py:91
-msgid "Description"
-msgstr "Beschreibung"
-
-#: src/z3c/password/interfaces.py:92
-msgid "A description of the password utility."
-msgstr "Eine Beschreibung des Passwortdienstes."
-
Modified: z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.mo
===================================================================
(Binary files differ)
Modified: z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.po
===================================================================
--- z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.po 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/locales/ru/LC_MESSAGES/z3c.password.po 2010-01-29 17:28:55 UTC (rev 108644)
@@ -1,4 +1,4 @@
-##############################################################################
+# #############################################################################
#
# Copyright (c) 2003-2004 Zope Corporation and Contributors.
# All Rights Reserved.
@@ -10,11 +10,11 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
-##############################################################################
+# #############################################################################
msgid ""
msgstr ""
"Project-Id-Version: Development/Revision: 70761\n"
-"POT-Creation-Date: Tue Oct 17 23:25:44 2006\n"
+"POT-Creation-Date: Fri Jan 29 17:24:33 2010\n"
"PO-Revision-Date: 2008-10-23 10:33+0300\n"
"Last-Translator: Dan Korostelev <nadako at gmail.com>\n"
"Language-Team: Zope 3 Developers <zope3-dev at zope.org>\n"
@@ -23,67 +23,229 @@
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: zope/app/locales/extract.py\n"
-#: src/z3c/password/interfaces.py:104
+#: z3c/password/interfaces.py:114
+msgid "Description"
+msgstr "ÐпиÑание"
+
+#: z3c/password/interfaces.py:115
+msgid "A description of the password utility."
+msgstr "ÐпиÑание ÑÑилиÑÑ Ð¿Ð°Ñолей."
+
+#: z3c/password/interfaces.py:145
+msgid "Minimum Length"
+msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð°"
+
+#: z3c/password/interfaces.py:146
+msgid "The minimum length of the password."
+msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° паÑолÑ."
+
+#: z3c/password/interfaces.py:151
msgid "Maximum Length"
msgstr "ÐакÑималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð°"
-#: src/z3c/password/interfaces.py:105
+#: z3c/password/interfaces.py:152
msgid "The maximum length of the password."
msgstr "ÐакÑималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° паÑолÑ."
-#: src/z3c/password/interfaces.py:117
+#: z3c/password/interfaces.py:164
msgid "Maximum Characters of Group"
msgstr "ÐакÑимÑм Ñимволов гÑÑппÑ"
-#: src/z3c/password/interfaces.py:118
-msgid "The maximum amount of characters that a password can have from one group. The groups are: digits, letters, punctuation."
-msgstr "ÐакÑималÑное колиÑеÑÑво Ñимволов одной гÑÑппÑ, коÑоÑое Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ Ð¿Ð°ÑолÑ. ÐÑÑÐ¿Ð¿Ñ - ÑÑо ÑиÑÑÑ, бÑквÑ, знаки пÑнкÑÑаÑии."
+#: z3c/password/interfaces.py:165
+msgid ""
+"The maximum amount of characters that a password can have from one group. "
+"The groups are: digits, letters, punctuation."
+msgstr ""
+"ÐакÑималÑное колиÑеÑÑво Ñимволов одной гÑÑппÑ, коÑоÑое Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ "
+"паÑолÑ. ÐÑÑÐ¿Ð¿Ñ - ÑÑо ÑиÑÑÑ, бÑквÑ, знаки пÑнкÑÑаÑии."
-#: src/z3c/password/interfaces.py:125
+#: z3c/password/interfaces.py:172
msgid "Old/New Similarity"
msgstr "СÑ
ожеÑÑÑ Ð½Ð¾Ð²Ð¾Ð³Ð¾ и ÑÑаÑого паÑолей"
-#: src/z3c/password/interfaces.py:29
+#: z3c/password/interfaces.py:178
+msgid "Minimum Number of Lowercase letters"
+msgstr ""
+
+#: z3c/password/interfaces.py:179
+msgid "The minimum amount of lowercase letters that a password must have."
+msgstr ""
+
+#: z3c/password/interfaces.py:185
+msgid "Minimum Number of Uppercase letters"
+msgstr ""
+
+#: z3c/password/interfaces.py:186
+msgid "The minimum amount of uppercase letters that a password must have."
+msgstr ""
+
+#: z3c/password/interfaces.py:192
+msgid "Minimum Number of Numeric digits"
+msgstr ""
+
+#: z3c/password/interfaces.py:193
+#, fuzzy
+msgid "The minimum amount of numeric digits that a password must have."
+msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° паÑолÑ."
+
+#: z3c/password/interfaces.py:199
+msgid "Minimum Number of Special characters"
+msgstr ""
+
+#: z3c/password/interfaces.py:200
+msgid "The minimum amount of special characters that a password must have."
+msgstr ""
+
+#: z3c/password/interfaces.py:207
+msgid "Minimum Number of Other characters"
+msgstr ""
+
+#: z3c/password/interfaces.py:208
+#, fuzzy
+msgid "The minimum amount of other characters that a password must have."
+msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° паÑолÑ."
+
+#: z3c/password/interfaces.py:259
+msgid "Minimum Number of Unique letters"
+msgstr ""
+
+#: z3c/password/interfaces.py:260
+msgid ""
+"The minimum amount of unique letters that a password must have. This is "
+"against passwords like `aAaA0000`. All characters taken lowercase."
+msgstr ""
+
+#: z3c/password/interfaces.py:276
+msgid "Minimum Number of Unique characters"
+msgstr ""
+
+#: z3c/password/interfaces.py:277
+msgid ""
+"The minimum amount of unique characters that a password must have. This is "
+"against passwords like `aAaA0000`. All characters taken lowercase."
+msgstr ""
+
+#: z3c/password/interfaces.py:29
msgid "No new password specified."
msgstr "ÐовÑй паÑÐ¾Ð»Ñ Ð½Ðµ Ñказан."
-#: src/z3c/password/interfaces.py:32
+#: z3c/password/interfaces.py:302 z3c/password/interfaces.py:303
+msgid "Password must be changed on next login"
+msgstr ""
+
+#: z3c/password/interfaces.py:308 z3c/password/interfaces.py:309
+msgid "Password expires after (days)"
+msgstr ""
+
+#: z3c/password/interfaces.py:314
+msgid "Lockout period (minutes)"
+msgstr ""
+
+#: z3c/password/interfaces.py:315
+msgid ""
+"Lockout the user after too many failed password entriesfor this many "
+"minutes. The user can try again after."
+msgstr ""
+
+#: z3c/password/interfaces.py:32
msgid "Password is too short."
msgstr "ÐаÑÐ¾Ð»Ñ ÑлиÑком коÑоÑкий."
-#: src/z3c/password/interfaces.py:35
+#: z3c/password/interfaces.py:321
+msgid "Max. number of failed password entries before account is locked"
+msgstr ""
+
+#: z3c/password/interfaces.py:322
+msgid ""
+"Specifies the amount of failed attempts allowed to check the password before "
+"the password is locked and no new password can be provided."
+msgstr ""
+
+#: z3c/password/interfaces.py:329
+msgid "Failed password check method"
+msgstr ""
+
+#: z3c/password/interfaces.py:330
+msgid ""
+"Failed password check method. All requests, non-reqource requests, POST "
+"requests."
+msgstr ""
+
+#: z3c/password/interfaces.py:337
+msgid "Disallow Password Reuse"
+msgstr ""
+
+#: z3c/password/interfaces.py:338
+msgid "Do not allow to set a previously set password again."
+msgstr ""
+
+#: z3c/password/interfaces.py:35
msgid "Password is too long."
msgstr "ÐаÑÐ¾Ð»Ñ ÑлиÑком длиннÑй."
-#: src/z3c/password/interfaces.py:38
+#: z3c/password/interfaces.py:38
msgid "Password is too similar to old one."
msgstr "ÐаÑÐ¾Ð»Ñ ÑлиÑком поÑ
ож на ÑÑаÑÑй."
-#: src/z3c/password/interfaces.py:41
+#: z3c/password/interfaces.py:41
msgid "Password contains too many characters of one group."
msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
-#: src/z3c/password/interfaces.py:44
+#: z3c/password/interfaces.py:44
+#, fuzzy
+msgid "Password does not contain enough characters of one group."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:47
+#, fuzzy
+msgid "Password does not contain enough characters of lowercase letters."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:51
+#, fuzzy
+msgid "Password does not contain enough characters of uppercase letters."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:55
+#, fuzzy
+msgid "Password does not contain enough characters of digits."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:58
+#, fuzzy
+msgid "Password does not contain enough characters of special characters."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:62
+#, fuzzy
+msgid "Password does not contain enough characters of other characters."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:66
+#, fuzzy
+msgid "Password does not contain enough unique characters."
+msgstr "ÐаÑÐ¾Ð»Ñ ÑодеÑÐ¶Ð¸Ñ ÑлиÑком много Ñимволов одной гÑÑппÑ."
+
+#: z3c/password/interfaces.py:69
+msgid "Password does not contain enough unique letters."
+msgstr ""
+
+#: z3c/password/interfaces.py:72
msgid "The password has expired."
msgstr "ÐÑÐµÐ¼Ñ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð¿Ð°ÑÐ¾Ð»Ñ Ð¸ÑÑекло."
-#: src/z3c/password/interfaces.py:51
+#: z3c/password/interfaces.py:79
+#, fuzzy
+msgid "The password set was already used before."
+msgstr "ÐÑÐµÐ¼Ñ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð¿Ð°ÑÐ¾Ð»Ñ Ð¸ÑÑекло."
+
+#: z3c/password/interfaces.py:86
msgid "The password was entered incorrectly too often."
msgstr "ÐепÑавилÑнÑй паÑÐ¾Ð»Ñ Ð±Ñл введÑн ÑлиÑком много Ñаз."
-#: src/z3c/password/interfaces.py:67
-msgid "Description"
-msgstr "ÐпиÑание"
-
-#: src/z3c/password/interfaces.py:68
-msgid "A description of the password utility."
-msgstr "ÐпиÑание ÑÑилиÑÑ Ð¿Ð°Ñолей."
-
-#: src/z3c/password/interfaces.py:98
-msgid "Minimum Length"
-msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð°"
-
-#: src/z3c/password/interfaces.py:99
-msgid "The minimum length of the password."
-msgstr "ÐинималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° паÑолÑ."
-
+#: z3c/password/interfaces.py:97
+#, fuzzy
+msgid ""
+"The account is locked, because the password was entered incorrectly too "
+"often."
+msgstr "ÐепÑавилÑнÑй паÑÐ¾Ð»Ñ Ð±Ñл введÑн ÑлиÑком много Ñаз."
Modified: z3c.password/trunk/src/z3c/password/locales/z3c.password.pot
===================================================================
--- z3c.password/trunk/src/z3c/password/locales/z3c.password.pot 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/locales/z3c.password.pot 2010-01-29 17:28:55 UTC (rev 108644)
@@ -14,7 +14,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Development/Unknown\n"
-"POT-Creation-Date: Thu Aug 6 16:10:14 2009\n"
+"POT-Creation-Date: Fri Jan 29 17:24:33 2010\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
"Language-Team: Zope 3 Developers <zope3-dev at zope.org>\n"
@@ -23,177 +23,205 @@
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: zope/app/locales/extract.py\n"
-#: src/z3c/password/interfaces.py:122
+#: z3c/password/interfaces.py:114
+msgid "Description"
+msgstr ""
+
+#: z3c/password/interfaces.py:115
+msgid "A description of the password utility."
+msgstr ""
+
+#: z3c/password/interfaces.py:145
msgid "Minimum Length"
msgstr ""
-#: src/z3c/password/interfaces.py:123
+#: z3c/password/interfaces.py:146
msgid "The minimum length of the password."
msgstr ""
-#: src/z3c/password/interfaces.py:128
+#: z3c/password/interfaces.py:151
msgid "Maximum Length"
msgstr ""
-#: src/z3c/password/interfaces.py:129
+#: z3c/password/interfaces.py:152
msgid "The maximum length of the password."
msgstr ""
-#: src/z3c/password/interfaces.py:141
+#: z3c/password/interfaces.py:164
msgid "Maximum Characters of Group"
msgstr ""
-#: src/z3c/password/interfaces.py:142
+#: z3c/password/interfaces.py:165
msgid "The maximum amount of characters that a password can have from one group. The groups are: digits, letters, punctuation."
msgstr ""
-#: src/z3c/password/interfaces.py:149
+#: z3c/password/interfaces.py:172
msgid "Old/New Similarity"
msgstr ""
-#: src/z3c/password/interfaces.py:155
+#: z3c/password/interfaces.py:178
msgid "Minimum Number of Lowercase letters"
msgstr ""
-#: src/z3c/password/interfaces.py:156
+#: z3c/password/interfaces.py:179
msgid "The minimum amount of lowercase letters that a password must have."
msgstr ""
-#: src/z3c/password/interfaces.py:162
+#: z3c/password/interfaces.py:185
msgid "Minimum Number of Uppercase letters"
msgstr ""
-#: src/z3c/password/interfaces.py:163
+#: z3c/password/interfaces.py:186
msgid "The minimum amount of uppercase letters that a password must have."
msgstr ""
-#: src/z3c/password/interfaces.py:169
+#: z3c/password/interfaces.py:192
msgid "Minimum Number of Numeric digits"
msgstr ""
-#: src/z3c/password/interfaces.py:170
+#: z3c/password/interfaces.py:193
msgid "The minimum amount of numeric digits that a password must have."
msgstr ""
-#: src/z3c/password/interfaces.py:176
+#: z3c/password/interfaces.py:199
msgid "Minimum Number of Special characters"
msgstr ""
-#: src/z3c/password/interfaces.py:177
+#: z3c/password/interfaces.py:200
msgid "The minimum amount of special characters that a password must have."
msgstr ""
-#: src/z3c/password/interfaces.py:184
+#: z3c/password/interfaces.py:207
msgid "Minimum Number of Other characters"
msgstr ""
-#: src/z3c/password/interfaces.py:185
+#: z3c/password/interfaces.py:208
msgid "The minimum amount of other characters that a password must have."
msgstr ""
-#: src/z3c/password/interfaces.py:236
+#: z3c/password/interfaces.py:259
msgid "Minimum Number of Unique letters"
msgstr ""
-#: src/z3c/password/interfaces.py:237
+#: z3c/password/interfaces.py:260
msgid "The minimum amount of unique letters that a password must have. This is against passwords like `aAaA0000`. All characters taken lowercase."
msgstr ""
-#: src/z3c/password/interfaces.py:253
+#: z3c/password/interfaces.py:276
msgid "Minimum Number of Unique characters"
msgstr ""
-#: src/z3c/password/interfaces.py:254
+#: z3c/password/interfaces.py:277
msgid "The minimum amount of unique characters that a password must have. This is against passwords like `aAaA0000`. All characters taken lowercase."
msgstr ""
-#: src/z3c/password/interfaces.py:279
-#: src/z3c/password/interfaces.py:280
+#: z3c/password/interfaces.py:29
+msgid "No new password specified."
+msgstr ""
+
+#: z3c/password/interfaces.py:302
+#: z3c/password/interfaces.py:303
msgid "Password must be changed on next login"
msgstr ""
-#: src/z3c/password/interfaces.py:285
-#: src/z3c/password/interfaces.py:286
+#: z3c/password/interfaces.py:308
+#: z3c/password/interfaces.py:309
msgid "Password expires after (days)"
msgstr ""
-#: src/z3c/password/interfaces.py:29
-msgid "No new password specified."
-msgstr ""
-
-#: src/z3c/password/interfaces.py:291
+#: z3c/password/interfaces.py:314
msgid "Lockout period (minutes)"
msgstr ""
-#: src/z3c/password/interfaces.py:292
+#: z3c/password/interfaces.py:315
msgid "Lockout the user after too many failed password entriesfor this many minutes. The user can try again after."
msgstr ""
-#: src/z3c/password/interfaces.py:298
+#: z3c/password/interfaces.py:32
+msgid "Password is too short."
+msgstr ""
+
+#: z3c/password/interfaces.py:321
msgid "Max. number of failed password entries before account is locked"
msgstr ""
-#: src/z3c/password/interfaces.py:299
+#: z3c/password/interfaces.py:322
msgid "Specifies the amount of failed attempts allowed to check the password before the password is locked and no new password can be provided."
msgstr ""
-#: src/z3c/password/interfaces.py:306
+#: z3c/password/interfaces.py:329
+msgid "Failed password check method"
+msgstr ""
+
+#: z3c/password/interfaces.py:330
+msgid "Failed password check method. All requests, non-reqource requests, POST requests."
+msgstr ""
+
+#: z3c/password/interfaces.py:337
msgid "Disallow Password Reuse"
msgstr ""
-#: src/z3c/password/interfaces.py:307
+#: z3c/password/interfaces.py:338
msgid "Do not allow to set a previously set password again."
msgstr ""
-#: src/z3c/password/interfaces.py:32
-msgid "Password is too short."
-msgstr ""
-
-#: src/z3c/password/interfaces.py:35
+#: z3c/password/interfaces.py:35
msgid "Password is too long."
msgstr ""
-#: src/z3c/password/interfaces.py:38
+#: z3c/password/interfaces.py:38
msgid "Password is too similar to old one."
msgstr ""
-#: src/z3c/password/interfaces.py:41
+#: z3c/password/interfaces.py:41
msgid "Password contains too many characters of one group."
msgstr ""
-#: src/z3c/password/interfaces.py:44
+#: z3c/password/interfaces.py:44
msgid "Password does not contain enough characters of one group."
msgstr ""
-#: src/z3c/password/interfaces.py:47
+#: z3c/password/interfaces.py:47
+msgid "Password does not contain enough characters of lowercase letters."
+msgstr ""
+
+#: z3c/password/interfaces.py:51
+msgid "Password does not contain enough characters of uppercase letters."
+msgstr ""
+
+#: z3c/password/interfaces.py:55
+msgid "Password does not contain enough characters of digits."
+msgstr ""
+
+#: z3c/password/interfaces.py:58
+msgid "Password does not contain enough characters of special characters."
+msgstr ""
+
+#: z3c/password/interfaces.py:62
+msgid "Password does not contain enough characters of other characters."
+msgstr ""
+
+#: z3c/password/interfaces.py:66
msgid "Password does not contain enough unique characters."
msgstr ""
-#: src/z3c/password/interfaces.py:50
+#: z3c/password/interfaces.py:69
msgid "Password does not contain enough unique letters."
msgstr ""
-#: src/z3c/password/interfaces.py:53
+#: z3c/password/interfaces.py:72
msgid "The password has expired."
msgstr ""
-#: src/z3c/password/interfaces.py:60
+#: z3c/password/interfaces.py:79
msgid "The password set was already used before."
msgstr ""
-#: src/z3c/password/interfaces.py:67
+#: z3c/password/interfaces.py:86
msgid "The password was entered incorrectly too often."
msgstr ""
-#: src/z3c/password/interfaces.py:74
+#: z3c/password/interfaces.py:97
msgid "The account is locked, because the password was entered incorrectly too often."
msgstr ""
-#: src/z3c/password/interfaces.py:91
-msgid "Description"
-msgstr ""
-
-#: src/z3c/password/interfaces.py:92
-msgid "A description of the password utility."
-msgstr ""
-
Modified: z3c.password/trunk/src/z3c/password/password.py
===================================================================
--- z3c.password/trunk/src/z3c/password/password.py 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/password.py 2010-01-29 17:28:55 UTC (rev 108644)
@@ -146,23 +146,23 @@
if (self.minLowerLetter is not None
and num_lower_letters < self.minLowerLetter):
- raise interfaces.TooFewGroupCharacters()
+ raise interfaces.TooFewGroupCharactersLowerLetter()
if (self.minUpperLetter is not None
and num_upper_letters < self.minUpperLetter):
- raise interfaces.TooFewGroupCharacters()
+ raise interfaces.TooFewGroupCharactersUpperLetter()
if (self.minDigits is not None
and num_digits < self.minDigits):
- raise interfaces.TooFewGroupCharacters()
+ raise interfaces.TooFewGroupCharactersDigits()
if (self.minSpecials is not None
and num_specials < self.minSpecials):
- raise interfaces.TooFewGroupCharacters()
+ raise interfaces.TooFewGroupCharactersSpecials()
if (self.minOthers is not None
and num_others < self.minOthers):
- raise interfaces.TooFewGroupCharacters()
+ raise interfaces.TooFewGroupCharactersOthers()
if (self.minUniqueCharacters is not None
and len(uniqueChars) < self.minUniqueCharacters):
@@ -212,13 +212,17 @@
interfaces.IPasswordOptionsUtility['maxFailedAttempts'])
disallowPasswordReuse = FieldProperty(
interfaces.IPasswordOptionsUtility['disallowPasswordReuse'])
+ failedAttemptCheck = FieldProperty(
+ interfaces.IPasswordOptionsUtility['failedAttemptCheck'])
def __init__(self, changePasswordOnNextLogin=None,
passwordExpiresAfter=None,
lockOutPeriod=None, maxFailedAttempts=None,
- disallowPasswordReuse=None):
+ disallowPasswordReuse=None,
+ failedAttemptCheck=None):
self.changePasswordOnNextLogin = changePasswordOnNextLogin
self.passwordExpiresAfter = passwordExpiresAfter
self.lockOutPeriod = lockOutPeriod
self.maxFailedAttempts = maxFailedAttempts
- self.disallowPasswordReuse = disallowPasswordReuse
\ No newline at end of file
+ self.disallowPasswordReuse = disallowPasswordReuse
+ self.failedAttemptCheck = failedAttemptCheck
\ No newline at end of file
Modified: z3c.password/trunk/src/z3c/password/principal.py
===================================================================
--- z3c.password/trunk/src/z3c/password/principal.py 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/principal.py 2010-01-29 17:28:55 UTC (rev 108644)
@@ -19,6 +19,8 @@
import datetime
import persistent.list
import zope.component
+from zope.security.management import getInteraction
+
from z3c.password import interfaces
class PrincipalMixIn(object):
@@ -31,6 +33,7 @@
#e.g. for changePasswordOnNextLogin
failedAttempts = 0
+ failedAttemptCheck = interfaces.TML_CHECK_ALL
maxFailedAttempts = None
lastFailedAttempt = None
lockOutPeriod = None
@@ -115,9 +118,7 @@
add = 0
else:
#failed attempt, record it, increase counter
- self.failedAttempts += 1
- self.lastFailedAttempt = self.now()
- add = 1
+ add = self.checkFailedAttempt()
# If the maximum amount of failures has been reached notify the
# system by raising an error.
@@ -132,6 +133,45 @@
return same
+ def _getRequest(self):
+ interaction = getInteraction()
+ try:
+ return interaction.participations[0]
+ except IndexError:
+ return None
+
+ def checkFailedAttempt(self):
+ #failed attempt, record it, increase counter (in case we have to)
+ validRequest = True
+ fac = self._failedAttemptCheck()
+ if fac == interfaces.TML_CHECK_ALL:
+ validRequest = True
+ else:
+ request = self._getRequest()
+ if request is None:
+ validRequest = True
+ else:
+ if fac == interfaces.TML_CHECK_NONRESOURCE:
+ url = request.getURL()
+ if '/@@/' in url:
+ #this is a resource
+ validRequest = False
+ else:
+ validRequest = True
+ elif fac == interfaces.TML_CHECK_POSTONLY:
+ if request.method == 'POST':
+ #this is a POST request
+ validRequest = True
+ else:
+ validRequest = False
+
+ if validRequest:
+ self.failedAttempts += 1
+ self.lastFailedAttempt = self.now()
+ return 1
+ else:
+ return 0
+
def tooManyLoginFailures(self, add = 0):
attempts = self._maxFailedAttempts()
#this one needs to be >=, because... data just does not
@@ -199,6 +239,19 @@
else:
return self.lockOutPeriod
+ def _failedAttemptCheck(self):
+ if self.failedAttemptCheck is not None:
+ return self.failedAttemptCheck
+
+ options = self._optionsUtility()
+ if options is None:
+ return self.failedAttemptCheck
+ else:
+ if options.failedAttemptCheck is not None:
+ return options.failedAttemptCheck
+ else:
+ return self.failedAttemptCheck
+
def _maxFailedAttempts(self):
if self.maxFailedAttempts is not None:
return self.maxFailedAttempts
Modified: z3c.password/trunk/src/z3c/password/principal.txt
===================================================================
--- z3c.password/trunk/src/z3c/password/principal.txt 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/principal.txt 2010-01-29 17:28:55 UTC (rev 108644)
@@ -104,6 +104,7 @@
Let's now create a principal:
>>> from zope.app.authentication import principalfolder
+ >>> from z3c.password import interfaces
>>> from z3c.password import principal
>>> class MyPrincipal(principal.PrincipalMixIn,
@@ -130,6 +131,9 @@
>>> user.checkPassword('123123')
True
+failedAttempts
+--------------
+
Initially, the amount of failed attempts is zero, ...
>>> user.failedAttempts
@@ -180,6 +184,132 @@
>>> user.failedAttempts = 0
+
+failedAttemptCheck, non-resource
+---------------------------------
+
+ >>> import zope.security.management
+ >>> from z3c.password import testing
+
+Set the option on the user:
+
+ >>> user.failedAttemptCheck = interfaces.TML_CHECK_NONRESOURCE
+
+Create our dummy request:
+Watch out! this is a request for a resource (/@@/)
+
+ >>> request = testing.TestBrowserRequest('http://localhost/@@/logo.gif')
+ >>> zope.security.management.getInteraction().add(request)
+
+Reset the counter:
+
+ >>> user.failedAttempts = 0
+
+Here's the password checking.
+The password is wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But the counter is not incremented.
+
+ >>> user.failedAttempts
+ 0
+
+Try a non-resource request.
+
+ >>> zope.security.management.getInteraction().remove(request)
+ >>> request = testing.TestBrowserRequest('http://localhost/loginform.html',
+ ... 'POST')
+ >>> zope.security.management.getInteraction().add(request)
+
+Password is still wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But now the counter is incremented.
+
+ >>> user.failedAttempts
+ 1
+
+Try now without a request in effect (as an edge case):
+
+ >>> zope.security.management.getInteraction().remove(request)
+
+ >>> user.failedAttempts = 0
+
+A bad password gets counted.
+
+ >>> user.checkPassword('456456')
+ False
+ >>> user.failedAttempts
+ 1
+
+failedAttemptCheck, POST
+-------------------------
+
+Set the option on the user:
+
+ >>> user.failedAttemptCheck = interfaces.TML_CHECK_POSTONLY
+
+Create our dummy request:
+Watch out! this is a normal GET request.
+
+ >>> request = testing.TestBrowserRequest('http://localhost/index.html', 'GET')
+ >>> zope.security.management.getInteraction().add(request)
+
+ >>> user.failedAttempts = 0
+
+Here's the password checking.
+The password is wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But the counter is not incremented.
+
+ >>> user.failedAttempts
+ 0
+
+Try a POST request. What a loginform usually is.
+(Note, that the request gets examined only if the password does not match.)
+
+ >>> zope.security.management.getInteraction().remove(request)
+ >>> request = testing.TestBrowserRequest('http://localhost/loginform.html',
+ ... 'POST')
+ >>> zope.security.management.getInteraction().add(request)
+
+Password is still wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But now the counter is incremented.
+
+ >>> user.failedAttempts
+ 1
+
+Try now without a request in effect (as an edge case):
+
+ >>> zope.security.management.getInteraction().remove(request)
+
+ >>> user.failedAttempts = 0
+
+A bad password gets counted.
+
+ >>> user.checkPassword('456456')
+ False
+ >>> user.failedAttempts
+ 1
+
+Reset the option on the user:
+
+ >>> user.failedAttemptCheck = None
+
+Expired password
+----------------
+
Next we expire the password:
>>> NOW = datetime.datetime(2009, 6, 14, 13, 0) + datetime.timedelta(181)
@@ -220,7 +350,6 @@
>>> import zope.interface
>>> import zope.component
- >>> from z3c.password import interfaces
>>> from z3c.password.password import PasswordOptionsUtility
>>> poptions = PasswordOptionsUtility()
>>> zope.component.provideUtility(poptions)
@@ -400,7 +529,126 @@
>>> user.checkPassword('234234')
True
+failedAttemptCheck, non-resource
+---------------------------------
+Set the option on the utility:
+
+ >>> poptions.failedAttemptCheck = interfaces.TML_CHECK_NONRESOURCE
+
+Create our dummy request:
+Watch out! this is a request for a resource (/@@/)
+
+ >>> request = testing.TestBrowserRequest('http://localhost/@@/logo.gif')
+ >>> zope.security.management.getInteraction().add(request)
+
+Reset the counter:
+
+ >>> user.failedAttempts = 0
+
+Here's the password checking.
+The password is wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But the counter is not incremented.
+
+ >>> user.failedAttempts
+ 0
+
+Try a non-resource request.
+
+ >>> zope.security.management.getInteraction().remove(request)
+ >>> request = testing.TestBrowserRequest('http://localhost/loginform.html',
+ ... 'POST')
+ >>> zope.security.management.getInteraction().add(request)
+
+Password is still wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But now the counter is incremented.
+
+ >>> user.failedAttempts
+ 1
+
+Try now without a request in effect (as an edge case):
+
+ >>> zope.security.management.getInteraction().remove(request)
+
+ >>> user.failedAttempts = 0
+
+A bad password gets counted.
+
+ >>> user.checkPassword('456456')
+ False
+ >>> user.failedAttempts
+ 1
+
+failedAttemptCheck, POST
+-------------------------
+
+Set the option on the utility:
+
+ >>> poptions.failedAttemptCheck = interfaces.TML_CHECK_POSTONLY
+
+Create our dummy request:
+Watch out! this is a normal GET request.
+
+ >>> request = testing.TestBrowserRequest('http://localhost/index.html', 'GET')
+ >>> zope.security.management.getInteraction().add(request)
+
+ >>> user.failedAttempts = 0
+
+Here's the password checking.
+The password is wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But the counter is not incremented.
+
+ >>> user.failedAttempts
+ 0
+
+Try a POST request. What a loginform usually is.
+(Note, that the request gets examined only if the password does not match.)
+
+ >>> zope.security.management.getInteraction().remove(request)
+ >>> request = testing.TestBrowserRequest('http://localhost/loginform.html',
+ ... 'POST')
+ >>> zope.security.management.getInteraction().add(request)
+
+Password is still wrong.
+
+ >>> user.checkPassword('456456')
+ False
+
+But now the counter is incremented.
+
+ >>> user.failedAttempts
+ 1
+
+Try now without a request in effect (as an edge case):
+
+ >>> zope.security.management.getInteraction().remove(request)
+
+ >>> user.failedAttempts = 0
+
+A bad password gets counted.
+
+ >>> user.checkPassword('456456')
+ False
+ >>> user.failedAttempts
+ 1
+
+Reset the option on the utility:
+
+ >>> poptions.failedAttemptCheck = None
+
+
Timed lockout
-------------
Modified: z3c.password/trunk/src/z3c/password/testing.py
===================================================================
--- z3c.password/trunk/src/z3c/password/testing.py 2010-01-29 16:30:50 UTC (rev 108643)
+++ z3c.password/trunk/src/z3c/password/testing.py 2010-01-29 17:28:55 UTC (rev 108644)
@@ -30,3 +30,15 @@
def tearDown(test):
placelesssetup.tearDown(test)
+
+
+class TestBrowserRequest():
+ """pretty dumb test request"""
+
+ def __init__(self, url, method='GET'):
+ self.URL = url
+ self.method = method
+ self.interaction = None
+
+ def getURL(self):
+ return self.URL
More information about the checkins
mailing list