Browse Source

HUE-3861 [core] Upgrade Django Axes to 1.5

Fixes the AXES_LOCKOUT_BY_COMBINATION_USER_AND_IP issue

NOTE: Axes 1.6+ requires Django 1.7+, so until we update the Django rolled into Hue, we can't upgrade Axes
Jenny Kim 10 years ago
parent
commit
6f31373
44 changed files with 39 additions and 715 deletions
  1. 11 0
      desktop/core/ext-py/django-axes-1.5.0/.gitignore
  2. 0 4
      desktop/core/ext-py/django-axes-1.5.0/.travis.yml
  3. 0 21
      desktop/core/ext-py/django-axes-1.5.0/CHANGES.txt
  4. 0 0
      desktop/core/ext-py/django-axes-1.5.0/LICENSE
  5. 0 0
      desktop/core/ext-py/django-axes-1.5.0/MANIFEST.in
  6. 0 0
      desktop/core/ext-py/django-axes-1.5.0/Makefile
  7. 0 48
      desktop/core/ext-py/django-axes-1.5.0/README.rst
  8. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/__init__.py
  9. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/admin.py
  10. 23 24
      desktop/core/ext-py/django-axes-1.5.0/axes/decorators.py
  11. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/management/__init__.py
  12. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/__init__.py
  13. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/axes_list_attempts.py
  14. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/axes_reset.py
  15. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/middleware.py
  16. 0 4
      desktop/core/ext-py/django-axes-1.5.0/axes/models.py
  17. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/signals.py
  18. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/test_settings.py
  19. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/test_urls.py
  20. 4 13
      desktop/core/ext-py/django-axes-1.5.0/axes/tests.py
  21. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/utils.py
  22. 0 0
      desktop/core/ext-py/django-axes-1.5.0/axes/views.py
  23. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/README.rst
  24. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/__init__.py
  25. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/__init__.py
  26. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/__init__.py
  27. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/commands/__init__.py
  28. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/commands/axes_create_test_data.py
  29. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/models.py
  30. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/local_settings.example
  31. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/manage.py
  32. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/settings.py
  33. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/urls.py
  34. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/example/wsgi.py
  35. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/install.sh
  36. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/reinstall.sh
  37. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/test.sh
  38. 0 0
      desktop/core/ext-py/django-axes-1.5.0/examples/uninstall.sh
  39. 1 1
      desktop/core/ext-py/django-axes-1.5.0/setup.py
  40. 0 490
      desktop/core/ext-py/django-axes-1.6.0/PKG-INFO
  41. 0 51
      desktop/core/ext-py/django-axes-1.6.0/axes/migrations/0001_initial.py
  42. 0 54
      desktop/core/ext-py/django-axes-1.6.0/axes/migrations/0002_auto_20151217_2044.py
  43. 0 0
      desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/management/commands/__init__.py
  44. 0 5
      desktop/core/ext-py/django-axes-1.6.0/setup.cfg

+ 11 - 0
desktop/core/ext-py/django-axes-1.5.0/.gitignore

@@ -0,0 +1,11 @@
+django_axes.egg-info
+*.pyc
+build
+dist
+.hg
+.DS_Store
+examples/db/
+examples/logs/
+examples/media/
+examples/static/
+examples/example/local_settings.py

+ 0 - 4
desktop/core/ext-py/django-axes-1.6.0/.travis.yml → desktop/core/ext-py/django-axes-1.5.0/.travis.yml

@@ -3,14 +3,12 @@ language: python
 python:
   - 2.7
   - 3.3
-  - 3.4
 
 env:
   - DJANGO=Django==1.4.15
   - DJANGO=Django==1.5.10
   - DJANGO=Django==1.6.7
   - DJANGO=Django==1.7
-  - DJANGO=Django==1.8.5
 
 install:
   - pip install -q $DJANGO
@@ -22,5 +20,3 @@ matrix:
     exclude:
         - python: 3.3
           env: DJANGO=Django==1.4.15
-        - python: 3.4
-          env: DJANGO=Django==1.4.15

+ 0 - 21
desktop/core/ext-py/django-axes-1.6.0/CHANGES.txt → desktop/core/ext-py/django-axes-1.5.0/CHANGES.txt

@@ -1,27 +1,6 @@
 Changes
 =======
 
