diff -Nru djoser-0.7.0/debian/changelog djoser-1.1.5/debian/changelog --- djoser-0.7.0/debian/changelog 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/changelog 2018-01-08 15:02:20.000000000 +0000 @@ -1,3 +1,14 @@ +djoser (1.1.5-1) unstable; urgency=low + + * New upstream release. + * Always use pristine-tar. + * Run wrap-and-sort -bast to reduce diff size of future changes. + * Bump debhelper compatibility and version to 11. + * Bump Standards-Version to 4.1.3. + * Fix name of README.rst (formerly README.md). + + -- Michael Fladischer Mon, 08 Jan 2018 16:02:20 +0100 + djoser (0.7.0-1) unstable; urgency=low * New upstream release. diff -Nru djoser-0.7.0/debian/compat djoser-1.1.5/debian/compat --- djoser-0.7.0/debian/compat 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/compat 2018-01-08 15:02:20.000000000 +0000 @@ -1 +1 @@ -9 +11 diff -Nru djoser-0.7.0/debian/control djoser-1.1.5/debian/control --- djoser-0.7.0/debian/control 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/control 2018-01-08 15:02:20.000000000 +0000 @@ -2,20 +2,22 @@ Section: python Priority: optional Maintainer: Debian Python Modules Team -Uploaders: Michael Fladischer -Build-Depends: debhelper (>= 9), - dh-python, - python-all, - python-django (>= 1.7), - python-djangorestframework (>= 3), - python-pypandoc, - python-setuptools, - python3-all, - python3-django, - python3-djangorestframework (>= 3), - python3-pypandoc, - python3-setuptools -Standards-Version: 4.1.0 +Uploaders: + Michael Fladischer , +Build-Depends: + debhelper (>= 11), + dh-python, + python-all, + python-django (>= 1.7), + python-djangorestframework (>= 3), + python-pypandoc, + python-setuptools, + python3-all, + python3-django, + python3-djangorestframework (>= 3), + python3-pypandoc, + python3-setuptools, +Standards-Version: 4.1.3 X-Python-Version: >= 2.7 X-Python3-Version: >= 3.4 Homepage: https://github.com/sunscrapers/djoser @@ -24,10 +26,11 @@ Package: python-djoser Architecture: all -Depends: python-django (>= 1.7), - python-djangorestframework (>= 3), - ${misc:Depends}, - ${python:Depends} +Depends: + python-django (>= 1.7), + python-djangorestframework (>= 3), + ${misc:Depends}, + ${python:Depends}, Description: REST implementation of Django authentication system Djoser library provides a set of Django Rest Framework views to handle basic actions such as registration, login, logout, password reset and account @@ -42,10 +45,11 @@ Package: python3-djoser Architecture: all -Depends: python3-django, - python3-djangorestframework (>= 3), - ${misc:Depends}, - ${python3:Depends} +Depends: + python3-django, + python3-djangorestframework (>= 3), + ${misc:Depends}, + ${python3:Depends}, Description: REST implementation of Django authentication system (Python3 version) Djoser library provides a set of Django Rest Framework views to handle basic actions such as registration, login, logout, password reset and account diff -Nru djoser-0.7.0/debian/gbp.conf djoser-1.1.5/debian/gbp.conf --- djoser-0.7.0/debian/gbp.conf 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/gbp.conf 2018-01-08 15:02:20.000000000 +0000 @@ -1,2 +1,3 @@ [DEFAULT] debian-branch=debian/master +pristine-tar=True diff -Nru djoser-0.7.0/debian/python3-djoser.docs djoser-1.1.5/debian/python3-djoser.docs --- djoser-0.7.0/debian/python3-djoser.docs 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/python3-djoser.docs 2018-01-08 15:02:20.000000000 +0000 @@ -1 +1 @@ -README.md +README.rst diff -Nru djoser-0.7.0/debian/python-djoser.docs djoser-1.1.5/debian/python-djoser.docs --- djoser-0.7.0/debian/python-djoser.docs 2017-09-12 17:13:41.000000000 +0000 +++ djoser-1.1.5/debian/python-djoser.docs 2018-01-08 15:02:20.000000000 +0000 @@ -1 +1 @@ -README.md +README.rst diff -Nru djoser-0.7.0/djoser/compat.py djoser-1.1.5/djoser/compat.py --- djoser-0.7.0/djoser/compat.py 2017-08-25 22:23:27.000000000 +0000 +++ djoser-1.1.5/djoser/compat.py 2017-10-07 16:31:33.000000000 +0000 @@ -1,11 +1,6 @@ from djoser.conf import settings -try: - from django.contrib.auth.password_validation import validate_password -except ImportError: - from password_validation import validate_password - -__all__ = ['settings', 'validate_password'] +__all__ = ['settings'] def get_user_email(user): diff -Nru djoser-0.7.0/djoser/conf.py djoser-1.1.5/djoser/conf.py --- djoser-0.7.0/djoser/conf.py 2017-08-25 14:10:17.000000000 +0000 +++ djoser-1.1.5/djoser/conf.py 2017-11-05 01:11:16.000000000 +0000 @@ -24,21 +24,17 @@ default_settings = { - 'USE_HTML_EMAIL_TEMPLATES': False, 'SEND_ACTIVATION_EMAIL': False, 'SEND_CONFIRMATION_EMAIL': False, 'SET_PASSWORD_RETYPE': False, 'SET_USERNAME_RETYPE': False, 'PASSWORD_RESET_CONFIRM_RETYPE': False, 'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': False, - 'ROOT_VIEW_URLS_MAPPING': {}, 'PASSWORD_VALIDATORS': [], 'TOKEN_MODEL': 'rest_framework.authtoken.models.Token', 'SERIALIZERS': ObjDict({ 'activation': 'djoser.serializers.ActivationSerializer', - 'login': - 'djoser.serializers.LoginSerializer', 'password_reset': 'djoser.serializers.PasswordResetSerializer', 'password_reset_confirm': @@ -53,18 +49,29 @@ 'djoser.serializers.SetUsernameSerializer', 'set_username_retype': 'djoser.serializers.SetUsernameRetypeSerializer', - 'user_registration': - 'djoser.serializers.UserRegistrationSerializer', + 'user_create': + 'djoser.serializers.UserCreateSerializer', + 'user_delete': + 'djoser.serializers.UserDeleteSerializer', 'user': 'djoser.serializers.UserSerializer', 'token': 'djoser.serializers.TokenSerializer', + 'token_create': + 'djoser.serializers.TokenCreateSerializer', + }), + 'EMAIL': ObjDict({ + 'activation': 'djoser.email.ActivationEmail', + 'confirmation': 'djoser.email.ConfirmationEmail', + 'password_reset': 'djoser.email.PasswordResetEmail', }), 'LOGOUT_ON_PASSWORD_CHANGE': False, 'USER_EMAIL_FIELD_NAME': 'email', + 'SOCIAL_AUTH_TOKEN_STRATEGY': 'djoser.social.token.jwt.TokenStrategy', + 'SOCIAL_AUTH_ALLOWED_REDIRECT_URIS': [], } -SETTINGS_TO_IMPORT = ['TOKEN_MODEL'] +SETTINGS_TO_IMPORT = ['TOKEN_MODEL', 'SOCIAL_AUTH_TOKEN_STRATEGY'] class Settings(object): diff -Nru djoser-0.7.0/djoser/email.py djoser-1.1.5/djoser/email.py --- djoser-0.7.0/djoser/email.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/email.py 2017-10-19 22:00:57.000000000 +0000 @@ -0,0 +1,36 @@ +from django.contrib.auth.tokens import default_token_generator + +from templated_mail.mail import BaseEmailMessage + +from djoser import utils +from djoser.conf import settings + + +class ActivationEmail(BaseEmailMessage): + template_name = 'email/activation.html' + + def get_context_data(self): + context = super(ActivationEmail, self).get_context_data() + + user = context.get('user') + context['uid'] = utils.encode_uid(user.pk) + context['token'] = default_token_generator.make_token(user) + context['url'] = settings.ACTIVATION_URL.format(**context) + return context + + +class ConfirmationEmail(BaseEmailMessage): + template_name = 'email/confirmation.html' + + +class PasswordResetEmail(BaseEmailMessage): + template_name = 'email/password_reset.html' + + def get_context_data(self): + context = super(PasswordResetEmail, self).get_context_data() + + user = context.get('user') + context['uid'] = utils.encode_uid(user.pk) + context['token'] = default_token_generator.make_token(user) + context['url'] = settings.PASSWORD_RESET_CONFIRM_URL.format(**context) + return context diff -Nru djoser-0.7.0/djoser/serializers.py djoser-1.1.5/djoser/serializers.py --- djoser-0.7.0/djoser/serializers.py 2017-08-25 16:18:53.000000000 +0000 +++ djoser-1.1.5/djoser/serializers.py 2017-11-03 09:51:19.000000000 +0000 @@ -1,12 +1,12 @@ from django.contrib.auth import authenticate, get_user_model +from django.contrib.auth.password_validation import validate_password +from django.core import exceptions as django_exceptions from django.db import IntegrityError, transaction from rest_framework import exceptions, serializers from djoser import constants, utils -from djoser.compat import ( - get_user_email, get_user_email_field_name, validate_password -) +from djoser.compat import get_user_email, get_user_email_field_name from djoser.conf import settings User = get_user_model() @@ -31,7 +31,7 @@ return super(UserSerializer, self).update(instance, validated_data) -class UserRegistrationSerializer(serializers.ModelSerializer): +class UserCreateSerializer(serializers.ModelSerializer): password = serializers.CharField( style={'input_type': 'password'}, write_only=True @@ -47,17 +47,22 @@ User.USERNAME_FIELD, User._meta.pk.name, 'password', ) - def validate_password(self, value): - validate_password(value) - return value + def validate(self, attrs): + user = User(**attrs) + password = attrs.get('password') + + try: + validate_password(password, user) + except django_exceptions.ValidationError as e: + raise serializers.ValidationError({'password': list(e.messages)}) + + return attrs def create(self, validated_data): try: user = self.perform_create(validated_data) except IntegrityError: - raise serializers.ValidationError( - self.error_messages['cannot_create_user'] - ) + self.fail('cannot_create_user') return user @@ -70,18 +75,18 @@ return user -class LoginSerializer(serializers.Serializer): +class TokenCreateSerializer(serializers.Serializer): password = serializers.CharField( required=False, style={'input_type': 'password'} ) default_error_messages = { - 'inactive_account': constants.INACTIVE_ACCOUNT_ERROR, 'invalid_credentials': constants.INVALID_CREDENTIALS_ERROR, + 'inactive_account': constants.INACTIVE_ACCOUNT_ERROR, } def __init__(self, *args, **kwargs): - super(LoginSerializer, self).__init__(*args, **kwargs) + super(TokenCreateSerializer, self).__init__(*args, **kwargs) self.user = None self.fields[User.USERNAME_FIELD] = serializers.CharField( required=False @@ -99,31 +104,24 @@ def _validate_user_exists(self, user): if not user: - raise serializers.ValidationError( - self.error_messages['invalid_credentials'] - ) + self.fail('invalid_credentials') def _validate_user_is_active(self, user): if not user.is_active: - raise serializers.ValidationError( - self.error_messages['inactive_account'] - ) + self.fail('inactive_account') class PasswordResetSerializer(serializers.Serializer): email = serializers.EmailField() - default_error_messages = { - 'email_not_found': constants.EMAIL_NOT_FOUND - } + default_error_messages = {'email_not_found': constants.EMAIL_NOT_FOUND} def validate_email(self, value): users = self.context['view'].get_users(value) if settings.PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND and not users: - raise serializers.ValidationError( - self.error_messages['email_not_found'] - ) - return value + self.fail('email_not_found') + else: + return value class UidAndTokenSerializer(serializers.Serializer): @@ -140,9 +138,8 @@ uid = utils.decode_uid(value) self.user = User.objects.get(pk=uid) except (User.DoesNotExist, ValueError, TypeError, OverflowError): - raise serializers.ValidationError( - self.error_messages['invalid_uid'] - ) + self.fail('invalid_uid') + return value def validate(self, attrs): @@ -152,13 +149,12 @@ ) if is_token_valid: return attrs - raise serializers.ValidationError(self.error_messages['invalid_token']) + else: + self.fail('invalid_token') class ActivationSerializer(UidAndTokenSerializer): - default_error_messages = { - 'stale_token': constants.STALE_TOKEN_ERROR, - } + default_error_messages = {'stale_token': constants.STALE_TOKEN_ERROR} def validate(self, attrs): attrs = super(ActivationSerializer, self).validate(attrs) @@ -170,9 +166,17 @@ class PasswordSerializer(serializers.Serializer): new_password = serializers.CharField(style={'input_type': 'password'}) - def validate_new_password(self, value): - validate_password(value) - return value + def validate(self, attrs): + user = self.context['request'].user or self.user + assert user is not None + + try: + validate_password(attrs['new_password'], user) + except django_exceptions.ValidationError as e: + raise serializers.ValidationError({ + 'new_password': list(e.messages) + }) + return super(PasswordSerializer, self).validate(attrs) class PasswordRetypeSerializer(PasswordSerializer): @@ -186,9 +190,8 @@ attrs = super(PasswordRetypeSerializer, self).validate(attrs) if attrs['new_password'] == attrs['re_new_password']: return attrs - raise serializers.ValidationError( - self.error_messages['password_mismatch'] - ) + else: + self.fail('password_mismatch') class CurrentPasswordSerializer(serializers.Serializer): @@ -202,9 +205,8 @@ is_password_valid = self.context['request'].user.check_password(value) if is_password_valid: return value - raise serializers.ValidationError( - self.error_messages['invalid_password'] - ) + else: + self.fail('invalid_password') class SetPasswordSerializer(PasswordSerializer, CurrentPasswordSerializer): @@ -226,15 +228,16 @@ pass +class UserDeleteSerializer(CurrentPasswordSerializer): + pass + + class SetUsernameSerializer(serializers.ModelSerializer, CurrentPasswordSerializer): class Meta(object): model = User - fields = ( - User.USERNAME_FIELD, - 'current_password', - ) + fields = (User.USERNAME_FIELD, 'current_password') def __init__(self, *args, **kwargs): """ @@ -262,12 +265,9 @@ attrs = super(SetUsernameRetypeSerializer, self).validate(attrs) new_username = attrs[User.USERNAME_FIELD] if new_username != attrs['re_new_' + User.USERNAME_FIELD]: - raise serializers.ValidationError( - self.error_messages['username_mismatch'].format( - User.USERNAME_FIELD - ) - ) - return attrs + self.fail('username_mismatch') + else: + return attrs class TokenSerializer(serializers.ModelSerializer): @@ -275,6 +275,4 @@ class Meta: model = settings.TOKEN_MODEL - fields = ( - 'auth_token', - ) + fields = ('auth_token',) diff -Nru djoser-0.7.0/djoser/social/backends/facebook.py djoser-1.1.5/djoser/social/backends/facebook.py --- djoser-0.7.0/djoser/social/backends/facebook.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/social/backends/facebook.py 2017-11-05 01:11:16.000000000 +0000 @@ -0,0 +1,5 @@ +from social_core.backends.facebook import FacebookOAuth2 + + +class FacebookOAuth2Override(FacebookOAuth2): + REDIRECT_STATE = False diff -Nru djoser-0.7.0/djoser/social/serializers.py djoser-1.1.5/djoser/social/serializers.py --- djoser-0.7.0/djoser/social/serializers.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/social/serializers.py 2017-12-08 11:21:40.000000000 +0000 @@ -0,0 +1,62 @@ +from rest_framework import serializers + +from social_core import exceptions +from social_django.utils import load_backend, load_strategy + +from djoser.conf import settings + + +class ProviderAuthSerializer(serializers.Serializer): + # GET auth token + token = serializers.CharField(read_only=True) + user = serializers.CharField(read_only=True) + + def create(self, validated_data): + user = validated_data['user'] + return settings.SOCIAL_AUTH_TOKEN_STRATEGY.obtain(user) + + def validate(self, attrs): + request = self.context['request'] + if 'state' in request.GET: + self._validate_state(request.GET['state']) + + strategy = load_strategy(request) + redirect_uri = strategy.session_get('redirect_uri') + + backend_name = self.context['view'].kwargs['provider'] + backend = load_backend( + strategy, backend_name, redirect_uri=redirect_uri + ) + + try: + user = backend.auth_complete() + except exceptions.AuthException as e: + raise serializers.ValidationError(str(e)) + return {'user': user} + + def _validate_state(self, value): + request = self.context['request'] + strategy = load_strategy(request) + redirect_uri = strategy.session_get('redirect_uri') + + backend_name = self.context['view'].kwargs['provider'] + backend = load_backend( + strategy, backend_name, redirect_uri=redirect_uri + ) + + try: + backend.validate_state() + except exceptions.AuthMissingParameter: + raise serializers.ValidationError( + 'State could not be found in request data.' + ) + except exceptions.AuthStateMissing: + raise serializers.ValidationError( + 'State could not be found in server-side session data.' + ) + except exceptions.AuthStateForbidden: + raise serializers.ValidationError( + 'Invalid state has been provided.' + ) + + return value diff -Nru djoser-0.7.0/djoser/social/token/jwt.py djoser-1.1.5/djoser/social/token/jwt.py --- djoser-0.7.0/djoser/social/token/jwt.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/social/token/jwt.py 2017-11-05 09:21:42.000000000 +0000 @@ -0,0 +1,9 @@ +class TokenStrategy: + @classmethod + def obtain(cls, user): + from rest_framework_jwt.settings import api_settings + payload = api_settings.JWT_PAYLOAD_HANDLER(user) + return { + 'token': api_settings.JWT_ENCODE_HANDLER(payload), + 'user': user + } diff -Nru djoser-0.7.0/djoser/social/urls.py djoser-1.1.5/djoser/social/urls.py --- djoser-0.7.0/djoser/social/urls.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/social/urls.py 2017-11-05 01:11:16.000000000 +0000 @@ -0,0 +1,12 @@ +from django.conf.urls import url + +from djoser.social import views + + +urlpatterns = [ + url( + r'^o/(?P\S+)/$', + views.ProviderAuthView.as_view(), + name='provider-auth' + ), +] diff -Nru djoser-0.7.0/djoser/social/views.py djoser-1.1.5/djoser/social/views.py --- djoser-0.7.0/djoser/social/views.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/social/views.py 2017-11-05 01:11:16.000000000 +0000 @@ -0,0 +1,29 @@ +from rest_framework import generics, permissions, status +from rest_framework.response import Response + +from social_django.utils import load_backend, load_strategy + +from djoser.conf import settings +from djoser.social.serializers import ProviderAuthSerializer + + +class ProviderAuthView(generics.CreateAPIView): + permission_classes = [permissions.AllowAny] + serializer_class = ProviderAuthSerializer + + def get(self, request, *args, **kwargs): + redirect_uri = request.GET.get('redirect_uri') + if redirect_uri not in settings.SOCIAL_AUTH_ALLOWED_REDIRECT_URIS: + return Response(status=status.HTTP_400_BAD_REQUEST) + strategy = load_strategy(request) + strategy.session_set('redirect_uri', redirect_uri) + + backend_name = self.kwargs['provider'] + backend = load_backend( + strategy, backend_name, redirect_uri=redirect_uri + + ) + authorization_url = backend.auth_url() + return Response(data={ + 'authorization_url': authorization_url, + }) diff -Nru djoser-0.7.0/djoser/templates/activation_email_body.html djoser-1.1.5/djoser/templates/activation_email_body.html --- djoser-0.7.0/djoser/templates/activation_email_body.html 2017-06-16 09:33:34.000000000 +0000 +++ djoser-1.1.5/djoser/templates/activation_email_body.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -{% load i18n %}{% autoescape off %} - - -{% blocktrans %}

