Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support django22, py38 #27

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Test

on:
push:
branches:
- master
pull_request:

jobs:
build:
runs-on: ubuntu-latest
name: Python ${{ matrix.python-version }}, Django${{ matrix.django-version }}

strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
django-version: [">=1.11,<2", ">=2.0,<2.1", ">=2.1,<2.2", ">=2.2,<2.3"]

steps:
- uses: actions/checkout@v2
- name: Install Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip --disable-pip-version-check install -r dev-requirements.txt
pip install "Django${{ matrix.django-version }}"
- name: Run lint
run: |
flake8 sudo/
- name: Run tests
run: |
pytest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
venv/

*.py[cod]

# C extensions
Expand Down
54 changes: 0 additions & 54 deletions .travis.yml

This file was deleted.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ $ pip install django-sudo

## Compatibility

* Django 1.9-1.11
* Python 2.7, 3.6-3.7
* Django 1.11 - 2.2
* Python 3.6 - 3.8

## Resources

Expand Down
4 changes: 2 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"sudo",
]

MIDDLEWARE_CLASSES = [
MIDDLEWARE = [
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
]
Expand Down Expand Up @@ -35,7 +35,7 @@ def pytest_configure(config):
DATABASE_NAME=":memory:",
TEST_DATABASE_NAME=":memory:",
INSTALLED_APPS=INSTALLED_APPS,
MIDDLEWARE_CLASSES=MIDDLEWARE_CLASSES,
MIDDLEWARE=MIDDLEWARE,
PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"],
ROOT_URLCONF="tests.urls",
)
19 changes: 9 additions & 10 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
-e .
flake8>=3.7.0,<3.8.0
invoke==1.4.0
pytest==4.6.5
pytest-cov==2.5.1
pytest-django==3.5.1
sphinx
sphinx_rtd_theme
tox
twine
wheel
flake8==3.8.4
pytest==6.1.0
pytest-django==3.10.0

# HACK: pytest-django just assumes six is installed without requiring it.
six==1.15.0

#sphinx
#sphinx_rtd_theme
5 changes: 5 additions & 0 deletions docs/changelog/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

4.0.0 (unreleased)
~~~~~~~~~~~~~~~~~~
* Added support for Django 2.0 - 2.2, Python 3.7 - 3.8
* Dropped support for Django < 1.11

3.1.0
~~~~~
* Added support for Django 1.11
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ will automatically register the ``user_logged_in`` and ``user_logged_out`` signa
'sudo',
)

Now we need to install the required middleware into ``MIDDLEWARE_CLASSES``:
Now we need to install the required middleware into ``MIDDLEWARE``:

.. code-block:: python

MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
# ...
'sudo.middleware.SudoMiddleware',
)
Expand Down
5 changes: 2 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ Installation

Compatibility
~~~~~~~~~~~~~
* Django 1.4-1.9
* Python 2.6-3.5
* pypy
* Django 1.11-2.2
* Python 3.6-3.8

Contents
~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ the :class:`~sudo.middleware.SudoMiddleware`. This is an shortcut for calling

.. class:: sudo.middleware.SudoMiddleware

By default, you just need to add this into your ``MIDDLEWARE_CLASSES`` list.
By default, you just need to add this into your ``MIDDLEWARE`` list.

.. method:: has_sudo_privileges(self, request)

Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python",
"Topic :: Software Development",
],
Expand Down
8 changes: 7 additions & 1 deletion sudo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ def __init__(self, user, *args, **kwargs):

def clean_password(self):
username = self.user.get_username()
if auth.authenticate(username=username, password=self.data["password"]):

if auth.authenticate(
request=None,
username=username,
password=self.data["password"],
):
return self.data["password"]

raise forms.ValidationError(_("Incorrect password"))
6 changes: 4 additions & 2 deletions sudo/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
)
from sudo.utils import has_sudo_privileges

from django.utils.deprecation import MiddlewareMixin

class SudoMiddleware(object):