-1.6.0 (2016-01-07)
-------------------
-
-- Stopped using render_to_response so that other template engines work
-  [tarkatronic]
-
-- Improved performance & DoS prevention on query2str
-  [tarkatronic]
-
-- Immediately return from is_already_locked if the user is not lockable
-  [jdunck]
-
-- Iterate over ip addresses only once
-  [annp89]
-
-- added initial migration files to support django 1.7 &up
-  [ibaguio]
-
-- Add db indexes to CommonAccess model
-  [Schweigi]
-
 1.5.0 (2015-09-11)
 ------------------
 

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/LICENSE → desktop/core/ext-py/django-axes-1.5.0/LICENSE


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/MANIFEST.in → desktop/core/ext-py/django-axes-1.5.0/MANIFEST.in


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/Makefile → desktop/core/ext-py/django-axes-1.5.0/Makefile


+ 0 - 48
desktop/core/ext-py/django-axes-1.6.0/README.rst → desktop/core/ext-py/django-axes-1.5.0/README.rst

@@ -165,51 +165,3 @@ leads to all users attempts being lumped together. To fix this add the following
 to your settings:
 
     AXES_USERNAME_FORM_FIELD = "email"
-
-
-Using a captcha
-===============
-
-Using https://github.com/mbi/django-simple-captcha you do the following:
-
-1. Change axes lockout url in ``settings.py``::
-
-    AXES_LOCKOUT_URL = '/locked'
-
-2. Add the url in ``urls.py``::
-
-    url(r'^locked/$', locked_out, name='locked_out'),
-
-3. Create a captcha form::
-
-    class AxesCaptchaForm(forms.Form):
-        captcha = CaptchaField()
-
-4. Create a captcha view for the above url that resets on captcha success and redirects::
-
-    def locked_out(request):
-        if request.POST:
-            form = AxesCaptchaForm(request.POST)
-            if form.is_valid():
-                ip = get_ip_address_from_request(request)
-                reset(ip=ip)
-                return HttpResponseRedirect(reverse_lazy('signin'))
-        else:
-            form = AxesCaptchaForm()
-    
-        return render_to_response('locked_out.html', dict(form=form), context_instance=RequestContext(request))
-
-5. Add a captcha template::
-
-    <form action="" method="post">
-        {% csrf_token %}
-    
-        {{ form.captcha.errors }}
-        {{ form.captcha }}
-    
-        <div class="form-actions">
-            <input type="submit" value="Submit" />
-        </div>
-    </form>
-
-Done.

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/__init__.py → desktop/core/ext-py/django-axes-1.5.0/axes/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/admin.py → desktop/core/ext-py/django-axes-1.5.0/axes/admin.py


+ 23 - 24
desktop/core/ext-py/django-axes-1.6.0/axes/decorators.py → desktop/core/ext-py/django-axes-1.5.0/axes/decorators.py

@@ -8,7 +8,8 @@ from django.contrib.auth import logout
 from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpResponse
 from django.http import HttpResponseRedirect
-from django.template.loader import get_template
+from django.shortcuts import render_to_response
+from django.template import RequestContext
 from django.utils import timezone as datetime
 from django.utils.translation import ugettext_lazy
 
@@ -106,8 +107,8 @@ def get_ip_address_from_request(request):
         if not x_forwarded_for.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_forwarded_for):
             ip_address = x_forwarded_for.strip()
     else:
-        for ip_raw in x_forwarded_for.split(','):
-            ip = ip_raw.strip()
+        ips = [ip.strip() for ip in x_forwarded_for.split(',')]
+        for ip in ips:
             if ip.startswith(PRIVATE_IPS_PREFIX):
                 continue
             elif not is_valid_ip(ip):
@@ -160,11 +161,15 @@ def query2str(items, max_length=1024):
 
     If there's a field called "password" it will be excluded from the output.
 