-You're receiving this email because you need to finish activation process on {{ site_name }}. -

{% endblocktrans %} - -

{% trans "Please go to the following page to activate account:" %}

-

{% block reset_link %}

-

{{ protocol }}://{{ domain }}/{{ url }}

-{% endblock %} - -

{% trans "Thanks for using our site!" %}

- -

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

- -{% endautoescape %} - - \ No newline at end of file diff -Nru djoser-0.7.0/djoser/templates/activation_email_body.txt djoser-1.1.5/djoser/templates/activation_email_body.txt --- djoser-0.7.0/djoser/templates/activation_email_body.txt 2017-06-16 09:34:12.000000000 +0000 +++ djoser-1.1.5/djoser/templates/activation_email_body.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% blocktrans %}You're receiving this email because you need to finish activation process on {{ site_name }}.{% endblocktrans %} - -{% trans "Please go to the following page to activate account:" %} -{% block reset_link %} -{{ protocol }}://{{ domain }}/{{ url }} -{% endblock %} - -{% trans "Thanks for using our site!" %} - -{% blocktrans %}The {{ site_name }} team{% endblocktrans %} - -{% endautoescape %} diff -Nru djoser-0.7.0/djoser/templates/activation_email_subject.txt djoser-1.1.5/djoser/templates/activation_email_subject.txt --- djoser-0.7.0/djoser/templates/activation_email_subject.txt 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/activation_email_subject.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% blocktrans %}Account activation on {{ site_name }}{% endblocktrans %} -{% endautoescape %} \ No newline at end of file diff -Nru djoser-0.7.0/djoser/templates/confirmation_email_body.html djoser-1.1.5/djoser/templates/confirmation_email_body.html --- djoser-0.7.0/djoser/templates/confirmation_email_body.html 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/confirmation_email_body.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -{% load i18n %}{% autoescape off %} - - -

