浏览代码

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 9 年之前
父节点
当前提交
6f31373
共有 44 个文件被更改,包括 39 次插入715 次删除
  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
-