-    The length of the output is limited to max_length to avoid a DoS attack via excessively large payloads.
+    The length of the output is limited to max_length to avoid a DoS attack.
     """
 
-    return '\n'.join(['%s=%s' % (k, v) for k, v in six.iteritems(items)
-                      if k != PASSWORD_FORM_FIELD][:int(max_length/2)])[:max_length]
+    kvs = []
+    for k, v in items:
+        if k != PASSWORD_FORM_FIELD:
+            kvs.append(six.u('%s=%s') % (k, v))
+
+    return '\n'.join(kvs)[:max_length]
 
 
 def ip_in_whitelist(ip):
@@ -197,7 +202,7 @@ def is_user_lockable(request):
         return True
 
     if hasattr(user, 'nolockout'):
-        # need to invert since we need to return
+        # need to revert since we need to return
         # false for users that can't be blocked
         return not user.nolockout
 
@@ -205,7 +210,7 @@ def is_user_lockable(request):
         try:
             profile = user.get_profile()
             if hasattr(profile, 'nolockout'):
-                # need to invert since we need to return
+                # need to revert since we need to return
                 # false for users that can't be blocked
                 return not profile.nolockout
 
@@ -340,9 +345,8 @@ def lockout_response(request):
             'failure_limit': FAILURE_LIMIT,
             'username': request.POST.get(USERNAME_FORM_FIELD, '')
         }
-        template = get_template(LOCKOUT_TEMPLATE)
-        content = template.render(context, request)
-        return HttpResponse(content)
+        return render_to_response(LOCKOUT_TEMPLATE, context,
+                                  context_instance=RequestContext(request))
 
     LOCKOUT_URL = get_lockout_url()
     if LOCKOUT_URL:
@@ -366,15 +370,10 @@ def is_already_locked(request):
     if ip_in_blacklist(ip):
         return True
 
-    user_lockable = is_user_lockable(request)
-
-    if not user_lockable:
-        return False
-
     attempts = get_user_attempts(request)
-
+    user_lockable = is_user_lockable(request)
     for attempt in attempts:
-        if attempt.failures_since_start >= FAILURE_LIMIT and LOCK_OUT_AT_FAILURE:
+        if attempt.failures_since_start >= FAILURE_LIMIT and LOCK_OUT_AT_FAILURE and user_lockable:
             return True
 
     return False
@@ -399,11 +398,11 @@ def check_request(request, login_unsuccessful):
             for attempt in attempts:
                 attempt.get_data = '%s\n---------\n%s' % (
                     attempt.get_data,
-                    query2str(request.GET),
+                    query2str(request.GET.items()),
                 )
                 attempt.post_data = '%s\n---------\n%s' % (
                     attempt.post_data,
-                    query2str(request.POST)
+                    query2str(request.POST.items())
                 )
                 attempt.http_accept = request.META.get('HTTP_ACCEPT', '<unknown>')
                 attempt.path_info = request.META.get('PATH_INFO', '<unknown>')
@@ -462,8 +461,8 @@ def create_new_failure_records(request, failures):
         'user_agent': ua,
         'ip_address': ip,
         'username': username,
-        'get_data': query2str(request.GET),
-        'post_data': query2str(request.POST),
+        'get_data': query2str(request.GET.items()),
+        'post_data': query2str(request.POST.items()),
         'http_accept': request.META.get('HTTP_ACCEPT', '<unknown>'),
         'path_info': request.META.get('PATH_INFO', '<unknown>'),
         'failures_since_start': failures,
@@ -486,8 +485,8 @@ def create_new_trusted_record(request):
         user_agent=ua,
         ip_address=ip,
         username=username,
-        get_data=query2str(request.GET),
-        post_data=query2str(request.POST),
+        get_data=query2str(request.GET.items()),
+        post_data=query2str(request.POST.items()),
         http_accept=request.META.get('HTTP_ACCEPT', '<unknown>'),
         path_info=request.META.get('PATH_INFO', '<unknown>'),
         failures_since_start=0,

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/management/__init__.py → desktop/core/ext-py/django-axes-1.5.0/axes/management/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/management/commands/__init__.py → desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/management/commands/axes_list_attempts.py → desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/axes_list_attempts.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/management/commands/axes_reset.py → desktop/core/ext-py/django-axes-1.5.0/axes/management/commands/axes_reset.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/middleware.py → desktop/core/ext-py/django-axes-1.5.0/axes/middleware.py


+ 0 - 4
desktop/core/ext-py/django-axes-1.6.0/axes/models.py → desktop/core/ext-py/django-axes-1.5.0/axes/models.py

@@ -4,26 +4,22 @@ from django.utils import six
 class CommonAccess(models.Model):
     user_agent = models.CharField(
         max_length=255,
-        db_index=True,
     )
 
     ip_address = models.GenericIPAddressField(
         verbose_name='IP Address',
         null=True,
-        db_index=True,
     )
 
     username = models.CharField(
         max_length=255,
         null=True,
-        db_index=True,
     )
 
     # Once a user logs in from an ip, that combination is trusted and not
     # locked out in case of a distributed attack
     trusted = models.BooleanField(
         default=False,
-        db_index=True,
     )
 
     http_accept = models.CharField(

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/signals.py → desktop/core/ext-py/django-axes-1.5.0/axes/signals.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/test_settings.py → desktop/core/ext-py/django-axes-1.5.0/axes/test_settings.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/test_urls.py → desktop/core/ext-py/django-axes-1.5.0/axes/test_urls.py


+ 4 - 13
desktop/core/ext-py/django-axes-1.6.0/axes/tests.py → desktop/core/ext-py/django-axes-1.5.0/axes/tests.py

@@ -10,7 +10,7 @@ from django.core.urlresolvers import reverse
 
 from axes.decorators import COOLOFF_TIME
 from axes.decorators import FAILURE_LIMIT
-from axes.models import AccessAttempt, AccessLog
+from axes.models import AccessLog
 from axes.signals import user_locked_out
 from axes.utils import reset
 
@@ -23,7 +23,7 @@ class AccessAttemptTest(TestCase):
     LOCKED_MESSAGE = 'Account locked: too many login attempts.'
     LOGIN_FORM_KEY = '<input type="submit" value="Log in" />'
 
-    def _login(self, is_valid_username=False, is_valid_password=False, user_agent='test-browser', **kwargs):
+    def _login(self, is_valid_username=False, is_valid_password=False, user_agent='test-browser'):
         """Login a user. A valid credential is used when is_valid_username is True,
         otherwise it will use a random string to make a failed login.
         """
@@ -45,13 +45,11 @@ class AccessAttemptTest(TestCase):
         else:
             password = 'invalid-password'
 
-        post_data = {
+        response = self.client.post(admin_login, {
             'username': username,
             'password': password,
             'this_is_the_login_form': 1,
-        }
-        post_data.update(kwargs)
-        response = self.client.post(admin_login, post_data, HTTP_USER_AGENT=user_agent)
+        }, HTTP_USER_AGENT=user_agent)
 
         return response
 
@@ -207,10 +205,3 @@ class AccessAttemptTest(TestCase):
         # But we should get one now
         response = self._login(is_valid_username=True, is_valid_password=False)
         self.assertContains(response, self.LOCKED_MESSAGE)
-
-    def test_log_data_truncated(self):
-        """Tests that query2str properly truncates data to the max_length (default 1024)
-        """
-        extra_data = {string.ascii_letters * x: x for x in range(0, 1000)}  # An impossibly large post dict
-        self._login(**extra_data)
-        self.assertEquals(len(AccessAttempt.objects.latest('id').post_data), 1024)

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/utils.py → desktop/core/ext-py/django-axes-1.5.0/axes/utils.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/views.py → desktop/core/ext-py/django-axes-1.5.0/axes/views.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/README.rst → desktop/core/ext-py/django-axes-1.5.0/examples/README.rst


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/axes/migrations/__init__.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/__init__.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/__init__.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/management/__init__.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/commands/__init__.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/management/commands/axes_create_test_data.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/management/commands/axes_create_test_data.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/models.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/foo/models.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/local_settings.example → desktop/core/ext-py/django-axes-1.5.0/examples/example/local_settings.example


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/manage.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/manage.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/settings.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/settings.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/urls.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/urls.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/wsgi.py → desktop/core/ext-py/django-axes-1.5.0/examples/example/wsgi.py


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/install.sh → desktop/core/ext-py/django-axes-1.5.0/examples/install.sh


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/reinstall.sh → desktop/core/ext-py/django-axes-1.5.0/examples/reinstall.sh


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/test.sh → desktop/core/ext-py/django-axes-1.5.0/examples/test.sh


+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/uninstall.sh → desktop/core/ext-py/django-axes-1.5.0/examples/uninstall.sh


+ 1 - 1
desktop/core/ext-py/django-axes-1.6.0/setup.py → desktop/core/ext-py/django-axes-1.5.0/setup.py

@@ -4,7 +4,7 @@
 import os
 from setuptools import setup, find_packages
 
-VERSION = '1.6.0'
+VERSION = '1.5.0'
 
 setup(
     name='django-axes',

+ 0 - 490
desktop/core/ext-py/django-axes-1.6.0/PKG-INFO

@@ -1,490 +0,0 @@
-Metadata-Version: 1.1
-Name: django-axes
-Version: 1.6.0
-Summary: Keep track of failed login attempts in Django-powered sites.
-Home-page: https://github.com/django-pci/django-axes
-Author: Alex Clark
-Author-email: aclark@aclark.net
-License: MIT
-Description: Django Axes
-        ===========
-        
-        .. image:: https://secure.travis-ci.org/django-pci/django-axes.png?branch=master
-            :alt: Build Status
-            :target: http://travis-ci.org/django-pci/django-axes
-        
-        ``django-axes`` is a very simple way for you to keep track of failed login
-        attempts, both for the Django admin and for the rest of your site.  The name is
-        sort of a geeky pun, since ``axes`` can be read interpreted as:
-        
-        * "access", as in monitoring access attempts
-        * "axes", as in tools you can use hack (generally on wood).  In this case,
-          however, the "hacking" part of it can be taken a bit further: ``django-axes``
-          is intended to help you *stop* people from hacking (popular media
-          definition) your website.  Hilarious, right?  That's what I thought too!
-        
-        
-        Requirements
-        ============
-        
-        ``django-axes`` requires Django 1.5 or later. The application is intended to
-        work around the Django admin and the regular ``django.contrib.auth``
-        login-powered pages.
-        
-        
-        Installation
-        ============
-        
-        You can install the latest stable package running this command::
-        
-            $ pip install django-axes
-        
-        Also you can install the development version running this command::
-        
-            $ pip install -e git+http://github.com/django-pci/django-axes.git#egg=django_axes-dev
-        
-        Development
-        ===========
-        
-        You can contribute to this project forking it from github and sending pull requests.
-        
-        Running tests
-        -------------
-        
-        Tests can be run, after you clone the repository and having django installed, like::
-        
-            $ PYTHONPATH=$PYTHONPATH:$PWD django-admin.py test axes --settings=axes.test_settings
-        
-        
-        Configuration
-        =============
-        
-        First of all, you must add this project to your list of ``INSTALLED_APPS`` in
-        ``settings.py``::
-        
-            INSTALLED_APPS = (
-                'django.contrib.admin',
-                'django.contrib.auth',
-                'django.contrib.contenttypes',
-                'django.contrib.sessions',
-                'django.contrib.sites',
-                ...
-                'axes',
-                ...
-            )
-        
-        Next, install the ``FailedLoginMiddleware`` middleware::
-        
-            MIDDLEWARE_CLASSES = (
-                'django.middleware.common.CommonMiddleware',
-                'django.contrib.sessions.middleware.SessionMiddleware',
-                'django.contrib.auth.middleware.AuthenticationMiddleware',
-                'axes.middleware.FailedLoginMiddleware'
-            )
-        
-        Run ``python manage.py syncdb``.  This creates the appropriate tables in your database
-        that are necessary for operation.
-        
-        Customizing Axes
-        ----------------
-        
-        You have a couple options available to you to customize ``django-axes`` a bit.
-        These should be defined in your ``settings.py`` file.
-        
-        * ``AXES_LOGIN_FAILURE_LIMIT``: The number of login attempts allowed before a
-          record is created for the failed logins.  Default: ``3``
-        * ``AXES_LOCK_OUT_AT_FAILURE``: After the number of allowed login attempts
-          are exceeded, should we lock out this IP (and optional user agent)?
-          Default: ``True``
-        * ``AXES_USE_USER_AGENT``: If ``True``, lock out / log based on an IP address
-          AND a user agent.  This means requests from different user agents but from
-          the same IP are treated differently.  Default: ``False``
-        * ``AXES_COOLOFF_TIME``: If set, defines a period of inactivity after which
-          old failed login attempts will be forgotten. Can be set to a python
-          timedelta object or an integer. If an integer, will be interpreted as a
-          number of hours.  Default: ``None``
-        * ``AXES_LOGGER``: If set, specifies a logging mechanism for axes to use.
-          Default: ``'axes.watch_login'``
-        * ``AXES_LOCKOUT_TEMPLATE``: If set, specifies a template to render when a
-          user is locked out. Template receives cooloff_time and failure_limit as
-          context variables. Default: ``None``
-        * ``AXES_LOCKOUT_URL``: If set, specifies a URL to redirect to on lockout. If
-          both AXES_LOCKOUT_TEMPLATE and AXES_LOCKOUT_URL are set, the template will
-          be used. Default: ``None``
-        * ``AXES_VERBOSE``: If ``True``, you'll see slightly more logging for Axes.
-          Default: ``True``
-        * ``AXES_USERNAME_FORM_FIELD``: the name of the form field that contains your
-          users usernames. Default: ``username``
-        
-        * ``AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP``: If ``True`` prevents to login
-          from IP under particular user if attempts limit exceed, otherwise lock out
-          based on IP.
-          Default: ``False``
-        
-        
-        Usage
-        =====
-        
-        Using ``django-axes`` is extremely simple.  Once you install the application
-        and the middleware, all you need to do is periodically check the Access
-        Attempts section of the admin.
-        
-        By default, django-axes will lock out repeated attempts from the same IP
-        address.  You can allow this IP to attempt again by deleting the relevant
-        ``AccessAttempt`` records in the admin.
-        
-        You can also use the ``axes_reset`` management command using Django's
-        ``manage.py``.
-        
-        * ``manage.py axes_reset`` will reset all lockouts and access records.
-        * ``manage.py axes_reset ip`` will clear lockout/records for ip
-        
-        In your code, you can use ``from axes.utils import reset``.
-        
-        * ``reset()`` will reset all lockouts and access records.
-        * ``reset(ip=ip)`` will clear lockout/records for ip
-        * ``reset(username=username)`` will clear lockout/records for username
-        
-        Issues
-        ======
-        
-        Not being locked out after failed attempts
-        ------------------------------------------
-        
-        You may find that Axes is not capturing your failed login attempts. It may be that you need to manually add watch_login to your login url.
-        For example, in your urls.py::
-        
-            ...
-            from django.contrib.auth.views import login, logout, password_change
-            from axes.decorators import watch_login
-            ...
-            urlpatterns = patterns('',
-                (r'^login/$', watch_login(login), {'template_name': 'auth/login.html'}),
-            ...
-        
-        
-        Locked out without reason
-        -------------------------
-        
-        It may happen that you have suddenly become locked out without a single failed
-        attempt. One possible reason is that you are using some custom login form and the
-        username field is named something different than "username", e.g. "email". This
-        leads to all users attempts being lumped together. To fix this add the following
-        to your settings:
-        
-            AXES_USERNAME_FORM_FIELD = "email"
-        
-        
-        Using a captcha
-        ===============
-        
-        Using https://github.com/mbi/django-simple-captcha you do the following:
-        
-        1. Change axes lockout url in ``settings.py``::
-        
-            AXES_LOCKOUT_URL = '/locked'
-        
-        2. Add the url in ``urls.py``::
-        
-            url(r'^locked/$', locked_out, name='locked_out'),
-        
-        3. Create a captcha form::
-        
-            class AxesCaptchaForm(forms.Form):
-                captcha = CaptchaField()
-        
-        4. Create a captcha view for the above url that resets on captcha success and redirects::
-        
-            def locked_out(request):
-                if request.POST:
-                    form = AxesCaptchaForm(request.POST)
-                    if form.is_valid():
-                        ip = get_ip_address_from_request(request)
-                        reset(ip=ip)
-                        return HttpResponseRedirect(reverse_lazy('signin'))
-                else:
-                    form = AxesCaptchaForm()
-            
-                return render_to_response('locked_out.html', dict(form=form), context_instance=RequestContext(request))
-        
-        5. Add a captcha template::
-        
-            <form action="" method="post">
-                {% csrf_token %}
-            
-                {{ form.captcha.errors }}
-                {{ form.captcha }}
-            
-                <div class="form-actions">
-                    <input type="submit" value="Submit" />
-                </div>
-            </form>
-        
-        Done.
-        
-        Changes
-        =======
-        
-        1.6.0 (2016-01-07)
-        ------------------
-        
-        - Stopped using render_to_response so that other template engines work
-          [tarkatronic]
-        
-        - Improved performance & DoS prevention on query2str
-          [tarkatronic]
-        
-        - Immediately return from is_already_locked if the user is not lockable
-          [jdunck]
-        
-        - Iterate over ip addresses only once
-          [annp89]
-        
-        - added initial migration files to support django 1.7 &up
-          [ibaguio]
-        
-        - Add db indexes to CommonAccess model
-          [Schweigi]
-        
-        1.5.0 (2015-09-11)
-        ------------------
-        
-        - Fix #_get_user_attempts to include username when filtering AccessAttempts if AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP is True
-          [afioca]
-        
-        1.4.0 (2015-08-09)
-        ------------------
-        
-        - Send the user_locked_out signal. Fixes #94.
-          [toabi]
-        
-        1.3.9 (2015-02-11)
-        ------------------
-        
-        - Python 3 fix (#104)
-        
-        1.3.8 (2014-10-07)
-        ------------------
-        
-        - Rename GitHub organization from django-security to django-pci to emphasize focus on providing assistance with building PCI compliant websites with Django.
-          [aclark4life]
-        
-        1.3.7 (2014-10-05)
-        ------------------
-        
-        - Explain common issues where Axes fails silently
-          [cericoda]
-        
-        - Allow for user-defined username field for lookup in POST data
-          [SteveByerly]
-        
-        - Log out only if user was logged in
-          [zoten]
-        
-        - Support for floats in cooloff time (i.e: 0.1 == 6 minutes)
-          [marianov]
-        
-        - Limit amount of POST data logged (#73). Limiting the length of value is not enough, as there could be arbitrary number of them, or very long key names.
-          [peterkuma]
-        
-        - Improve get_ip to try for real ip address
-          [7wonders]
-        
-        - Change IPAddressField to GenericIPAddressField. When using a PostgreSQL database and the client does not pass an IP address you get an inet error. This is a known problem with PostgreSQL and the IPAddressField. https://code.djangoproject.com/ticket/5622. It can be fixed by using a GenericIPAddressField instead.
-          [polvoblanco]
-        
-        - Get first X-Forwarded-For IP
-          [tutumcloud]
-        
-        - White listing IP addresses behind reverse proxy. Allowing some IP addresses to have direct access to the app even if they are behind a reverse proxy. Those IP addresses must still be on a white list.
-          [ericbulloch]
-        
-        - Reduce logging of reverse proxy IP lookup and use configured logger. Fixes #76. Instead of logging the notice that django.axes looks for a HTTP header set by a reverse proxy on each attempt, just log it one-time on first module import. Also use the configured logger (by default axes.watch_login) for the message to be more consistent in logging.
-          [eht16]
-        
-        - Limit the length of the values logged into the database. Refs #73
-          [camilonova]
-        
-        - Refactored tests to be more stable and faster
-          [camilonova]
-        
-        - Clean client references
-          [camilonova]
-        
-        - Fixed admin login url
-          [camilonova]
-        
-        - Added django 1.7 for testing
-          [camilonova]
-        
-        - Travis file cleanup
-          [camilonova]
-        
-        - Remove hardcoded url path
-          [camilonova]
-        
-        - Fixing tests for django 1.7
-          [Andrew-Crosio]
-        
-        - Fix for django 1.7 exception not existing
-          [Andrew-Crosio]
-        
-        - Removed python 2.6 from testing
-          [camilonova]
-        
-        - Use django built-in six version
-          [camilonova]
-        
-        - Added six as requirement
-          [camilonova]
-        
-        - Added python 2.6 for travis testing
-          [camilonova]
-        
-        - Replaced u string literal prefixes with six.u() calls
-          [amrhassan]
-        
-        - Fixes object type issue, response is not an string
-          [camilonova]
-            
-        - Python 3 compatibility fix for db_reset
-          [nicois]
-        
-        - Added example project and helper scripts
-          [barseghyanartur]
-        
-        - Admin command to list login attemps
-          [marianov]
-        
-        - Replaced six imports with django.utils.six ones
-          [amrhassan]
-        
-        - Replaced u string literal prefixes with six.u() calls to make it compatible with Python 3.2
-          [amrhassan]
-        
-        - Replaced `assertIn`s and `assertNotIn`s with `assertContains` and `assertNotContains`
-          [fcurella]
-        
-        - Added py3k to travis
-          [fcurella]
-        
-        - Update test cases to be python3 compatible
-          [nicois]
-        
-        - Python 3 compatibility fix for db_reset
-          [nicois]
-        
-        - Removed trash from example urls
-          [barseghyanartur]
-        
-        - Added django installer
-          [barseghyanartur]
-        
-        - Added example project and helper scripts
-          [barseghyanartur]
-        
-        
-        1.3.6 (2013-11-23)
-        ------------------
-        
-        - Added AttributeError in case get_profile doesn't exist [camilonova]
-        - Improved axes_reset command [camilonova]
-        
-        
-        1.3.5 (2013-11-01)
-        ------------------
-        
-        - Fix an issue with __version__ loading the wrong version [graingert]
-        
-        
-        1.3.4 (2013-11-01)
-        ------------------
-        
-        - Update README.rst for PyPI [marty] [camilonova] [graingert]
-        - Add cooloff period [visualspace]
-        
-        
-        1.3.3 (2013-07-05)
-        ------------------
-        
-        - Added 'username' field to the Admin table [bkvirendra]
-        - Removed fallback logging creation since logging cames by default on django 1.4 or later, if you don't have it is because you explicitly wanted. Fixes #45 [camilonova]
-        
-        
-        1.3.2 (2013-03-28)
-        ------------------
-        
-        - Fix an issue when a user logout [camilonova]
-        - Match pypi version [camilonova]
-        - Better User model import method [camilonova]
-        - Use only one place to get the version number [camilonova]
-        - Fixed an issue when a user on django 1.4 logout [camilonova]
-        - Handle exception if there is not user profile model set [camilonova]
-        - Made some cleanup and remove a pokemon exception handling [camilonova]
-        - Improved tests so it really looks for the rabbit in the hole [camilonova]
-        - Match pypi version [camilonova]
-        
-        
-        1.3.1 (2013-03-19)
-        ------------------
-        
-        - Add support for Django 1.5 [camilonova]
-        
-        
-        1.3.0 (2013-02-27)
-        ------------------
-        
-        - Bug fix: get_version() format string [csghormley]
-        
-        
-        1.2.9 (2013-02-20)
-        ------------------
-        
-        - Add to and improve test cases [camilonova]
-        
-        
-        1.2.8 (2013-01-23)
-        ------------------
-        
-        - Increased http accept header length [jslatts]
-        
-        
-        1.2.7 (2013-01-17)
-        ------------------
-        
-        - Reverse proxy support [rmagee]
-        - Clean up README [martey]
-        
-        
-        1.2.6 (2012-12-04)
-        ------------------
-        
-        - Remove unused import [aclark4life]
-        
-        
-        1.2.5 (2012-11-28)
-        ------------------
-        
-        - Fix setup.py [aclark4life]
-        - Added ability to flag user accounts as unlockable. [kencochrane]
-        - Added ipaddress as a param to the user_locked_out signal. [kencochrane]
-        - Added a signal receiver for user_logged_out. [kencochrane]
-        - Added a signal for when a user gets locked out. [kencochrane]
-        - Added AccessLog model to log all access attempts. [kencochrane]
-        
-Keywords: authentication,django,pci,security
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Web Environment
-Classifier: Framework :: Django
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Internet :: Log Analysis
-Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware
-Classifier: Topic :: Security
-Classifier: Topic :: System :: Logging

+ 0 - 51
desktop/core/ext-py/django-axes-1.6.0/axes/migrations/0001_initial.py

@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='AccessAttempt',
-            fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('user_agent', models.CharField(max_length=255)),
-                ('ip_address', models.GenericIPAddressField(null=True, verbose_name=b'IP Address')),
-                ('username', models.CharField(max_length=255, null=True)),
-                ('trusted', models.BooleanField(default=False)),
-                ('http_accept', models.CharField(max_length=1025, verbose_name=b'HTTP Accept')),
-                ('path_info', models.CharField(max_length=255, verbose_name=b'Path')),
-                ('attempt_time', models.DateTimeField(auto_now_add=True)),
-                ('get_data', models.TextField(verbose_name=b'GET Data')),
-                ('post_data', models.TextField(verbose_name=b'POST Data')),
-                ('failures_since_start', models.PositiveIntegerField(verbose_name=b'Failed Logins')),
-            ],
-            options={
-                'ordering': ['-attempt_time'],
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='AccessLog',
-            fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('user_agent', models.CharField(max_length=255)),
-                ('ip_address', models.GenericIPAddressField(null=True, verbose_name=b'IP Address')),
-                ('username', models.CharField(max_length=255, null=True)),
-                ('trusted', models.BooleanField(default=False)),
-                ('http_accept', models.CharField(max_length=1025, verbose_name=b'HTTP Accept')),
-                ('path_info', models.CharField(max_length=255, verbose_name=b'Path')),
-                ('attempt_time', models.DateTimeField(auto_now_add=True)),
-                ('logout_time', models.DateTimeField(null=True, blank=True)),
-            ],
-            options={
-                'ordering': ['-attempt_time'],
-                'abstract': False,
-            },
-        ),
-    ]

+ 0 - 54
desktop/core/ext-py/django-axes-1.6.0/axes/migrations/0002_auto_20151217_2044.py

@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('axes', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='accessattempt',
-            name='ip_address',
-            field=models.GenericIPAddressField(db_index=True, null=True, verbose_name=b'IP Address'),
-        ),
-        migrations.AlterField(
-            model_name='accessattempt',
-            name='trusted',
-            field=models.BooleanField(db_index=True, default=False),
-        ),
-        migrations.AlterField(
-            model_name='accessattempt',
-            name='user_agent',
-            field=models.CharField(db_index=True, max_length=255),
-        ),
-        migrations.AlterField(
-            model_name='accessattempt',
-            name='username',
-            field=models.CharField(db_index=True, max_length=255, null=True),
-        ),
-        migrations.AlterField(
-            model_name='accesslog',
-            name='ip_address',
-            field=models.GenericIPAddressField(db_index=True, null=True, verbose_name=b'IP Address'),
-        ),
-        migrations.AlterField(
-            model_name='accesslog',
-            name='trusted',
-            field=models.BooleanField(db_index=True, default=False),
-        ),
-        migrations.AlterField(
-            model_name='accesslog',
-            name='user_agent',
-            field=models.CharField(db_index=True, max_length=255),
-        ),
-        migrations.AlterField(
-            model_name='accesslog',
-            name='username',
-            field=models.CharField(db_index=True, max_length=255, null=True),
-        ),
-    ]

+ 0 - 0
desktop/core/ext-py/django-axes-1.6.0/examples/example/foo/management/commands/__init__.py


+ 0 - 5
desktop/core/ext-py/django-axes-1.6.0/setup.cfg

@@ -1,5 +0,0 @@
-[egg_info]
-tag_build = 
-tag_date = 0
-tag_svn_revision = 0
-