Skip to content
Browse files

automatically clear after a while (bug 827580)

  • Loading branch information...
1 parent f1569c4 commit 292027e03b932c0023aaab232db341bd87de31dd @andymckay andymckay committed with wraithan Jan 7, 2013
Showing with 44 additions and 3 deletions.
  1. +9 −1 lib/buyers/models.py
  2. +12 −1 lib/buyers/tests/test_api.py
  3. +21 −1 lib/buyers/tests/test_models.py
  4. +2 −0 solitude/settings/base.py
View
10 lib/buyers/models.py
@@ -24,7 +24,15 @@ class Meta(Model.Meta):
@property
def locked_out(self):
- return bool(self.pin_locked_out)
+ if not self.pin_locked_out:
+ return False
+
+ if ((datetime.now() - self.pin_locked_out).seconds >
+ settings.PIN_FAILURE_LENGTH):
+ self.clear_lockout()
+ return False
+
+ return True
def clear_lockout(self):
self.pin_failures = 0
View
13 lib/buyers/tests/test_api.py
@@ -1,4 +1,4 @@
-from datetime import datetime
+from datetime import datetime, timedelta
import json
from django.conf import settings
@@ -282,6 +282,17 @@ def test_good_pin_but_locked_out(self, log_cef):
assert log_cef.called
eq_(res.status_code, 403)
+ def test_locked_out_over_time(self):
+ self.buyer.pin_locked_out = (datetime.now() -
+ timedelta(seconds=settings.PIN_FAILURE_LENGTH + 60))
+ self.buyer.save()
+
+ res = self.client.post(self.list_url, data={'uuid': self.uuid,
+ 'pin': self.pin})
+ eq_(res.status_code, 201)
+ data = json.loads(res.content)
+ assert data['valid']
+
def test_good_reset_failures(self):
self.buyer.pin_failures = 1
self.buyer.save()
View
22 lib/buyers/tests/test_models.py
@@ -1,4 +1,4 @@
-from datetime import datetime
+from datetime import datetime, timedelta
from aesfield.field import EncryptedField
from nose.tools import eq_
@@ -41,6 +41,13 @@ def test_filter(self):
with self.assertRaises(EncryptedField):
BuyerPaypal.objects.filter(key='bar')
+
+class TestLockout(TestCase):
+
+ def setUp(self):
+ self.uid = 'test:uid'
+ self.buyer = Buyer.objects.create(uuid=self.uid)
+
def test_locked_out(self):
assert not self.buyer.locked_out
self.buyer.pin_locked_out = datetime.now()
@@ -67,3 +74,16 @@ def test_clear(self):
self.buyer.clear_lockout()
eq_(self.buyer.pin_failures, 0)
eq_(self.buyer.pin_locked_out, None)
+
+ def test_under_timeout(self):
+ self.buyer.pin_locked_out = (datetime.now() -
+ timedelta(seconds=settings.PIN_FAILURE_LENGTH - 60))
+ self.buyer.save()
+ assert self.buyer.locked_out
+
+ def test_over_timeout(self):
+ self.buyer.pin_locked_out = (datetime.now() -
+ timedelta(seconds=settings.PIN_FAILURE_LENGTH + 60))
+ self.buyer.save()
+ assert not self.buyer.locked_out
+ eq_(self.buyer.reget().pin_locked_out, None)
View
2 solitude/settings/base.py
@@ -189,3 +189,5 @@
# The number of PIN failures before we lock them out.
PIN_FAILURES = 5
+# The amount of time before you can try it again in seconds.
+PIN_FAILURE_LENGTH = 600

0 comments on commit 292027e

Please sign in to comment.
Something went wrong with that request. Please try again.