Skip to content
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
39 changes: 26 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
language: python
python:
- "2.6"
- "2.7"
- "3.3"
env:
- DJANGO_VERSION=1.3
- DJANGO_VERSION=1.4
- DJANGO_VERSION=1.5
- DJANGO_VERSION=1.6
matrix:
include:
- python: 2.7
env: TOXENV=py27-django18
- python: 2.7
env: TOXENV=py27-django19
- python: 2.7
env: TOXENV=py27-django110
- python: 2.7
env: TOXENV=py27-django111

- python: 3.6
env: TOXENV=py36-django18
- python: 3.6
env: TOXENV=py36-django19
- python: 3.6
env: TOXENV=py36-django110
- python: 3.6
env: TOXENV=py36-django111
- python: 3.6
env: TOXENV=py36-django20
- python: 3.6
env: TOXENV=py36-django21

install:
- if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install --use-mirrors importlib unittest2; fi
- pip install -q Django==$DJANGO_VERSION --use-mirrors
- pip install -q -r requirements.txt --use-mirrors
script: python manage.py test rest_framework_digestauth
- pip install tox
script: tox
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,20 @@ Once you've implimented a new backend, you can use it with the `DIGESTAUTH_BACKE
## Running the tests
To run the tests against the current environment:

$ ./manage.py test rest_framework_digestauth
$ pytest test

The tests with different environments can be run using tox:

$ tox

## Changelog

### Unreleased

- Drop support of the django 1.6 or lower
- Add support of the django 1.8-2.1
- Switch from *south* to *django* migration system

### 1.1.0

**31th Jan 2014**
Expand Down
2 changes: 0 additions & 2 deletions requirements.txt

This file was deleted.

2 changes: 1 addition & 1 deletion rest_framework_digestauth/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.1.0'
from ._version import __version__
1 change: 1 addition & 0 deletions rest_framework_digestauth/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = '1.1.0'
39 changes: 22 additions & 17 deletions rest_framework_digestauth/authentication.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import os
import hashlib
import os
from importlib import import_module

from django.core.signing import Signer
from django.contrib.auth import get_user_model
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.signing import Signer
from django.utils import six

from rest_framework import exceptions
from rest_framework import authentication
from rest_framework import exceptions

from rest_framework_digestauth.utils import parse_dict_header

__all__ = ['DigestAuthentication']

_User = get_user_model()


def _load_backed_class():
backend_path = getattr(
settings,
'DIGESTAUTH_BACKEND',
'rest_framework_digestauth.backends.DatabaseBackend',
).split('.')
return getattr(import_module('.'.join(backend_path[:-1])), backend_path[-1])

User = get_user_model()

backend_path = getattr(
settings,
'DIGESTAUTH_BACKEND',
'rest_framework_digestauth.backends.DatabaseBackend',
).split('.')
DigestBackend = getattr(import_module('.'.join(backend_path[:-1])), backend_path[-1])
_DigestBackend = _load_backed_class()


class DigestAuthentication(authentication.BaseAuthentication):
Expand All @@ -46,7 +51,7 @@ def authenticate(self, request):
return None
self.check_authorization_request_header()
user = self.get_user()
self.backend = DigestBackend(user)
self.backend = _DigestBackend(user)
password = self.backend.get_password()
if self.check_digest_auth(request, password):
return user, None
Expand Down Expand Up @@ -107,11 +112,11 @@ def get_user(self):
username = self.auth_header['username']
try:
username_field = 'username'
if hasattr(User, 'USERNAME_FIELD'):
username_field = User.USERNAME_FIELD
if hasattr(_User, 'USERNAME_FIELD'):
username_field = _User.USERNAME_FIELD
args = {username_field: username}
user = User.objects.get(**args)
except (User.DoesNotExist, User.MultipleObjectsReturned):
user = _User.objects.get(**args)
except (_User.DoesNotExist, _User.MultipleObjectsReturned):
raise exceptions.PermissionDenied
return user

Expand Down
9 changes: 5 additions & 4 deletions rest_framework_digestauth/backends.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@

from rest_framework import exceptions
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token

from rest_framework_digestauth.models import DigestAuthCounter

__all__ = ['AbstractDigestBackend', 'DatabaseBackend']


class AbstractDigestBackend(object):

def __init__(self, user):
self.user = user # This user is *unauthenticated*, beware.
self.user = user # This user is *unauthenticated*, beware.