{% trans "Your account has been created and is ready to use!" %}

- -

{% trans "Thanks for using our site!" %}

- -

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

- -{% endautoescape %} - - \ No newline at end of file diff -Nru djoser-0.7.0/djoser/templates/confirmation_email_body.txt djoser-1.1.5/djoser/templates/confirmation_email_body.txt --- djoser-0.7.0/djoser/templates/confirmation_email_body.txt 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/confirmation_email_body.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% trans "Your account has been created and is ready to use!" %} - -{% trans "Thanks for using our site!" %} - -{% blocktrans %}The {{ site_name }} team{% endblocktrans %} - -{% endautoescape %} \ No newline at end of file diff -Nru djoser-0.7.0/djoser/templates/confirmation_email_subject.txt djoser-1.1.5/djoser/templates/confirmation_email_subject.txt --- djoser-0.7.0/djoser/templates/confirmation_email_subject.txt 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/confirmation_email_subject.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% blocktrans %}{{ site_name }} - Your account has been successfully created and activated!{% endblocktrans %} -{% endautoescape %} diff -Nru djoser-0.7.0/djoser/templates/email/activation.html djoser-1.1.5/djoser/templates/email/activation.html --- djoser-0.7.0/djoser/templates/email/activation.html 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/templates/email/activation.html 2017-09-22 10:51:36.000000000 +0000 @@ -0,0 +1,29 @@ +{% load i18n %} + +{% block subject %} +{% blocktrans %}Account activation on {{ site_name }}{% endblocktrans %} +{% endblock subject %} + +{% block text_body %} +{% blocktrans %}You're receiving this email because you need to finish activation process on {{ site_name }}.{% endblocktrans %} + +{% trans "Please go to the following page to activate account:" %} +{{ protocol }}://{{ domain }}/{{ url }} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} +{% endblock text_body %} + +{% block html_body %} +{% blocktrans %} +

