Skip to content

Commit

Permalink
Merge branch 'next_release'
Browse files Browse the repository at this point in the history
  • Loading branch information
sztamas committed Aug 30, 2020
2 parents 8c6cf07 + 8bfb66e commit 44b7be4
Show file tree
Hide file tree
Showing 59 changed files with 2,159 additions and 886 deletions.
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
sudo: false
language: python
python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"
env:
global:
- RUNTEST_ARGS="-v --noinput"
install:
- pip install tox-travis
script: tox
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Changelog
=========

### 1.9.0 Aug 30, 2020
- Switched to Poetry (https://python-poetry.org/) + more cleanup
- Switched to pytest and pytest-django
- Drop support for pre-Django 1.10 style MIDDLEWARES
- Switch to old style url to path in urls.py
- Added Black and re-formatted and linted all the code
- Added isort and sorted all imports
- Bugfix: Add rule in admin was throwing an exception
- Handling "unknown" values in X-Forwarded-For header; introduces IPRESTRICT_USE_PROXY_IF_UNKNOWN header
- More cleanup

### 1.8.1 Aug 24, 2020
- General clean-up after forking the project from muccg/django-iprestrict
- Added support for Django 3+
- Dropped support for old releases of Django/Python

4 changes: 0 additions & 4 deletions MANIFEST.in

This file was deleted.

8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
django-iprestrict-redux
=======================
[![Build Status](https://travis-ci.org/sztamas/django-iprestrict-redux.png?branch=master)](https://travis-ci.org/sztamas/django-iprestrict-redux)

[![Build Status](https://travis-ci.org/sztamas/django-iprestrict-redux.png?branch=master)](https://travis-ci.org/sztamas/django-iprestrict-redux)
[![PyPI](https://badge.fury.io/py/django-iprestrict-redux.svg)](https://pypi.python.org/pypi/django-iprestrict-redux)
[![Documentation Status](https://readthedocs.org/projects/django-iprestrict-redux/badge/?version=latest)](http://django-iprestrict-redux.readthedocs.org/en/latest/?badge=latest)
[![Documentation Status](https://readthedocs.org/projects/django-iprestrict/badge/?version=latest)](http://django-iprestrict.readthedocs.org/en/latest/?badge=latest)
![GitHub](https://img.shields.io/github/license/sztamas/django-iprestrict-redux)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)

___

Expand Down
1 change: 0 additions & 1 deletion common-requirements.txt

This file was deleted.

11 changes: 0 additions & 11 deletions debian/changelog

This file was deleted.

1 change: 0 additions & 1 deletion debian/compat

This file was deleted.

18 changes: 0 additions & 18 deletions debian/control

This file was deleted.

41 changes: 0 additions & 41 deletions debian/copyright

This file was deleted.

6 changes: 0 additions & 6 deletions debian/docs

This file was deleted.

13 changes: 0 additions & 13 deletions debian/rules

This file was deleted.

1 change: 0 additions & 1 deletion debian/source/format

This file was deleted.

8 changes: 4 additions & 4 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ Enable Django Admin for at least the iprestrict application.

Add the urls of iprestrict to your project. Ex in your root urls.py::

from django.conf.urls import url, include
from django.urls import include, path

urlpatterns = [
# ... snip ...
url(r'^iprestrict/', include('iprestrict.urls', namespace='iprestrict')),
path('iprestrict/', include('iprestrict.urls', namespace='iprestrict')),

This configuration will allow you to configure and test your restriction rules.

Expand Down Expand Up @@ -140,9 +140,9 @@ Go to *YOUR_URL/iprestrict/* page. You can use the page to enter any *URL* and *
Enabling the middleware
-----------------------

Add ``iprestrict.middleware.IPRestrictMiddleware`` to your ``MIDDLEWARE`` in your settings file (or ``MIDDLEWARE_CLASSES`` for old versions of Django). Generally, you will want this middleware to run early, before your session, auth etc. middlewares (the ``superuser_required`` decorator may also not function correctly if placed out of order)::
Add ``iprestrict.middleware.IPRestrictMiddleware`` to your ``MIDDLEWARE`` in your settings file. Generally, you will want this middleware to run early, before your session, auth etc. middlewares (the ``superuser_required`` decorator may also not function correctly if placed out of order)::

MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'iprestrict.middleware.IPRestrictMiddleware',
...
Expand Down
13 changes: 9 additions & 4 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,20 @@ The country based lookups are optional, if you need it you can install them with
Development
^^^^^^^^^^^

For development create a ``virtualenv``, activate it and then::
For development you will need Poetry_.

pip install -e .[geoip,dev]
.. _Poetry https://python-poetry.org
Fork the project and then:

poetry install

To run the tests against the *python* and *Django* in your virtualenv::

./runtests.sh
pytest

To run the tests against all combinations of *python 2*, *python 3*, and supported *Django* versions::
To run the tests against all combinations of supported *Python 3*, and *Django* versions::

tox

Expand Down
Empty file removed iprestrict/.vimp
Empty file.
74 changes: 48 additions & 26 deletions iprestrict/admin.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from django import forms
import re

from django import forms
from django.contrib import admin

from . import ip_utils as ipu
from . import models
from .geoip import is_valid_country_code


NOT_LETTER = re.compile(r'[^A-Z]+')
NOT_LETTER = re.compile(r"[^A-Z]+")


@admin.register(models.Rule)
class RuleAdmin(admin.ModelAdmin):
exclude = ('rank',)
list_display = ('url_pattern', 'ip_group', 'reverse_ip_group', 'is_allowed', 'move_up_url', 'move_down_url')
exclude = ("rank",)
list_display = (
"url_pattern",
"ip_group",
"reverse_ip_group",
"is_allowed",
"move_up_url",
"move_down_url",
)


class IPRangeForm(forms.ModelForm):
Expand All @@ -25,27 +33,34 @@ class Meta:

def clean(self):
cleaned_data = super(IPRangeForm, self).clean()
first_ip = cleaned_data.get('first_ip')
first_ip = cleaned_data.get("first_ip")
if first_ip is None:
# first_ip is Mandatory, so just let the default validator catch this
return cleaned_data
version = ipu.get_version(first_ip)
last_ip = cleaned_data['last_ip']
cidr = cleaned_data.get('cidr_prefix_length')
last_ip = cleaned_data["last_ip"]
cidr = cleaned_data.get("cidr_prefix_length")
if cidr is not None:
if version == ipu.IPv4 and not (1 <= cidr <= 31):
self.add_error('cidr_prefix_length', 'Must be a number between 1 and 31')
self.add_error(
"cidr_prefix_length", "Must be a number between 1 and 31"
)
return cleaned_data
if version == ipu.IPv6 and not (1 <= cidr <= 127):
self.add_error('cidr_prefix_length', 'Must be a number between 1 and 127')
self.add_error(
"cidr_prefix_length", "Must be a number between 1 and 127"
)
return cleaned_data

if last_ip and cidr:
raise forms.ValidationError("Don't specify the Last IP if you specified a CIDR prefix length")
raise forms.ValidationError(
"Don't specify the Last IP if you specified a CIDR prefix length"
)
if last_ip:
if version != ipu.get_version(last_ip):
raise forms.ValidationError(
"Last IP should be the same type as First IP (%s)" % version)
"Last IP should be the same type as First IP (%s)" % version
)
if ipu.to_number(first_ip) > ipu.to_number(last_ip):
raise forms.ValidationError("Last IP should be greater than First IP")

Expand All @@ -54,7 +69,7 @@ def clean(self):
# the user specified. Making sure it is set to the first ip in the
# subnet.
start, end = ipu.cidr_to_range(first_ip, cidr)
cleaned_data['first_ip'] = ipu.to_ip(start, version=version)
cleaned_data["first_ip"] = ipu.to_ip(start, version=version)

return cleaned_data

Expand All @@ -63,8 +78,8 @@ class IPRangeInline(admin.TabularInline):
model = models.IPRange
form = IPRangeForm

fields = ['first_ip', 'cidr_prefix_length', 'last_ip', 'ip_type', 'description']
readonly_fields = ['ip_type']
fields = ["first_ip", "cidr_prefix_length", "last_ip", "ip_type", "description"]
readonly_fields = ["ip_type"]
extra = 2


Expand All @@ -74,36 +89,43 @@ class Meta:
exclude = ()

def clean_country_codes(self):
codes = self.cleaned_data['country_codes']
codes = set(filter(lambda x: x != '',
NOT_LETTER.split(self.cleaned_data['country_codes'].upper())))
codes = self.cleaned_data["country_codes"]
codes = set(
filter(
lambda x: x != "",
NOT_LETTER.split(self.cleaned_data["country_codes"].upper()),
)
)

if not all(map(is_valid_country_code, codes)):
incorrect = [c for c in codes if not is_valid_country_code(c)]
msg = ('""%s" must be a valid country code' if len(incorrect) == 1 else
'""%s" must be valid country codes')
raise forms.ValidationError(msg % ', '.join(incorrect))
msg = (
'""%s" must be a valid country code'
if len(incorrect) == 1
else '""%s" must be valid country codes'
)
raise forms.ValidationError(msg % ", ".join(incorrect))

codes = list(codes)
codes.sort()
return ', '.join(codes)
return ", ".join(codes)


class IPLocationInline(admin.TabularInline):
model = models.IPLocation
form = IPLocationForm

fields = ['country_codes']
fields = ["country_codes"]
extra = 2


@admin.register(models.RangeBasedIPGroup)
class RangeBasedIPGroupAdmin(admin.ModelAdmin):
exclude = ('type',)
exclude = ("type",)
inlines = [IPRangeInline]


@admin.register(models.LocationBasedIPGroup)
class LocationBasedIPGroupAdmin(admin.ModelAdmin):
exclude = ('type',)
exclude = ("type",)
inlines = [IPLocationInline]
7 changes: 4 additions & 3 deletions iprestrict/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@


# Based on django django.contrib.admin.views.decorators.staff_member_required.
def superuser_required(view_func=None, redirect_field_name=REDIRECT_FIELD_NAME,
login_url='admin:login'):
def superuser_required(
view_func=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url="admin:login"
):
"""
Decorator for views that checks that the user is logged in and is a superuser
member, redirecting to the login page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_superuser,
login_url=login_url,
redirect_field_name=redirect_field_name
redirect_field_name=redirect_field_name,
)
if view_func:
return actual_decorator(view_func)
Expand Down
Loading

0 comments on commit 44b7be4

Please sign in to comment.