def get_password(self):
"""
Expand Down Expand Up @@ -35,7 +37,6 @@ def set_counter(self, server_nonce, client_nonce, counter):
class DatabaseBackend(AbstractDigestBackend):

def get_password(self):
Token = TokenAuthentication.model
try:
token = Token.objects.get(user=self.user)
except (Token.DoesNotExist,
Expand Down
70 changes: 27 additions & 43 deletions rest_framework_digestauth/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'DigestAuthCounter'
db.create_table(u'rest_framework_digestauth_digestauthcounter', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('server_nonce', self.gf('django.db.models.fields.TextField')()),
('client_nonce', self.gf('django.db.models.fields.TextField')()),
('client_counter', self.gf('django.db.models.fields.IntegerField')(null=True)),
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
))
db.send_create_signal(u'rest_framework_digestauth', ['DigestAuthCounter'])

# Adding unique constraint on 'DigestAuthCounter', fields ['server_nonce', 'client_nonce']
db.create_unique(u'rest_framework_digestauth_digestauthcounter', ['server_nonce', 'client_nonce'])


def backwards(self, orm):
# Removing unique constraint on 'DigestAuthCounter', fields ['server_nonce', 'client_nonce']
db.delete_unique(u'rest_framework_digestauth_digestauthcounter', ['server_nonce', 'client_nonce'])

# Deleting model 'DigestAuthCounter'
db.delete_table(u'rest_framework_digestauth_digestauthcounter')


models = {
u'rest_framework_digestauth.digestauthcounter': {
'Meta': {'unique_together': "(('server_nonce', 'client_nonce'),)", 'object_name': 'DigestAuthCounter'},
'client_counter': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'client_nonce': ('django.db.models.fields.TextField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'server_nonce': ('django.db.models.fields.TextField', [], {})
}
}

complete_apps = ['rest_framework_digestauth']
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):
initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='DigestAuthCounter',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('server_nonce', models.TextField()),
('client_nonce', models.TextField()),
('client_counter', models.IntegerField(null=True)),
('created', models.DateTimeField(auto_now_add=True)),
],
),
migrations.AlterUniqueTogether(
name='digestauthcounter',
unique_together={('server_nonce', 'client_nonce')},
),
]
3 changes: 2 additions & 1 deletion rest_framework_digestauth/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

from django.db import models

__all__ = ['DigestAuthCounter']


class DigestAuthCounter(models.Model):
server_nonce = models.TextField()
Expand Down
16 changes: 2 additions & 14 deletions rest_framework_digestauth/utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
import sys
from six.moves.urllib.request import parse_http_list as _parse_list_header


_ver = sys.version_info

#: Python 2.x?
is_py2 = (_ver[0] == 2)

#: Python 3.x?
is_py3 = (_ver[0] == 3)

if is_py2:
from urllib2 import parse_http_list as _parse_list_header
elif is_py3:
from urllib.request import parse_http_list as _parse_list_header # NOQA
__all__ = ['parse_dict_header', 'unquote_header_value']


# From mitsuhiko/werkzeug (used with permission).
Expand Down
82 changes: 18 additions & 64 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,33 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function

from setuptools import setup
import re
import os
import sys


def get_version(package):
"""
Return package version as listed in `__version__` in `init.py`.
"""
init_py = open(os.path.join(package, '__init__.py')).read()
return re.search(
"^__version__ = ['\"]([^'\"]+)['\"]",
init_py, re.MULTILINE).group(1)


def get_packages(package):
"""
Return root package and all sub-packages.
"""
return [dirpath
for dirpath, dirnames, filenames in os.walk(package)
if os.path.exists(os.path.join(dirpath, '__init__.py'))]


def get_package_data(package):
"""
Return all files under the root package, that are not in a
package themselves.
"""
walk = [(dirpath.replace(package + os.sep, '', 1), filenames)
for dirpath, dirnames, filenames in os.walk(package)
if not os.path.exists(os.path.join(dirpath, '__init__.py'))]

filepaths = []
for base, filenames in walk:
filepaths.extend([os.path.join(base, filename)
for filename in filenames])
return {package: filepaths}


package = 'rest_framework_digestauth'
version = get_version(package)
install_requires = open('requirements.txt').read().split('\n')

try:
import importlib
except ImportError:
install_requires.append('importlib')


if sys.argv[-1] == 'publish':
os.system("python setup.py sdist upload")
args = {'version': version}
print("You probably want to also tag the version now:")
print(" git tag -a %(version)s -m 'version %(version)s'" % args)
print(" git push --tags")
sys.exit()
from setuptools import setup, find_packages

# Version info -- read without importing
_locals = {}
with open('rest_framework_digestauth/_version.py') as fp:
exec(fp.read(), None, _locals)
__version__ = _locals['__version__']

setup(
name='djangorestframework-digestauth',
version=version,
version=__version__,
url='http://github.com/juanriaza/django-rest-framework-digestauth',
license='BSD',
description='Digest HTTP auth support for Django REST framework',
author='Juan Riaza',
author_email='juanriaza@gmail.com',
packages=get_packages(package),
package_data=get_package_data(package),
install_requires=install_requires,
packages=find_packages(include="rest_framework_digestauth.*"),
include_package_data=True,
install_requires=[
'Django>=1.7',
'djangorestframework',
'six'
],
tests_require=[
'pytest',
'pytest-django'
],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Web Environment',
Expand Down
9 changes: 9 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
def pytest_configure():
import logging

logging.basicConfig(level=logging.INFO)

import os
import django
os.environ['DJANGO_SETTINGS_MODULE'] = 'test_app.settings'
django.setup()
Empty file added test/test_app/__init__.py
Empty file.
9 changes: 8 additions & 1 deletion testsettings.py → test/test_app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
'rest_framework_digestauth',
)

ROOT_URLCONF = 'rest_framework_digestauth.tests'
MIDDLEWARE = []

ROOT_URLCONF = 'test_app.urls'

SECRET_KEY = 'DIGESTAUTH'

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_digestauth.authentication.DigestAuthentication'],
"DEFAULT_PERMISSION_CLASSES": ['rest_framework.permissions.IsAuthenticated']
}
Loading