You're receiving this email because you need to finish activation process on {{ site_name }}.

{% endblocktrans %} + +

{% trans "Please go to the following page to activate account:" %}

+

{{ protocol }}://{{ domain }}/{{ url }}

+ +

{% trans "Thanks for using our site!" %}

+ +

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

+ +{% endblock html_body %} diff -Nru djoser-0.7.0/djoser/templates/email/confirmation.html djoser-1.1.5/djoser/templates/email/confirmation.html --- djoser-0.7.0/djoser/templates/email/confirmation.html 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/templates/email/confirmation.html 2017-09-22 10:51:36.000000000 +0000 @@ -0,0 +1,21 @@ +{% load i18n %} + +{% block subject %} +{% blocktrans %}{{ site_name }} - Your account has been successfully created and activated!{% endblocktrans %} +{% endblock %} + +{% block text_body %} +{% trans "Your account has been created and is ready to use!" %} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} +{% endblock text_body %} + +{% block html_body %} +

{% trans "Your account has been created and is ready to use!" %}

+ +

{% trans "Thanks for using our site!" %}

+ +

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

+{% endblock html_body %} diff -Nru djoser-0.7.0/djoser/templates/email/password_reset.html djoser-1.1.5/djoser/templates/email/password_reset.html --- djoser-0.7.0/djoser/templates/email/password_reset.html 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/templates/email/password_reset.html 2017-09-22 10:51:36.000000000 +0000 @@ -0,0 +1,29 @@ +{% load i18n %} + +{% block subject %} +{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %} +{% endblock subject %} + +{% block text_body %} +{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %} + +{% trans "Please go to the following page and choose a new password:" %} +{{ protocol }}://{{ domain }}/{{ url }} +{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} +{% endblock text_body %} + +{% block html_body %} +

{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}

+ +

{% trans "Please go to the following page and choose a new password:" %}

+{{ protocol }}://{{ domain }}/{{ url }} +

{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}

+ +

{% trans "Thanks for using our site!" %}

+ +

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

+{% endblock html_body %} diff -Nru djoser-0.7.0/djoser/templates/password_reset_email_body.html djoser-1.1.5/djoser/templates/password_reset_email_body.html --- djoser-0.7.0/djoser/templates/password_reset_email_body.html 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/password_reset_email_body.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -{% load i18n %}{% autoescape off %} - - -

-{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}

- -

{% trans "Please go to the following page and choose a new password:" %}

-

{% block reset_link %} -{{ protocol }}://{{ domain }}/{{ url }} -{% endblock %}

-

{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}

- -

{% trans "Thanks for using our site!" %}

- -

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

