Skip to content

Commit

Permalink
Merge 2241626 into a1a5884
Browse files Browse the repository at this point in the history
  • Loading branch information
MrLokans committed Feb 7, 2018
2 parents a1a5884 + 2241626 commit e7404ed
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 90 deletions.
48 changes: 39 additions & 9 deletions .travis.yml
@@ -1,16 +1,46 @@
language: python

env:
- TOXENV=django18_py27
- TOXENV=django18_py33
- TOXENV=django18_py34
- TOXENV=django18_py35
matrix:
include:
- env: TOXENV=django18-py27
python: '2.7'
- env: TOXENV=django18-py34
python: '3.3'
- env: TOXENV=django18-py34
python: '3.4'
- env: TOXENV=django18-py35
python: '3.5'

- TOXENV=django19_py27
- TOXENV=django19_py34
- TOXENV=django19_py35
- env: TOXENV=django19-py27
python: '2.7'
- env: TOXENV=django19-py34
python: '3.4'
- env: TOXENV=django19-py35
python: '3.5'

- TOXENV=coverage
- env: TOXENV=django110-py27
python: '2.7'
- env: TOXENV=django110-py34
python: '3.4'
- env: TOXENV=django110-py35
python: '3.5'

- env: TOXENV=django111-py27
python: '2.7'
- env: TOXENV=django111-py34
python: '3.4'
- env: TOXENV=django111-py35
python: '3.5'
- env: TOXENV=django111-py35
python: '3.6'

- env: TOXENV=django20-py34
python: '3.4'
- env: TOXENV=django20-py35
python: '3.5'
- env: TOXENV=django20-py36
python: '3.6'
- env: TOXENV=coverage

install:
- pip install tox
Expand Down
9 changes: 8 additions & 1 deletion README.rst
Expand Up @@ -39,11 +39,18 @@ tl;dr
* Update your urls.py:

::

# If django version is lower than 2.0
urlpatterns = patterns(''
...
url(r'^admin/', include('admin_honeypot.urls', namespace='admin_honeypot')),
url(r'^secret/', include(admin.site.urls)),
)

# Otherwise
from django.urls import path
urlpatterns = [
path('admin/', include('admin_honeypot.urls', namespace='admin_honeypot')),
path('secret/', admin.site.urls),
]

* Run ``python manage.py migrate``
15 changes: 15 additions & 0 deletions admin_honeypot/compat.py
@@ -0,0 +1,15 @@
"""
Compatibility layer for various django and python versions imports
"""

try:
from django.urls import reverse
except ImportError: # For Django version less than 2.0
from django.core.urlresolvers import reverse # noqa

try:
# Python 2.7
from urllib import quote_plus
except ImportError:
# Python 3+
from urllib.parse import quote_plus # noqa
4 changes: 3 additions & 1 deletion admin_honeypot/listeners.py
@@ -1,7 +1,8 @@
from admin_honeypot.compat import reverse
from admin_honeypot.signals import honeypot

from django.conf import settings
from django.core.mail import mail_admins
from django.core.urlresolvers import reverse
from django.template.loader import render_to_string


Expand All @@ -17,5 +18,6 @@ def notify_admins(instance, request, **kwargs):
message = render_to_string('admin_honeypot/email_message.txt', context).strip()
mail_admins(subject=subject, message=message)


if getattr(settings, 'ADMIN_HONEYPOT_EMAIL_ADMINS', True):
honeypot.connect(notify_admins)
2 changes: 1 addition & 1 deletion admin_honeypot/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from admin_honeypot import listeners
from admin_honeypot import listeners # noqa


class LoginAttempt(models.Model):
Expand Down
2 changes: 2 additions & 0 deletions admin_honeypot/urls.py
@@ -1,6 +1,8 @@
from admin_honeypot import views
from django.conf.urls import url

app_name = 'admin_honeypot'

urlpatterns = [
url(r'^login/$', views.AdminHoneypot.as_view(), name='login'),
url(r'^.*$', views.AdminHoneypot.as_view(), name='index'),
Expand Down
2 changes: 1 addition & 1 deletion admin_honeypot/views.py
@@ -1,10 +1,10 @@
import django
from admin_honeypot.compat import reverse
from admin_honeypot.forms import HoneypotLoginForm
from admin_honeypot.models import LoginAttempt
from admin_honeypot.signals import honeypot
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.views import redirect_to_login
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
from django.views import generic
Expand Down
9 changes: 7 additions & 2 deletions setup.py
Expand Up @@ -15,6 +15,10 @@
classifiers=[
'Development Status :: 5 - Production/Stable',
'Framework :: Django',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
Expand All @@ -26,8 +30,9 @@
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
],
keywords='django admin honeypot trap',
maintainer='Derek Payton',
maintainer_email='derek.payton@gmail.com',
Expand All @@ -37,4 +42,4 @@
include_package_data=True,
packages=find_packages(),
zip_safe=False,
)
)
8 changes: 7 additions & 1 deletion tests/settings.py
Expand Up @@ -38,12 +38,18 @@
'admin_honeypot',
)