class SudoMiddleware(MiddlewareMixin):
"""
Middleware that contributes ``request.is_sudo()`` and sets the required
cookie for sudo mode to work correctly.
Expand All @@ -29,7 +31,7 @@ def has_sudo_privileges(self, request):
def process_request(self, request):
assert hasattr(request, "session"), (
"The Sudo middleware requires session middleware to be installed."
"Edit your MIDDLEWARE_CLASSES setting to insert "
"Edit your MIDDLEWARE setting to insert "
"'django.contrib.sessions.middleware.SessionMiddleware' before "
"'sudo.middleware.SudoMiddleware'."
)
Expand Down
4 changes: 2 additions & 2 deletions sudo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def grant_sudo_privileges(request, max_age=COOKIE_AGE):
if user is None:
return

if not user.is_authenticated():
if not user.is_authenticated:
raise ValueError("User needs to be logged in to be elevated to sudo")

# Token doesn't need to be unique,
Expand Down Expand Up @@ -53,7 +53,7 @@ def has_sudo_privileges(request):
"""
if getattr(request, "_sudo", None) is None:
try:
request._sudo = request.user.is_authenticated() and constant_time_compare(
request._sudo = request.user.is_authenticated and constant_time_compare(
request.get_signed_cookie(
COOKIE_NAME, salt=COOKIE_SALT, max_age=COOKIE_AGE
),
Expand Down
4 changes: 2 additions & 2 deletions sudo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def grant_sudo_privileges(self, request, redirect_to):
# Restore the redirect destination from the GET request
redirect_to = request.session.pop(REDIRECT_TO_FIELD_NAME, redirect_to)
# Double check we're not redirecting to other sites
if not is_safe_url(url=redirect_to, host=request.get_host()):
if not is_safe_url(url=redirect_to, allowed_hosts={request.get_host()}):
redirect_to = resolve_url(REDIRECT_URL)
return HttpResponseRedirect(redirect_to)

Expand All @@ -60,7 +60,7 @@ def dispatch(self, request):
redirect_to = request.GET.get(REDIRECT_FIELD_NAME, REDIRECT_URL)

# Make sure we're not redirecting to other sites
if not is_safe_url(url=redirect_to, host=request.get_host()):
if not is_safe_url(url=redirect_to, allowed_hosts={request.get_host()}):
redirect_to = resolve_url(REDIRECT_URL)

if request.is_sudo():
Expand Down
49 changes: 0 additions & 49 deletions tasks.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class StubPasswordBackend(object):

password = "stub"

def authenticate(self, username, password):
def authenticate(self, request, username, password):
if password == self.password:
return User()

Expand Down
34 changes: 13 additions & 21 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GrantSudoPrivilegesTestCase(BaseTestCase):
def assertRequestHasToken(self, request, max_age):
token = request.session[COOKIE_NAME]

self.assertRegexpMatches(token, r"^\w{12}$")
self.assertRegex(token, r"^\w{12}$")
self.assertTrue(request._sudo)
self.assertEqual(request._sudo_token, token)
self.assertEqual(request._sudo_max_age, max_age)
Expand Down Expand Up @@ -108,25 +108,17 @@ def test_missing_keys(self):

class IsSafeUrlTestCase(BaseTestCase):
def test_success(self):
urls = (
("/", None),
("/foo/", None),
("/", "example.com"),
("http://example.com/foo", "example.com"),
)
for url in urls:
self.assertTrue(is_safe_url(*url))
self.assertTrue(is_safe_url("/", allowed_hosts=None))
self.assertTrue(is_safe_url("/foo/", allowed_hosts=None))
self.assertTrue(is_safe_url("/", allowed_hosts={"example.com"}))
self.assertTrue(is_safe_url("http://example.com/foo", allowed_hosts={"example.com"}))

def test_failure(self):
urls = (
(None, None),
("", ""),
("http://mattrobenolt.com/", "example.com"),
("///example.com/", None),
("ftp://example.com", "example.com"),
("http://example.com\@mattrobenolt.com", "example.com"), # noqa: W605
("http:///example.com", "example.com"),
("\x08//example.com", "example.com"),
)
for url in urls:
self.assertFalse(is_safe_url(*url))
self.assertFalse(is_safe_url(None, allowed_hosts=None))
self.assertFalse(is_safe_url("", allowed_hosts={""}))
self.assertFalse(is_safe_url("http://mattrobenolt.com/", allowed_hosts={"example.com"}))
self.assertFalse(is_safe_url("///example.com/", allowed_hosts=None))
self.assertFalse(is_safe_url("ftp://example.com", allowed_hosts={"example.com"}))
self.assertFalse(is_safe_url("http://example.com\\@mattrobenolt.com", allowed_hosts={"example.com"}))
self.assertFalse(is_safe_url("http:///example.com", allowed_hosts={"example.com"}))
self.assertFalse(is_safe_url("\x08//example.com", allowed_hosts={"example.com"}))
Loading