- -{% endautoescape %} diff -Nru djoser-0.7.0/djoser/templates/password_reset_email_body.txt djoser-1.1.5/djoser/templates/password_reset_email_body.txt --- djoser-0.7.0/djoser/templates/password_reset_email_body.txt 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/password_reset_email_body.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %} - -{% trans "Please go to the following page and choose a new password:" %} -{% block reset_link %} -{{ protocol }}://{{ domain }}/{{ url }} -{% endblock %} -{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }} - -{% trans "Thanks for using our site!" %} - -{% blocktrans %}The {{ site_name }} team{% endblocktrans %} - -{% endautoescape %} diff -Nru djoser-0.7.0/djoser/templates/password_reset_email_subject.txt djoser-1.1.5/djoser/templates/password_reset_email_subject.txt --- djoser-0.7.0/djoser/templates/password_reset_email_subject.txt 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/djoser/templates/password_reset_email_subject.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{% load i18n %}{% autoescape off %} -{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %} -{% endautoescape %} \ No newline at end of file diff -Nru djoser-0.7.0/djoser/urls/authtoken.py djoser-1.1.5/djoser/urls/authtoken.py --- djoser-0.7.0/djoser/urls/authtoken.py 2017-08-18 10:25:39.000000000 +0000 +++ djoser-1.1.5/djoser/urls/authtoken.py 2017-10-07 16:56:33.000000000 +0000 @@ -1,13 +1,17 @@ from django.conf.urls import url + from djoser import views -from . import base -urlpatterns = base.base_urlpatterns + ( - url(r'^login/$', views.LoginView.as_view(), name='login'), - url(r'^logout/$', views.LogoutView.as_view(), name='logout'), + +urlpatterns = [ + url( + r'^token/create/$', + views.TokenCreateView.as_view(), + name='token-create' + ), url( - r'^$', views.RootView.as_view(urls_extra_mapping={ - 'login': 'login', 'logout': 'logout' - }), name='root' + r'^token/destroy/$', + views.TokenDestroyView.as_view(), + name='token-destroy' ), -) +] diff -Nru djoser-0.7.0/djoser/urls/base.py djoser-1.1.5/djoser/urls/base.py --- djoser-0.7.0/djoser/urls/base.py 2017-08-18 10:29:54.000000000 +0000 +++ djoser-1.1.5/djoser/urls/base.py 2017-10-02 16:41:04.000000000 +0000 @@ -1,13 +1,28 @@ from django.conf.urls import url -from djoser import views from django.contrib.auth import get_user_model +from djoser import views + User = get_user_model() -base_urlpatterns = ( + +urlpatterns = [ url(r'^me/$', views.UserView.as_view(), name='user'), - url(r'^register/$', views.RegistrationView.as_view(), name='register'), - url(r'^activate/$', views.ActivationView.as_view(), name='activate'), + url( + r'^users/create/$', + views.UserCreateView.as_view(), + name='user-create' + ), + url( + r'^users/delete/$', + views.UserDeleteView.as_view(), + name='user-delete' + ), + url( + r'^users/activate/$', + views.ActivationView.as_view(), + name='user-activate' + ), url( r'^{0}/$'.format(User.USERNAME_FIELD), views.SetUsernameView.as_view(), @@ -24,8 +39,5 @@ views.PasswordResetConfirmView.as_view(), name='password_reset_confirm' ), -) - -urlpatterns = base_urlpatterns + ( url(r'^$', views.RootView.as_view(), name='root'), -) +] diff -Nru djoser-0.7.0/djoser/urls/jwt.py djoser-1.1.5/djoser/urls/jwt.py --- djoser-0.7.0/djoser/urls/jwt.py 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser/urls/jwt.py 2017-09-29 17:18:03.000000000 +0000 @@ -0,0 +1,10 @@ +from django.conf.urls import url + +from rest_framework_jwt import views + + +urlpatterns = [ + url(r'^jwt/create/', views.obtain_jwt_token, name='jwt-create'), + url(r'^jwt/refresh/', views.refresh_jwt_token, name='jwt-refresh'), + url(r'^jwt/verify/', views.verify_jwt_token, name='jwt-verify'), +] diff -Nru djoser-0.7.0/djoser/utils.py djoser-1.1.5/djoser/utils.py --- djoser-0.7.0/djoser/utils.py 2017-08-25 16:53:22.000000000 +0000 +++ djoser-1.1.5/djoser/utils.py 2017-09-22 10:51:36.000000000 +0000 @@ -1,14 +1,7 @@ -from django.conf import settings as django_settings from django.contrib.auth import user_logged_in, user_logged_out -from django.contrib.auth.tokens import default_token_generator -from django.contrib.sites.shortcuts import get_current_site -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.template import loader from django.utils.encoding import force_bytes, force_text from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode -from djoser import constants -from djoser.compat import get_user_email from djoser.conf import settings @@ -33,124 +26,8 @@ ) -def send_email(request, factory, user): - email_factory = factory.from_request(request, user) - email = email_factory.create() - email.send() - - class ActionViewMixin(object): def post(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) return self._action(serializer) - - -class UserEmailFactoryBase(object): - token_generator = default_token_generator - subject_template_name = None - plain_body_template_name = None - html_body_template_name = None - - def __init__(self, from_email, user, protocol, domain, site_name, - **context_data): - self.from_email = from_email - self.user = user - self.domain = domain - self.site_name = site_name - self.protocol = protocol - self.context_data = context_data - - @classmethod - def from_request(cls, request, user=None, from_email=None, protocol=None, - **context_data): - site = get_current_site(request) - from_email = from_email or getattr( - django_settings, 'DEFAULT_FROM_EMAIL', '' - ) - - return cls( - from_email=from_email, - user=user or request.user, - domain=django_settings.DJOSER.get('DOMAIN') or site.domain, - site_name=django_settings.DJOSER.get('SITE_NAME') or site.name, - protocol=protocol or ('https' if request.is_secure() else 'http'), - **context_data - ) - - def create(self): - assert self.plain_body_template_name or self.html_body_template_name - context = self.get_context() - subject = loader.render_to_string(self.subject_template_name, context) - subject = ''.join(subject.splitlines()) - - user_email = get_user_email(self.user) - if user_email is None: - raise ValueError(constants.USER_WITHOUT_EMAIL_FIELD_ERROR) - - if self.plain_body_template_name: - plain_body = loader.render_to_string( - self.plain_body_template_name, context - ) - email_message = EmailMultiAlternatives( - subject, plain_body, self.from_email, [user_email] - ) - if self.html_body_template_name: - html_body = loader.render_to_string( - self.html_body_template_name, context - ) - email_message.attach_alternative(html_body, 'text/html') - else: - html_body = loader.render_to_string( - self.html_body_template_name, context - ) - email_message = EmailMessage( - subject, html_body, self.from_email, [user_email] - ) - email_message.content_subtype = 'html' - return email_message - - def get_context(self): - context = { - 'user': self.user, - 'domain': self.domain, - 'site_name': self.site_name, - 'uid': encode_uid(self.user.pk), - 'token': self.token_generator.make_token(self.user), - 'protocol': self.protocol, - } - context.update(self.context_data) - return context - - -class UserActivationEmailFactory(UserEmailFactoryBase): - subject_template_name = 'activation_email_subject.txt' - plain_body_template_name = 'activation_email_body.txt' - if settings.USE_HTML_EMAIL_TEMPLATES: - html_body_template_name = 'activation_email_body.html' - - def get_context(self): - context = super(UserActivationEmailFactory, self).get_context() - context['url'] = settings.ACTIVATION_URL.format(**context) - return context - - -class UserPasswordResetEmailFactory(UserEmailFactoryBase): - subject_template_name = 'password_reset_email_subject.txt' - plain_body_template_name = 'password_reset_email_body.txt' - if settings.USE_HTML_EMAIL_TEMPLATES: - html_body_template_name = 'password_reset_email_body.html' - - def get_context(self): - context = super(UserPasswordResetEmailFactory, self).get_context() - context['url'] = settings.PASSWORD_RESET_CONFIRM_URL.format( - **context - ) - return context - - -class UserConfirmationEmailFactory(UserEmailFactoryBase): - subject_template_name = 'confirmation_email_subject.txt' - plain_body_template_name = 'confirmation_email_body.txt' - if settings.USE_HTML_EMAIL_TEMPLATES: - html_body_template_name = 'confirmation_email_body.html' diff -Nru djoser-0.7.0/djoser/views.py djoser-1.1.5/djoser/views.py --- djoser-0.7.0/djoser/views.py 2017-08-25 17:10:50.000000000 +0000 +++ djoser-1.1.5/djoser/views.py 2017-11-03 09:51:19.000000000 +0000 @@ -1,14 +1,14 @@ from django.contrib.auth import get_user_model from django.contrib.auth.tokens import default_token_generator +from django.urls.exceptions import NoReverseMatch from rest_framework import generics, permissions, status, views from rest_framework.response import Response from rest_framework.reverse import reverse +from djoser import utils, signals +from djoser.compat import get_user_email, get_user_email_field_name from djoser.conf import settings -from djoser.compat import get_user_email_field_name - -from . import utils, signals User = get_user_model() @@ -17,67 +17,87 @@ """ Root endpoint - use one of sub endpoints. """ - permission_classes = ( - permissions.AllowAny, - ) - urls_mapping = { - 'me': 'user', - 'register': 'register', - 'activate': 'activate', - 'change-' + User.USERNAME_FIELD: 'set_username', - 'change-password': 'set_password', - 'password-reset': 'password_reset', - 'password-reset-confirm': 'password_reset_confirm', - } - urls_extra_mapping = None - - def get_urls_mapping(self, **kwargs): - mapping = self.urls_mapping.copy() - mapping.update(kwargs) - if self.urls_extra_mapping: - mapping.update(self.urls_extra_mapping) - mapping.update(settings.ROOT_VIEW_URLS_MAPPING) - return mapping + permission_classes = [permissions.AllowAny] - def get(self, request, format=None): - return Response( - dict([(key, reverse(url_name, request=request, format=format)) - for key, url_name in self.get_urls_mapping().items()]) - ) + def aggregate_djoser_urlpattern_names(self): + from djoser.urls import base, authtoken + urlpattern_names = [pattern.name for pattern in base.urlpatterns] + urlpattern_names += [pattern.name for pattern in authtoken.urlpatterns] + urlpattern_names += self._get_jwt_urlpatterns() + + return urlpattern_names + + def get_urls_map(self, request, urlpattern_names, fmt): + urls_map = {} + for urlpattern_name in urlpattern_names: + try: + url = reverse(urlpattern_name, request=request, format=fmt) + except NoReverseMatch: + url = '' + urls_map[urlpattern_name] = url + return urls_map + + def get(self, request, fmt=None): + urlpattern_names = self.aggregate_djoser_urlpattern_names() + urls_map = self.get_urls_map(request, urlpattern_names, fmt) + return Response(urls_map) + + def _get_jwt_urlpatterns(self): + try: + from djoser.urls import jwt + return [pattern.name for pattern in jwt.urlpatterns] + except ImportError: + return [] -class RegistrationView(generics.CreateAPIView): +class UserCreateView(generics.CreateAPIView): """ Use this endpoint to register new user. """ - serializer_class = settings.SERIALIZERS.user_registration - permission_classes = ( - permissions.AllowAny, - ) + serializer_class = settings.SERIALIZERS.user_create + permission_classes = [permissions.AllowAny] def perform_create(self, serializer): user = serializer.save() signals.user_registered.send( sender=self.__class__, user=user, request=self.request ) - email_factory_cls = None + + context = {'user': user} + to = [get_user_email(user)] if settings.SEND_ACTIVATION_EMAIL: - email_factory_cls = utils.UserActivationEmailFactory + settings.EMAIL.activation(self.request, context).send(to) elif settings.SEND_CONFIRMATION_EMAIL: - email_factory_cls = utils.UserConfirmationEmailFactory + settings.EMAIL.confirmation(self.request, context).send(to) + + +class UserDeleteView(generics.CreateAPIView): + """ + Use this endpoint to remove actually authenticated user + """ + serializer_class = settings.SERIALIZERS.user_delete + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user - if email_factory_cls is not None: - utils.send_email(self.request, email_factory_cls, user) + def post(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data) + serializer.is_valid(raise_exception=True) + utils.logout_user(self.request) + instance.delete() -class LoginView(utils.ActionViewMixin, generics.GenericAPIView): + return Response(status=status.HTTP_204_NO_CONTENT) + + +class TokenCreateView(utils.ActionViewMixin, generics.GenericAPIView): """ Use this endpoint to obtain user authentication token. """ - serializer_class = settings.SERIALIZERS.login - permission_classes = ( - permissions.AllowAny, - ) + serializer_class = settings.SERIALIZERS.token_create + permission_classes = [permissions.AllowAny] def _action(self, serializer): token = utils.login_user(self.request, serializer.user) @@ -88,13 +108,11 @@ ) -class LogoutView(views.APIView): +class TokenDestroyView(views.APIView): """ Use this endpoint to logout user (remove user authentication token). """ - permission_classes = ( - permissions.IsAuthenticated, - ) + permission_classes = [permissions.IsAuthenticated] def post(self, request): utils.logout_user(request) @@ -106,9 +124,7 @@ Use this endpoint to send email to user with password reset link. """ serializer_class = settings.SERIALIZERS.password_reset - permission_classes = ( - permissions.AllowAny, - ) + permission_classes = [permissions.AllowAny] _users = None @@ -129,20 +145,16 @@ return self._users def send_password_reset_email(self, user): - email_factory = utils.UserPasswordResetEmailFactory.from_request( - self.request, user=user - ) - email = email_factory.create() - email.send() + context = {'user': user} + to = [get_user_email(user)] + settings.EMAIL.password_reset(self.request, context).send(to) class SetPasswordView(utils.ActionViewMixin, generics.GenericAPIView): """ Use this endpoint to change user password. """ - permission_classes = ( - permissions.IsAuthenticated, - ) + permission_classes = [permissions.IsAuthenticated] def get_serializer_class(self): if settings.SET_PASSWORD_RETYPE: @@ -163,9 +175,7 @@ """ Use this endpoint to finish reset password process. """ - permission_classes = ( - permissions.AllowAny, - ) + permission_classes = [permissions.AllowAny] token_generator = default_token_generator def get_serializer_class(self): @@ -184,22 +194,23 @@ Use this endpoint to activate user account. """ serializer_class = settings.SERIALIZERS.activation - permission_classes = ( - permissions.AllowAny, - ) + permission_classes = [permissions.AllowAny] token_generator = default_token_generator def _action(self, serializer): - serializer.user.is_active = True - serializer.user.save() + user = serializer.user + user.is_active = True + user.save() + signals.user_activated.send( - sender=self.__class__, user=serializer.user, request=self.request) + sender=self.__class__, user=user, request=self.request + ) if settings.SEND_CONFIRMATION_EMAIL: - email_factory = utils.UserConfirmationEmailFactory.from_request( - self.request, user=serializer.user) - email = email_factory.create() - email.send() + context = {'user': user} + to = [get_user_email(user)] + settings.EMAIL.confirmation(self.request, context).send(to) + return Response(status=status.HTTP_204_NO_CONTENT) @@ -207,7 +218,7 @@ """ Use this endpoint to change user username. """ - permission_classes = (permissions.IsAuthenticated,) + permission_classes = [permissions.IsAuthenticated] def get_serializer_class(self): if settings.SET_USERNAME_RETYPE: @@ -221,8 +232,9 @@ setattr(user, User.USERNAME_FIELD, new_username) if settings.SEND_ACTIVATION_EMAIL: user.is_active = False - email_factory_cls = utils.UserActivationEmailFactory - utils.send_email(self.request, email_factory_cls, user) + context = {'user': user} + to = [get_user_email(user)] + settings.EMAIL.activation(self.request, context).send(to) user.save() return Response(status=status.HTTP_204_NO_CONTENT) @@ -234,7 +246,7 @@ """ model = User serializer_class = settings.SERIALIZERS.user - permission_classes = (permissions.IsAuthenticated,) + permission_classes = [permissions.IsAuthenticated] def get_object(self, *args, **kwargs): return self.request.user @@ -243,5 +255,6 @@ super(UserView, self).perform_update(serializer) user = serializer.instance if settings.SEND_ACTIVATION_EMAIL and not user.is_active: - email_factory_cls = utils.UserActivationEmailFactory - utils.send_email(self.request, email_factory_cls, user) + context = {'user': user} + to = [get_user_email(user)] + settings.EMAIL.activation(self.request, context).send(to) diff -Nru djoser-0.7.0/djoser.egg-info/PKG-INFO djoser-1.1.5/djoser.egg-info/PKG-INFO --- djoser-0.7.0/djoser.egg-info/PKG-INFO 2017-09-01 09:03:34.000000000 +0000 +++ djoser-1.1.5/djoser.egg-info/PKG-INFO 2017-12-08 12:39:46.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: djoser -Version: 0.7.0 +Version: 1.1.5 Summary: REST version of Django authentication system. Home-page: https://github.com/sunscrapers/djoser Author: SUNSCRAPERS Author-email: info@sunscrapers.com License: MIT +Description-Content-Type: UNKNOWN Description: ====== djoser ====== @@ -25,7 +26,8 @@ REST implementation of `Django `_ authentication system. **djoser** library provides a set of `Django Rest Framework `_ views to handle basic actions such as registration, login, logout, password - reset and account activation. It works with `custom user model `_. + reset and account activation. It works with + `custom user model `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ @@ -33,13 +35,37 @@ Developed by `SUNSCRAPERS `_ with passion & patience. + .. image:: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd.png + :target: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd?autoplay=1&speed=2 + + Requirements + ============ + + To be able to run **djoser** you have to meet following requirements: + + - Python (2.7, 3.4, 3.5, 3.6) + - Django (1.10, 1.11) + - Django REST Framework (3.7) + + Installation + ============ + + Simply install using ``pip``: + + .. code-block:: bash + + $ pip install djoser + + And continue with the steps described at + `configuration `_ + guide. Documentation ============= Documentation is available to study at - `http://djoser.readthedocs.io `_ and in - ``docs`` directory. + `http://djoser.readthedocs.io `_ + and in ``docs`` directory. Contributing and development ============================ @@ -93,19 +119,22 @@ List of projects related to Django, REST and authentication: - - `django-rest-auth `_ - - `django-rest-framework-digestauth `_ - - `django-oauth-toolkit `_ - - `doac `_ - `django-rest-framework-jwt `_ - - `django-rest-framework-httpsignature `_ - - `hawkrest `_ + - `django-oauth-toolkit `_ + - `django-rest-auth `_ + - `django-rest-framework-digestauth `_ (not maintained) + - `doac `_ (not maintained) Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha +Classifier: Development Status :: 5 - Production/Stable Classifier: Framework :: Django +Classifier: Framework :: Django :: 1.10 +Classifier: Framework :: Django :: 1.11 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 diff -Nru djoser-0.7.0/djoser.egg-info/requires.txt djoser-1.1.5/djoser.egg-info/requires.txt --- djoser-0.7.0/djoser.egg-info/requires.txt 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/djoser.egg-info/requires.txt 2017-12-08 12:39:46.000000000 +0000 @@ -0,0 +1 @@ +django-templated-mail diff -Nru djoser-0.7.0/djoser.egg-info/SOURCES.txt djoser-1.1.5/djoser.egg-info/SOURCES.txt --- djoser-0.7.0/djoser.egg-info/SOURCES.txt 2017-09-01 09:03:34.000000000 +0000 +++ djoser-1.1.5/djoser.egg-info/SOURCES.txt 2017-12-08 12:39:46.000000000 +0000 @@ -1,3 +1,4 @@ +LICENSE MANIFEST.in README.rst requirements.txt @@ -7,6 +8,7 @@ djoser/compat.py djoser/conf.py djoser/constants.py +djoser/email.py djoser/serializers.py djoser/signals.py djoser/utils.py @@ -14,16 +16,20 @@ djoser.egg-info/PKG-INFO djoser.egg-info/SOURCES.txt djoser.egg-info/dependency_links.txt +djoser.egg-info/requires.txt djoser.egg-info/top_level.txt -djoser/templates/activation_email_body.html -djoser/templates/activation_email_body.txt -djoser/templates/activation_email_subject.txt -djoser/templates/confirmation_email_body.html -djoser/templates/confirmation_email_body.txt -djoser/templates/confirmation_email_subject.txt -djoser/templates/password_reset_email_body.html -djoser/templates/password_reset_email_body.txt -djoser/templates/password_reset_email_subject.txt +djoser/social/__init__.py +djoser/social/serializers.py +djoser/social/urls.py +djoser/social/views.py +djoser/social/backends/__init__.py +djoser/social/backends/facebook.py +djoser/social/token/__init__.py +djoser/social/token/jwt.py +djoser/templates/email/activation.html +djoser/templates/email/confirmation.html +djoser/templates/email/password_reset.html djoser/urls/__init__.py djoser/urls/authtoken.py -djoser/urls/base.py \ No newline at end of file +djoser/urls/base.py +djoser/urls/jwt.py \ No newline at end of file diff -Nru djoser-0.7.0/djoser.egg-info/top_level.txt djoser-1.1.5/djoser.egg-info/top_level.txt --- djoser-0.7.0/djoser.egg-info/top_level.txt 2017-09-01 09:03:34.000000000 +0000 +++ djoser-1.1.5/djoser.egg-info/top_level.txt 2017-12-08 12:39:46.000000000 +0000 @@ -1,2 +1,5 @@ djoser +djoser/social +djoser/social/backends +djoser/social/token djoser/urls diff -Nru djoser-0.7.0/LICENSE djoser-1.1.5/LICENSE --- djoser-0.7.0/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ djoser-1.1.5/LICENSE 2017-06-16 07:57:56.000000000 +0000 @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 SUNSCRAPERS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru djoser-0.7.0/MANIFEST.in djoser-1.1.5/MANIFEST.in --- djoser-0.7.0/MANIFEST.in 2017-06-16 07:57:56.000000000 +0000 +++ djoser-1.1.5/MANIFEST.in 2017-09-28 08:33:47.000000000 +0000 @@ -1,3 +1,4 @@ include README.md -include djoser/templates/* +include LICENSE +recursive-include djoser/templates *.html include requirements.txt diff -Nru djoser-0.7.0/PKG-INFO djoser-1.1.5/PKG-INFO --- djoser-0.7.0/PKG-INFO 2017-09-01 09:03:34.000000000 +0000 +++ djoser-1.1.5/PKG-INFO 2017-12-08 12:39:46.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: djoser -Version: 0.7.0 +Version: 1.1.5 Summary: REST version of Django authentication system. Home-page: https://github.com/sunscrapers/djoser Author: SUNSCRAPERS Author-email: info@sunscrapers.com License: MIT +Description-Content-Type: UNKNOWN Description: ====== djoser ====== @@ -25,7 +26,8 @@ REST implementation of `Django `_ authentication system. **djoser** library provides a set of `Django Rest Framework `_ views to handle basic actions such as registration, login, logout, password - reset and account activation. It works with `custom user model `_. + reset and account activation. It works with + `custom user model `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ @@ -33,13 +35,37 @@ Developed by `SUNSCRAPERS `_ with passion & patience. + .. image:: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd.png + :target: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd?autoplay=1&speed=2 + + Requirements + ============ + + To be able to run **djoser** you have to meet following requirements: + + - Python (2.7, 3.4, 3.5, 3.6) + - Django (1.10, 1.11) + - Django REST Framework (3.7) + + Installation + ============ + + Simply install using ``pip``: + + .. code-block:: bash + + $ pip install djoser + + And continue with the steps described at + `configuration `_ + guide. Documentation ============= Documentation is available to study at - `http://djoser.readthedocs.io `_ and in - ``docs`` directory. + `http://djoser.readthedocs.io `_ + and in ``docs`` directory. Contributing and development ============================ @@ -93,19 +119,22 @@ List of projects related to Django, REST and authentication: - - `django-rest-auth `_ - - `django-rest-framework-digestauth `_ - - `django-oauth-toolkit `_ - - `doac `_ - `django-rest-framework-jwt `_ - - `django-rest-framework-httpsignature `_ - - `hawkrest `_ + - `django-oauth-toolkit `_ + - `django-rest-auth `_ + - `django-rest-framework-digestauth `_ (not maintained) + - `doac `_ (not maintained) Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha +Classifier: Development Status :: 5 - Production/Stable Classifier: Framework :: Django +Classifier: Framework :: Django :: 1.10 +Classifier: Framework :: Django :: 1.11 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 diff -Nru djoser-0.7.0/README.rst djoser-1.1.5/README.rst --- djoser-0.7.0/README.rst 2017-08-25 13:49:39.000000000 +0000 +++ djoser-1.1.5/README.rst 2017-11-24 15:13:40.000000000 +0000 @@ -17,7 +17,8 @@ REST implementation of `Django `_ authentication system. **djoser** library provides a set of `Django Rest Framework `_ views to handle basic actions such as registration, login, logout, password -reset and account activation. It works with `custom user model `_. +reset and account activation. It works with +`custom user model `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ @@ -25,13 +26,37 @@ Developed by `SUNSCRAPERS `_ with passion & patience. +.. image:: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd.png + :target: https://asciinema.org/a/FBTYjfDPUr99jxZqbLOZhh9Pd?autoplay=1&speed=2 + +Requirements +============ + +To be able to run **djoser** you have to meet following requirements: + +- Python (2.7, 3.4, 3.5, 3.6) +- Django (1.10, 1.11) +- Django REST Framework (3.7) + +Installation +============ + +Simply install using ``pip``: + +.. code-block:: bash + + $ pip install djoser + +And continue with the steps described at +`configuration `_ +guide. Documentation ============= Documentation is available to study at -`http://djoser.readthedocs.io `_ and in -``docs`` directory. +`http://djoser.readthedocs.io `_ +and in ``docs`` directory. Contributing and development ============================ @@ -85,10 +110,8 @@ List of projects related to Django, REST and authentication: -- `django-rest-auth `_ -- `django-rest-framework-digestauth `_ -- `django-oauth-toolkit `_ -- `doac `_ - `django-rest-framework-jwt `_ -- `django-rest-framework-httpsignature `_ -- `hawkrest `_ +- `django-oauth-toolkit `_ +- `django-rest-auth `_ +- `django-rest-framework-digestauth `_ (not maintained) +- `doac `_ (not maintained) diff -Nru djoser-0.7.0/requirements.txt djoser-1.1.5/requirements.txt --- djoser-0.7.0/requirements.txt 2017-08-18 11:08:43.000000000 +0000 +++ djoser-1.1.5/requirements.txt 2017-11-05 01:11:16.000000000 +0000 @@ -1,5 +1,8 @@ -e . +django-templated-mail==1.0.0 +djangorestframework-jwt==1.11.0 djet==0.2.1 +social-auth-app-django==2.0.0 coverage==4.3.1 pytest==3.1.3 diff -Nru djoser-0.7.0/setup.py djoser-1.1.5/setup.py --- djoser-0.7.0/setup.py 2017-09-01 08:47:14.000000000 +0000 +++ djoser-1.1.5/setup.py 2017-12-08 12:37:20.000000000 +0000 @@ -17,23 +17,28 @@ setup( name='djoser', - version='0.7.0', + version='1.1.5', packages=get_packages('djoser'), license='MIT', author='SUNSCRAPERS', description='REST version of Django authentication system.', author_email='info@sunscrapers.com', long_description=readme, - install_requires=[], + install_requires=['django-templated-mail'], include_package_data=True, url='https://github.com/sunscrapers/djoser', classifiers=[ - 'Development Status :: 3 - Alpha', + 'Development Status :: 5 - Production/Stable', 'Framework :: Django', + 'Framework :: Django :: 1.10', + 'Framework :: Django :: 1.11', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ] )