MIDDLEWARE_CLASSES = (
MIDDLEWARE = MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)

TEMPLATES = [
{
'APP_DIRS': True,
'BACKEND': 'django.template.backends.django.DjangoTemplates',
},
]

ADMIN_HONEYPOT_EMAIL_ADMINS = True
25 changes: 13 additions & 12 deletions tests/test_suite.py
@@ -1,17 +1,13 @@
import django
import pytest
import re
from admin_honeypot.compat import reverse, quote_plus
from admin_honeypot.models import LoginAttempt
from django.conf import settings
from django.core import mail
from django.core.urlresolvers import reverse
from django.test import TestCase

try:
# Python 2.7
from urllib import quote_plus
except ImportError:
# Python 3+
from urllib.parse import quote_plus

CSRF_TOKEN_REGEX = re.compile(r"(name='csrfmiddlewaretoken' value='\w+')")


class AdminHoneypotTest(TestCase):
maxDiff = None
Expand All @@ -35,12 +31,13 @@ def honeypot_url(self):
def test_same_content(self):
"""
The honeypot should be an exact replica of the admin login page,
with the exception of where the form submits to and the CSS to
hide the user tools.
with the exception of where the form submits to, the CSS to
hide the user tools and the CSRF token
"""

admin_html = self.client.get(self.admin_url, follow=True).content.decode('utf-8')
honeypot_html = (self.client.get(self.honeypot_url, follow=True).content.decode('utf-8')
honeypot_html = (
self.client.get(self.honeypot_url, follow=True).content.decode('utf-8')
# /admin/login/ -> /secret/login/
.replace(self.honeypot_login_url, self.admin_login_url)

Expand All @@ -51,6 +48,10 @@ def test_same_content(self):
.replace(quote_plus(self.honeypot_url), quote_plus(self.admin_url))
)

# Remove CSRF token
admin_html = CSRF_TOKEN_REGEX.sub('', admin_html)
honeypot_html = CSRF_TOKEN_REGEX.sub('', honeypot_html)

self.assertEqual(honeypot_html, admin_html)

def test_create_login_attempt(self):
Expand Down
21 changes: 13 additions & 8 deletions tests/urls.py
@@ -1,13 +1,18 @@
try:
from django.conf.urls import patterns, include, url
except ImportError: # django < 1.4
from django.conf.urls.defaults import patterns, include, url
import django
from django.conf.urls import include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
url(r'^admin/', include('admin_honeypot.urls', namespace='admin_honeypot')),
url(r'^secret/', include(admin.site.urls)),
)
if django.VERSION < (2, 0):
urlpatterns = [
url(r'^admin/', include('admin_honeypot.urls', namespace='admin_honeypot')),
url(r'^secret/', include(admin.site.urls)),
]
else:
from django.urls import path
urlpatterns = [
path('admin/', include('admin_honeypot.urls', namespace='admin_honeypot')),
path('secret/', admin.site.urls),
]
72 changes: 18 additions & 54 deletions tox.ini
Expand Up @@ -5,73 +5,37 @@

[tox]
envlist =
django18_py27, django18_py33, django18_py34, django18_py35
django19_py27, django19_py34, django19_py35
django18-py{27,33,34,35}
django19-py{27,34,35}
django110-py{27,34,35}
django111-py{27,34,35,36}
django20-py{34,35,36}

[testenv]
commands = py.test tests/
[testenvbase]
deps =
pytest
pytest-django
pytest-pythonpath

[testenv]
commands = py.test tests/
deps =
django18: Django>=1.8,<1.9
django19: Django>=1.9,<1.10
django110: Django>=1.10,<1.11
django111: Django>=1.11,<2
django20: Django==2.0.2
{[testenvbase]deps}

[testenv:coverage]
basepython = python2.7
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
commands =
py.test tests/ --cov admin_honeypot --cov-config .coveragerc --cov-report term-missing --pep8 admin_honeypot
coveralls
deps =
Django>=1.9,<1.10
Django>=1.9,<=2.0
coveralls
pytest-cov
pytest-pep8
{[testenv]deps}

[testenv:django18_py27]
basepython = python2.7
deps =
Django>=1.8,<1.9
{[testenv]deps}

[testenv:django18_py33]
basepython = python3.3
deps =
Django>=1.8,<1.9
{[testenv]deps}

[testenv:django18_py34]
basepython = python3.4
deps =
Django>=1.8,<1.9
{[testenv]deps}

[testenv:django18_py35]
basepython = python3.5
deps =
Django>=1.8,<1.9
{[testenv]deps}

[testenv:django19_py27]
basepython = python2.7
deps =
Django>=1.9,<1.10
{[testenv]deps}

[testenv:django19_py33]
basepython = python3.3
deps =
Django>=1.9,<1.10
{[testenv]deps}

[testenv:django19_py34]
basepython = python3.4
deps =
Django>=1.9,<1.10
{[testenv]deps}

[testenv:django19_py35]
basepython = python3.5
deps =
Django>=1.9,<1.10
{[testenv]deps}
{[testenvbase]deps}

0 comments on commit e7404ed

Please sign in to comment.