djoser-2.0.3/0000755000175000017500000000000013530256235013564 5ustar minderminder00000000000000djoser-2.0.3/LICENSE0000644000175000017500000000207313515647632014603 0ustar minderminder00000000000000The MIT License (MIT) Copyright (c) 2013-2019 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. djoser-2.0.3/MANIFEST.in0000644000175000017500000000021213513377611015320 0ustar minderminder00000000000000include README.md include LICENSE recursive-include djoser/templates *.html recursive-include djoser/locale *.mo include requirements.txt djoser-2.0.3/PKG-INFO0000644000175000017500000001216113530256235014662 0ustar minderminder00000000000000Metadata-Version: 1.1 Name: djoser Version: 2.0.3 Summary: REST version of Django authentication system. Home-page: https://github.com/sunscrapers/djoser Author: SUNSCRAPERS Author-email: info@sunscrapers.com License: MIT Description: ====== djoser ====== .. image:: https://img.shields.io/pypi/v/djoser.svg :target: https://pypi.org/project/djoser .. image:: https://img.shields.io/travis/sunscrapers/djoser/master.svg :target: https://travis-ci.org/sunscrapers/djoser .. image:: https://img.shields.io/codecov/c/github/sunscrapers/djoser.svg :target: https://codecov.io/gh/sunscrapers/djoser .. image:: https://api.codacy.com/project/badge/Grade/c9bf80318d2741e5bb63912a5e0b32dc :alt: Codacy Badge :target: https://app.codacy.com/app/dekoza/djoser?utm_source=github.com&utm_medium=referral&utm_content=sunscrapers/djoser&utm_campaign=Badge_Grade_Dashboard 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 `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ architecture. 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 (3.5, 3.6, 3.7, 3.8) - Django (1.11, 2.2) - Django REST Framework (3.9, 3.10) If you need to support other versions, please use djoser<2. 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 `https://djoser.readthedocs.io `_ and in ``docs`` directory. Contributing and development ============================ To start developing on **djoser**, clone the repository: .. code-block:: bash $ git clone git@github.com:sunscrapers/djoser.git If you are a **pipenv** user you can quickly setup testing environment by using Make commands: .. code-block:: bash $ make init $ make test Otherwise, if you cannot use Make commands, please create virtualenv and install requirements manually: .. code-block:: bash $ pip install django djangorestframework $ pip install -r requirements.txt .. code-block:: bash $ cd testproject $ ./manage.py test If you need to run tests against all supported Python and Django versions then invoke: .. code-block:: bash $ pip install tox $ tox -p all You can also play with test project by running following commands: .. code-block:: bash $ ./manage.py migrate $ ./manage.py runserver Similar projects ================ List of projects related to Django, REST and authentication: - `django-rest-framework-simplejwt `_ - `django-oauth-toolkit `_ - `django-rest-auth `_ - `django-rest-framework-digestauth `_ (not maintained) Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Framework :: Django Classifier: Framework :: Django :: 1.11 Classifier: Framework :: Django :: 2.2 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 djoser-2.0.3/README.rst0000644000175000017500000000665313515647723015276 0ustar minderminder00000000000000====== djoser ====== .. image:: https://img.shields.io/pypi/v/djoser.svg :target: https://pypi.org/project/djoser .. image:: https://img.shields.io/travis/sunscrapers/djoser/master.svg :target: https://travis-ci.org/sunscrapers/djoser .. image:: https://img.shields.io/codecov/c/github/sunscrapers/djoser.svg :target: https://codecov.io/gh/sunscrapers/djoser .. image:: https://api.codacy.com/project/badge/Grade/c9bf80318d2741e5bb63912a5e0b32dc :alt: Codacy Badge :target: https://app.codacy.com/app/dekoza/djoser?utm_source=github.com&utm_medium=referral&utm_content=sunscrapers/djoser&utm_campaign=Badge_Grade_Dashboard 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 `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ architecture. 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 (3.5, 3.6, 3.7, 3.8) - Django (1.11, 2.2) - Django REST Framework (3.9, 3.10) If you need to support other versions, please use djoser<2. 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 `https://djoser.readthedocs.io `_ and in ``docs`` directory. Contributing and development ============================ To start developing on **djoser**, clone the repository: .. code-block:: bash $ git clone git@github.com:sunscrapers/djoser.git If you are a **pipenv** user you can quickly setup testing environment by using Make commands: .. code-block:: bash $ make init $ make test Otherwise, if you cannot use Make commands, please create virtualenv and install requirements manually: .. code-block:: bash $ pip install django djangorestframework $ pip install -r requirements.txt .. code-block:: bash $ cd testproject $ ./manage.py test If you need to run tests against all supported Python and Django versions then invoke: .. code-block:: bash $ pip install tox $ tox -p all You can also play with test project by running following commands: .. code-block:: bash $ ./manage.py migrate $ ./manage.py runserver Similar projects ================ List of projects related to Django, REST and authentication: - `django-rest-framework-simplejwt `_ - `django-oauth-toolkit `_ - `django-rest-auth `_ - `django-rest-framework-digestauth `_ (not maintained) djoser-2.0.3/djoser/0000755000175000017500000000000013530256235015052 5ustar minderminder00000000000000djoser-2.0.3/djoser/__init__.py0000644000175000017500000000002613530255676017171 0ustar minderminder00000000000000__version__ = "2.0.3" djoser-2.0.3/djoser/compat.py0000644000175000017500000000041313513401334016676 0ustar minderminder00000000000000from djoser.conf import settings __all__ = ["settings"] def get_user_email(user): email_field_name = get_user_email_field_name(user) return getattr(user, email_field_name, None) def get_user_email_field_name(user): return user.get_email_field_name() djoser-2.0.3/djoser/conf.py0000644000175000017500000001455413525746636016377 0ustar minderminder00000000000000from django.apps import apps from django.conf import settings as django_settings from django.test.signals import setting_changed from django.utils.functional import LazyObject from django.utils.module_loading import import_string DJOSER_SETTINGS_NAMESPACE = "DJOSER" auth_module, user_model = django_settings.AUTH_USER_MODEL.rsplit(".", 1) User = apps.get_model(auth_module, user_model) class ObjDict(dict): def __getattribute__(self, item): try: val = self[item] if isinstance(val, str): val = import_string(val) elif isinstance(val, (list, tuple)): val = [import_string(v) if isinstance(v, str) else v for v in val] self[item] = val except KeyError: val = super(ObjDict, self).__getattribute__(item) return val default_settings = { "LOGIN_FIELD": User.USERNAME_FIELD, "SEND_ACTIVATION_EMAIL": False, "SEND_CONFIRMATION_EMAIL": False, "USER_CREATE_PASSWORD_RETYPE": False, "SET_PASSWORD_RETYPE": False, "PASSWORD_RESET_CONFIRM_RETYPE": False, "SET_USERNAME_RETYPE": False, "USERNAME_RESET_CONFIRM_RETYPE": False, "PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND": False, "USERNAME_RESET_SHOW_EMAIL_NOT_FOUND": False, "PASSWORD_CHANGED_EMAIL_CONFIRMATION": False, "USERNAME_CHANGED_EMAIL_CONFIRMATION": False, "TOKEN_MODEL": "rest_framework.authtoken.models.Token", "SERIALIZERS": ObjDict( { "activation": "djoser.serializers.ActivationSerializer", "password_reset": "djoser.serializers.SendEmailResetSerializer", "password_reset_confirm": "djoser.serializers.PasswordResetConfirmSerializer", "password_reset_confirm_retype": "djoser.serializers.PasswordResetConfirmRetypeSerializer", "set_password": "djoser.serializers.SetPasswordSerializer", "set_password_retype": "djoser.serializers.SetPasswordRetypeSerializer", "set_username": "djoser.serializers.SetUsernameSerializer", "set_username_retype": "djoser.serializers.SetUsernameRetypeSerializer", "username_reset": "djoser.serializers.SendEmailResetSerializer", "username_reset_confirm": "djoser.serializers.UsernameResetConfirmSerializer", "username_reset_confirm_retype": "djoser.serializers.UsernameResetConfirmRetypeSerializer", "user_create": "djoser.serializers.UserCreateSerializer", "user_create_password_retype": "djoser.serializers.UserCreatePasswordRetypeSerializer", "user_delete": "djoser.serializers.UserDeleteSerializer", "user": "djoser.serializers.UserSerializer", "current_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", "password_changed_confirmation": "djoser.email.PasswordChangedConfirmationEmail", "username_changed_confirmation": "djoser.email.UsernameChangedConfirmationEmail", "username_reset": "djoser.email.UsernameResetEmail", } ), "CONSTANTS": ObjDict({"messages": "djoser.constants.Messages"}), "LOGOUT_ON_PASSWORD_CHANGE": False, "CREATE_SESSION_ON_LOGIN": False, "SOCIAL_AUTH_TOKEN_STRATEGY": "djoser.social.token.jwt.TokenStrategy", "SOCIAL_AUTH_ALLOWED_REDIRECT_URIS": [], "HIDE_USERS": True, "PERMISSIONS": ObjDict( { "activation": ["rest_framework.permissions.AllowAny"], "password_reset": ["rest_framework.permissions.AllowAny"], "password_reset_confirm": ["rest_framework.permissions.AllowAny"], "set_password": ["djoser.permissions.CurrentUserOrAdmin"], "username_reset": ["rest_framework.permissions.AllowAny"], "username_reset_confirm": ["rest_framework.permissions.AllowAny"], "set_username": ["djoser.permissions.CurrentUserOrAdmin"], "user_create": ["rest_framework.permissions.AllowAny"], "user_delete": ["djoser.permissions.CurrentUserOrAdmin"], "user": ["djoser.permissions.CurrentUserOrAdmin"], "user_list": ["djoser.permissions.CurrentUserOrAdmin"], "token_create": ["rest_framework.permissions.AllowAny"], "token_destroy": ["rest_framework.permissions.IsAuthenticated"], } ), } SETTINGS_TO_IMPORT = ["TOKEN_MODEL", "SOCIAL_AUTH_TOKEN_STRATEGY"] class Settings: def __init__(self, default_settings, explicit_overriden_settings: dict = None): if explicit_overriden_settings is None: explicit_overriden_settings = {} overriden_settings = ( getattr(django_settings, DJOSER_SETTINGS_NAMESPACE, {}) or explicit_overriden_settings ) self._load_default_settings() self._override_settings(overriden_settings) self._init_settings_to_import() def _load_default_settings(self): for setting_name, setting_value in default_settings.items(): if setting_name.isupper(): setattr(self, setting_name, setting_value) def _override_settings(self, overriden_settings: dict): for setting_name, setting_value in overriden_settings.items(): value = setting_value if isinstance(setting_value, dict): value = getattr(self, setting_name, {}) value.update(ObjDict(setting_value)) setattr(self, setting_name, value) def _init_settings_to_import(self): for setting_name in SETTINGS_TO_IMPORT: value = getattr(self, setting_name) if isinstance(value, str): setattr(self, setting_name, import_string(value)) class LazySettings(LazyObject): def _setup(self, explicit_overriden_settings=None): self._wrapped = Settings(default_settings, explicit_overriden_settings) settings = LazySettings() def reload_djoser_settings(*args, **kwargs): global settings setting, value = kwargs["setting"], kwargs["value"] if setting == DJOSER_SETTINGS_NAMESPACE: settings._setup(explicit_overriden_settings=value) setting_changed.connect(reload_djoser_settings) djoser-2.0.3/djoser/constants.py0000644000175000017500000000133113515647632017446 0ustar minderminder00000000000000from django.utils.translation import ugettext_lazy as _ class Messages(object): INVALID_CREDENTIALS_ERROR = _("Unable to log in with provided credentials.") INACTIVE_ACCOUNT_ERROR = _("User account is disabled.") INVALID_TOKEN_ERROR = _("Invalid token for given user.") INVALID_UID_ERROR = _("Invalid user id or user doesn't exist.") STALE_TOKEN_ERROR = _("Stale token for given user.") PASSWORD_MISMATCH_ERROR = _("The two password fields didn't match.") USERNAME_MISMATCH_ERROR = _("The two {0} fields didn't match.") INVALID_PASSWORD_ERROR = _("Invalid password.") EMAIL_NOT_FOUND = _("User with given email does not exist.") CANNOT_CREATE_USER_ERROR = _("Unable to create account.") djoser-2.0.3/djoser/email.py0000644000175000017500000000350513525262710016515 0ustar minderminder00000000000000from 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): # ActivationEmail can be deleted context = super().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): # PasswordResetEmail can be deleted context = super().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 class PasswordChangedConfirmationEmail(BaseEmailMessage): template_name = "email/password_changed_confirmation.html" class UsernameChangedConfirmationEmail(BaseEmailMessage): template_name = "email/username_changed_confirmation.html" class UsernameResetEmail(BaseEmailMessage): template_name = "email/username_reset.html" def get_context_data(self): context = super().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.USERNAME_RESET_CONFIRM_URL.format(**context) return context djoser-2.0.3/djoser/locale/0000755000175000017500000000000013530256235016311 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/ka/0000755000175000017500000000000013530256235016704 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/ka/LC_MESSAGES/0000755000175000017500000000000013530256235020471 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/ka/LC_MESSAGES/django.mo0000644000175000017500000001065113515541413022271 0ustar minderminder00000000000000I# &+R:r4%0 Vw*%q[j2^(JX,P`}{MZ s x 8 M 0 iM J Q T 8 $ b6pc%(site_name)s - Your account has been successfully created and activated!Account activation on %(site_name)sInvalid password.Invalid token for given user.Invalid user id or user doesn't exist.Password reset on %(site_name)sPlease go to the following page and choose a new password:Please go to the following page to activate account:Stale token for given user.Thanks for using our site!The %(site_name)s teamThe two password fields didn't match.The two {0} fields didn't match.Unable to create account.Unable to login with provided credentials.User account is disabled.User model does not contain specified email field. Please see http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME for more details.User with given email does not exist.You're receiving this email because you need to finish activation process on %(site_name)s.You're receiving this email because you requested a password reset for your user account at %(site_name)s.Your account has been created and is ready to use!Your username, in case you've forgotten:Project-Id-Version: 1.4.0 Report-Msgid-Bugs-To: POT-Creation-Date: 2019-01-25 09:44+0100 PO-Revision-Date: 2019-01-29 14:25+0100 Last-Translator: Szymon Pyżalski Language: ka_GE Language-Team: http://sunscrapers.com Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 %(site_name)s - თქვენი ანგარიში წარმატებით შეიქმნილია და გააკტიურებულია.ანგარიშის აკტივაცია საიტზე %(site_name)sარასწორი პაროლი.ნიშანი ტოკენი ამ მომხმარებელისთვისსახელი არასწორია ან მომხმარებელი არ არსებობს.პაროლის აღდგენა საიტზე %(site_name)s.მოჰყევით ამ ლინკს და მიუთითეთ ახალი პაროლი:მიჰყევით ამ ლინკს რათა გაააკტიუროთ ანგარიში:ნიშანი მოძველებულია.მადლობა საითის გამოიყენებასსაიტის %(site_name)s გუნდიპაროლის ორი ველი ერთმანეთს არ ემთხვევა.ორი {0} ერთმანეთს არ ემთხვევა.ანგარიშის შექმნა შეუძლებულია.შესვლა ამ სახელით და პაროლით არ არის შესაძლებელი.ანგარიში გამორთულია.მომხმარებელის მოდელი არ შეიცავს მითითებულ იმეილის ველს. ნახე http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME მეტი დეტალებისთვისმომხმარებელი ამ იმეილით არ არსებობს.თქვენ იღებთ ამ იმეილს, რადგან საჭიროა დაამთავროთ აკტივაციი პროცესი საიტზე %(site_name)s.ამ ემაილს იღებთ, რანდან თქვნენ მოთხოვეთ პაროლის აღდგენა თქვენი ანგარიშისთვის %(site_name)s საიტზე.თქვენი ანგარიში შეიქმნილია და მზად არის გამოყენებისთვის!თქვენი მომხმარებლის სახელი, იმ შემთხვევისათვის თუ დაგავიწყდათ:djoser-2.0.3/djoser/locale/pl/0000755000175000017500000000000013530256235016724 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/pl/LC_MESSAGES/0000755000175000017500000000000013530256235020511 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/pl/LC_MESSAGES/django.mo0000644000175000017500000000613013515541413022306 0ustar minderminder00000000000000I# &+R:r4%0 Vw*%q[j2^((;(H%X:~%4< *Q +|    3 J ] - f6 h 7 > %(site_name)s - Your account has been successfully created and activated!Account activation on %(site_name)sInvalid password.Invalid token for given user.Invalid user id or user doesn't exist.Password reset on %(site_name)sPlease go to the following page and choose a new password:Please go to the following page to activate account:Stale token for given user.Thanks for using our site!The %(site_name)s teamThe two password fields didn't match.The two {0} fields didn't match.Unable to create account.Unable to login with provided credentials.User account is disabled.User model does not contain specified email field. Please see http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME for more details.User with given email does not exist.You're receiving this email because you need to finish activation process on %(site_name)s.You're receiving this email because you requested a password reset for your user account at %(site_name)s.Your account has been created and is ready to use!Your username, in case you've forgotten:Project-Id-Version: 1.4.0 Report-Msgid-Bugs-To: POT-Creation-Date: 2019-01-28 15:21+0100 PO-Revision-Date: 2019-01-29 14:25+0100 Last-Translator: Szymon Pyżalski Language: pl_PL Language-Team: http://sunscrapers.com Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 %(site_name)s - Twoje konto zostało stworzone i aktywowaneAktywacja konta na stronie %(site_name)sBłedne hasło.Błędny token dla tego użytkownika.Błędna nazwa użytkownika, lub użytkownik nie istnieje.Reset hasła na stronie %(site_name)sPrzejdź do poniższej strony i wybierz nowe hasło:Proszę przejdź na poniższą stronę, by aktywować konto:Przestarzały token dla tego użytkownika.Dziękujemy za korzystanie z naszej strony!Zespół strony %(site_name)sPola hasła nie pasują.Pola {0} nie pasują.Nie udało się stworzyć konta.Nie udało się zalogować przy pomocy tych danych.Konto wyłączone.Model użytkownika nie zawiera wskazanego pola email. Zobacz http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME by zobaczyć więcej szczegółówUżytkownik z tym adresem email nie istnieje.Otrzymałeś tego emaila, ponieważ potrzeujesz dokończyć proces aktywacji na stronie %(site_name)s.Otrzymałeś tego emaila, ponieważ prosiłeś o reset hasła do Twojego konta na stronie %(site_name)s.Twoje konto zostało utworzone i jest gotowe do użyciaTwoja nazwa użytkownika:djoser-2.0.3/djoser/locale/ru_RU/0000755000175000017500000000000013530256235017345 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/ru_RU/LC_MESSAGES/0000755000175000017500000000000013530256235021132 5ustar minderminder00000000000000djoser-2.0.3/djoser/locale/ru_RU/LC_MESSAGES/django.mo0000644000175000017500000001016613515541413022733 0ustar minderminder00000000000000I# &+R:r4%0 Vw*%q[j2^(x6&4K[*' ~R Oe G  , =G @ d I+ Du t /kE0%(site_name)s - Your account has been successfully created and activated!Account activation on %(site_name)sInvalid password.Invalid token for given user.Invalid user id or user doesn't exist.Password reset on %(site_name)sPlease go to the following page and choose a new password:Please go to the following page to activate account:Stale token for given user.Thanks for using our site!The %(site_name)s teamThe two password fields didn't match.The two {0} fields didn't match.Unable to create account.Unable to login with provided credentials.User account is disabled.User model does not contain specified email field. Please see http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME for more details.User with given email does not exist.You're receiving this email because you need to finish activation process on %(site_name)s.You're receiving this email because you requested a password reset for your user account at %(site_name)s.Your account has been created and is ready to use!Your username, in case you've forgotten:Project-Id-Version: 1.4.0 Report-Msgid-Bugs-To: POT-Creation-Date: 2019-01-28 15:21+0100 PO-Revision-Date: 2019-05-14 12:05+0300 Last-Translator: Sergey Ozeranskiy Language: ru_RU Language-Team: Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 %(site_name)s - Ваша учетная запись была успешно создана и активирована!Активация аккаунта на %(site_name)sНеправильный пароль.Неверный токен для данного пользователя.Неверный идентификатор пользователя или пользователь не существует.Сброс пароля на %(site_name)sПожалуйста, перейдите на следующую страницу и создайте новый пароль:Пожалуйста, перейдите на следующую страницу, чтобы активировать учетную запись:Устаревший токен для данного пользователя.Спасибо за использование нашего сайта!Команда %(site_name)sДва пароля не совпадают.Два значения поля {0} не совпадают.Невозможно создать учетную запись.Невозможно войти с предоставленными учетными данными.Учетная запись пользователя не активна.Модель пользователя не содержит указанное поле для электронной почты. Пожалуйста, посмотрите http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME для получения дополнительной информации.Пользователь с данным адресом электронной почты не существует.Вы получили это письмо, потому что вам нужно завершить процесс активации учетной записи на %(site_name)s.Вы получили это письмо, потому что вы или кто-то другой запросили сброс пароля для учетной записи пользователя на %(site_name)s.Ваша учетная запись была создана и готова к использованию!Ваше имя пользователя, если вы забыли:djoser-2.0.3/djoser/permissions.py0000644000175000017500000000107613515421133017775 0ustar minderminder00000000000000from rest_framework import permissions from rest_framework.permissions import SAFE_METHODS class CurrentUserOrAdmin(permissions.IsAuthenticated): def has_object_permission(self, request, view, obj): user = request.user return user.is_staff or obj.pk == user.pk class CurrentUserOrAdminOrReadOnly(permissions.IsAuthenticated): def has_object_permission(self, request, view, obj): user = request.user if type(obj) == type(user) and obj == user: return True return request.method in SAFE_METHODS or user.is_staff djoser-2.0.3/djoser/serializers.py0000644000175000017500000002516313530256055017767 0ustar minderminder00000000000000from 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 rest_framework.exceptions import ValidationError from djoser import utils from djoser.compat import get_user_email, get_user_email_field_name from djoser.conf import settings User = get_user_model() class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = tuple(User.REQUIRED_FIELDS) + ( User._meta.pk.name, settings.LOGIN_FIELD, ) read_only_fields = (settings.LOGIN_FIELD,) def update(self, instance, validated_data): email_field = get_user_email_field_name(User) if settings.SEND_ACTIVATION_EMAIL and email_field in validated_data: instance_email = get_user_email(instance) if instance_email != validated_data[email_field]: instance.is_active = False instance.save(update_fields=["is_active"]) return super().update(instance, validated_data) class UserCreateSerializer(serializers.ModelSerializer): password = serializers.CharField(style={"input_type": "password"}, write_only=True) default_error_messages = { "cannot_create_user": settings.CONSTANTS.messages.CANNOT_CREATE_USER_ERROR } class Meta: model = User fields = tuple(User.REQUIRED_FIELDS) + ( settings.LOGIN_FIELD, User._meta.pk.name, "password", ) def validate(self, attrs): user = User(**attrs) password = attrs.get("password") try: validate_password(password, user) except django_exceptions.ValidationError as e: serializer_error = serializers.as_serializer_error(e) raise serializers.ValidationError( {"password": serializer_error["non_field_errors"]} ) return attrs def create(self, validated_data): try: user = self.perform_create(validated_data) except IntegrityError: self.fail("cannot_create_user") return user def perform_create(self, validated_data): with transaction.atomic(): user = User.objects.create_user(**validated_data) if settings.SEND_ACTIVATION_EMAIL: user.is_active = False user.save(update_fields=["is_active"]) return user class UserCreatePasswordRetypeSerializer(UserCreateSerializer): default_error_messages = { "password_mismatch": settings.CONSTANTS.messages.PASSWORD_MISMATCH_ERROR } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["re_password"] = serializers.CharField( style={"input_type": "password"} ) def validate(self, attrs): self.fields.pop("re_password", None) re_password = attrs.pop("re_password") attrs = super().validate(attrs) if attrs["password"] == re_password: return attrs else: self.fail("password_mismatch") class TokenCreateSerializer(serializers.Serializer): password = serializers.CharField(required=False, style={"input_type": "password"}) default_error_messages = { "invalid_credentials": settings.CONSTANTS.messages.INVALID_CREDENTIALS_ERROR, "inactive_account": settings.CONSTANTS.messages.INACTIVE_ACCOUNT_ERROR, } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.user = None self.fields[settings.LOGIN_FIELD] = serializers.CharField(required=False) def validate(self, attrs): password = attrs.get("password") params = {settings.LOGIN_FIELD: attrs.get(settings.LOGIN_FIELD)} self.user = authenticate(**params, password=password) if not self.user: self.user = User.objects.filter(**params).first() if self.user and not self.user.check_password(password): self.fail("invalid_credentials") if self.user and self.user.is_active: return attrs self.fail("invalid_credentials") class UserFunctionsMixin: def get_user(self, is_active=True): try: user = User._default_manager.get( is_active=is_active, **{self.email_field: self.data.get(self.email_field, "")}, ) if user.has_usable_password(): return user except User.DoesNotExist: pass if ( settings.PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND or settings.USERNAME_RESET_SHOW_EMAIL_NOT_FOUND ): self.fail("email_not_found") class SendEmailResetSerializer(serializers.Serializer, UserFunctionsMixin): default_error_messages = { "email_not_found": settings.CONSTANTS.messages.EMAIL_NOT_FOUND } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.email_field = get_user_email_field_name(User) self.fields[self.email_field] = serializers.EmailField() class UidAndTokenSerializer(serializers.Serializer): uid = serializers.CharField() token = serializers.CharField() default_error_messages = { "invalid_token": settings.CONSTANTS.messages.INVALID_TOKEN_ERROR, "invalid_uid": settings.CONSTANTS.messages.INVALID_UID_ERROR, } def validate(self, attrs): validated_data = super().validate(attrs) # uid validation have to be here, because validate_ # doesn't work with modelserializer try: uid = utils.decode_uid(self.initial_data.get("uid", "")) self.user = User.objects.get(pk=uid) except (User.DoesNotExist, ValueError, TypeError, OverflowError): key_error = "invalid_uid" raise ValidationError( {"uid": [self.error_messages[key_error]]}, code=key_error ) is_token_valid = self.context["view"].token_generator.check_token( self.user, self.initial_data.get("token", "") ) if is_token_valid: return validated_data else: key_error = "invalid_token" raise ValidationError( {"token": [self.error_messages[key_error]]}, code=key_error ) class ActivationSerializer(UidAndTokenSerializer): default_error_messages = { "stale_token": settings.CONSTANTS.messages.STALE_TOKEN_ERROR } def validate(self, attrs): attrs = super().validate(attrs) if not self.user.is_active: return attrs raise exceptions.PermissionDenied(self.error_messages["stale_token"]) class PasswordSerializer(serializers.Serializer): new_password = serializers.CharField(style={"input_type": "password"}) def validate(self, attrs): user = self.context["request"].user or self.user # why assert? There are ValidationError / fail everywhere 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().validate(attrs) class PasswordRetypeSerializer(PasswordSerializer): re_new_password = serializers.CharField(style={"input_type": "password"}) default_error_messages = { "password_mismatch": settings.CONSTANTS.messages.PASSWORD_MISMATCH_ERROR } def validate(self, attrs): attrs = super().validate(attrs) if attrs["new_password"] == attrs["re_new_password"]: return attrs else: self.fail("password_mismatch") class CurrentPasswordSerializer(serializers.Serializer): current_password = serializers.CharField(style={"input_type": "password"}) default_error_messages = { "invalid_password": settings.CONSTANTS.messages.INVALID_PASSWORD_ERROR } def validate_current_password(self, value): is_password_valid = self.context["request"].user.check_password(value) if is_password_valid: return value else: self.fail("invalid_password") class UsernameSerializer(serializers.ModelSerializer): class Meta: model = User fields = (settings.LOGIN_FIELD,) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.username_field = settings.LOGIN_FIELD self._default_username_field = User.USERNAME_FIELD self.fields["new_{}".format(self.username_field)] = self.fields.pop( self.username_field ) def save(self, **kwargs): if self.username_field != self._default_username_field: kwargs[User.USERNAME_FIELD] = self.validated_data.get( "new_{}".format(self.username_field) ) return super().save(**kwargs) class UsernameRetypeSerializer(UsernameSerializer): default_error_messages = { "username_mismatch": settings.CONSTANTS.messages.USERNAME_MISMATCH_ERROR.format( settings.LOGIN_FIELD ) } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["re_new_" + settings.LOGIN_FIELD] = serializers.CharField() def validate(self, attrs): attrs = super().validate(attrs) new_username = attrs[settings.LOGIN_FIELD] if new_username != attrs["re_new_{}".format(settings.LOGIN_FIELD)]: self.fail("username_mismatch") else: return attrs class TokenSerializer(serializers.ModelSerializer): auth_token = serializers.CharField(source="key") class Meta: model = settings.TOKEN_MODEL fields = ("auth_token",) class SetPasswordSerializer(PasswordSerializer, CurrentPasswordSerializer): pass class SetPasswordRetypeSerializer(PasswordRetypeSerializer, CurrentPasswordSerializer): pass class PasswordResetConfirmSerializer(UidAndTokenSerializer, PasswordSerializer): pass class PasswordResetConfirmRetypeSerializer( UidAndTokenSerializer, PasswordRetypeSerializer ): pass class UsernameResetConfirmSerializer(UidAndTokenSerializer, UsernameSerializer): pass class UsernameResetConfirmRetypeSerializer( UidAndTokenSerializer, UsernameRetypeSerializer ): pass class UserDeleteSerializer(CurrentPasswordSerializer): pass class SetUsernameSerializer(UsernameSerializer, CurrentPasswordSerializer): pass class SetUsernameRetypeSerializer(UsernameRetypeSerializer, CurrentPasswordSerializer): pass djoser-2.0.3/djoser/signals.py0000644000175000017500000000034213525262710017062 0ustar minderminder00000000000000from django.dispatch import Signal # New user has registered. user_registered = Signal(providing_args=["user", "request"]) # User has activated his or her account. user_activated = Signal(providing_args=["user", "request"]) djoser-2.0.3/djoser/social/0000755000175000017500000000000013530256235016324 5ustar minderminder00000000000000djoser-2.0.3/djoser/social/__init__.py0000644000175000017500000000000013513377611020426 0ustar minderminder00000000000000djoser-2.0.3/djoser/social/backends/0000755000175000017500000000000013530256235020076 5ustar minderminder00000000000000djoser-2.0.3/djoser/social/backends/__init__.py0000644000175000017500000000000013513377611022200 0ustar minderminder00000000000000djoser-2.0.3/djoser/social/backends/facebook.py0000644000175000017500000000020413513377611022220 0ustar minderminder00000000000000from social_core.backends.facebook import FacebookOAuth2 class FacebookOAuth2Override(FacebookOAuth2): REDIRECT_STATE = False djoser-2.0.3/djoser/social/serializers.py0000644000175000017500000000373613525262710021242 0ustar minderminder00000000000000from 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 access = serializers.CharField(read_only=True) refresh = 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 djoser-2.0.3/djoser/social/token/0000755000175000017500000000000013530256235017444 5ustar minderminder00000000000000djoser-2.0.3/djoser/social/token/__init__.py0000644000175000017500000000000013513377611021546 0ustar minderminder00000000000000djoser-2.0.3/djoser/social/token/jwt.py0000644000175000017500000000056713513401334020623 0ustar minderminder00000000000000class TokenStrategy: @classmethod def obtain(cls, user): from rest_framework_simplejwt.tokens import RefreshToken from django.utils.six import text_type refresh = RefreshToken.for_user(user) return { "access": text_type(refresh.access_token), "refresh": text_type(refresh), "user": user, } djoser-2.0.3/djoser/social/urls.py0000644000175000017500000000031713525262710017663 0ustar minderminder00000000000000from django.conf.urls import url from djoser.social import views urlpatterns = [ url( r"^o/(?P\S+)/$", views.ProviderAuthView.as_view(), name="provider-auth", ) ] djoser-2.0.3/djoser/social/views.py0000644000175000017500000000173713525262710020042 0ustar minderminder00000000000000from 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}) djoser-2.0.3/djoser/templates/0000755000175000017500000000000013530256235017050 5ustar minderminder00000000000000djoser-2.0.3/djoser/templates/email/0000755000175000017500000000000013530256235020137 5ustar minderminder00000000000000djoser-2.0.3/djoser/templates/email/activation.html0000644000175000017500000000176613513377611023203 0ustar minderminder00000000000000{% 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|safe }} {% 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|safe }}

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

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

{% endblock html_body %} djoser-2.0.3/djoser/templates/email/confirmation.html0000644000175000017500000000115013312447226023512 0ustar minderminder00000000000000{% 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 %} djoser-2.0.3/djoser/templates/email/password_changed_confirmation.html0000644000175000017500000000106513515647632027122 0ustar minderminder00000000000000{% load i18n %} {% block subject %} {% blocktrans %}{{ site_name }} - Your password has been successfully changed!{% endblocktrans %} {% endblock %} {% block text_body %} {% trans "Your password has been changed!" %} {% trans "Thanks for using our site!" %} {% blocktrans %}The {{ site_name }} team{% endblocktrans %} {% endblock text_body %} {% block html_body %}

{% trans "Your password has been changed!" %}

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

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

{% endblock html_body %} djoser-2.0.3/djoser/templates/email/password_reset.html0000644000175000017500000000226113312447226024072 0ustar minderminder00000000000000{% 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 %} djoser-2.0.3/djoser/templates/email/username_changed_confirmation.html0000644000175000017500000000106513515647632027077 0ustar minderminder00000000000000{% load i18n %} {% block subject %} {% blocktrans %}{{ site_name }} - Your username has been successfully changed!{% endblocktrans %} {% endblock %} {% block text_body %} {% trans "Your username has been changed!" %} {% trans "Thanks for using our site!" %} {% blocktrans %}The {{ site_name }} team{% endblocktrans %} {% endblock text_body %} {% block html_body %}

{% trans "Your username has been changed!" %}

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

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

{% endblock html_body %} djoser-2.0.3/djoser/templates/email/username_reset.html0000644000175000017500000000226113515647632024057 0ustar minderminder00000000000000{% load i18n %} {% block subject %} {% blocktrans %}Username reset on {{ site_name }}{% endblocktrans %} {% endblock subject %} {% block text_body %} {% blocktrans %}You're receiving this email because you requested a username reset for your user account at {{ site_name }}.{% endblocktrans %} {% trans "Please go to the following page and choose a new username:" %} {{ 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 username reset for your user account at {{ site_name }}.{% endblocktrans %}

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

{{ 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 %} djoser-2.0.3/djoser/urls/0000755000175000017500000000000013530256235016037 5ustar minderminder00000000000000djoser-2.0.3/djoser/urls/__init__.py0000644000175000017500000000007113513401334020137 0ustar minderminder00000000000000from .base import urlpatterns __all__ = ["urlpatterns"] djoser-2.0.3/djoser/urls/authtoken.py0000644000175000017500000000035113525262710020411 0ustar minderminder00000000000000from django.conf.urls import url from djoser import views urlpatterns = [ url(r"^token/login/?$", views.TokenCreateView.as_view(), name="login"), url(r"^token/logout/?$", views.TokenDestroyView.as_view(), name="logout"), ] djoser-2.0.3/djoser/urls/base.py0000644000175000017500000000036413525262710017325 0ustar minderminder00000000000000from django.contrib.auth import get_user_model from rest_framework.routers import DefaultRouter from djoser import views router = DefaultRouter() router.register("users", views.UserViewSet) User = get_user_model() urlpatterns = router.urls djoser-2.0.3/djoser/urls/jwt.py0000644000175000017500000000052313515647632017225 0ustar minderminder00000000000000from django.conf.urls import url from rest_framework_simplejwt import views urlpatterns = [ url(r"^jwt/create/?", views.TokenObtainPairView.as_view(), name="jwt-create"), url(r"^jwt/refresh/?", views.TokenRefreshView.as_view(), name="jwt-refresh"), url(r"^jwt/verify/?", views.TokenVerifyView.as_view(), name="jwt-verify"), ] djoser-2.0.3/djoser/utils.py0000644000175000017500000000225713525262710016571 0ustar minderminder00000000000000from django.contrib.auth import login, logout, user_logged_in, user_logged_out from django.utils.encoding import force_bytes, force_text from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode from djoser.conf import settings def encode_uid(pk): return force_text(urlsafe_base64_encode(force_bytes(pk))) def decode_uid(pk): return force_text(urlsafe_base64_decode(pk)) def login_user(request, user): token, _ = settings.TOKEN_MODEL.objects.get_or_create(user=user) if settings.CREATE_SESSION_ON_LOGIN: login(request, user) user_logged_in.send(sender=user.__class__, request=request, user=user) return token def logout_user(request): if settings.TOKEN_MODEL: settings.TOKEN_MODEL.objects.filter(user=request.user).delete() user_logged_out.send( sender=request.user.__class__, request=request, user=request.user ) if settings.CREATE_SESSION_ON_LOGIN: logout(request) class ActionViewMixin(object): def post(self, request, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) return self._action(serializer) djoser-2.0.3/djoser/views.py0000644000175000017500000003042713525771347016601 0ustar minderminder00000000000000from django.contrib.auth import get_user_model from django.contrib.auth.tokens import default_token_generator from django.utils.timezone import now from rest_framework import generics, status, views, viewsets from rest_framework.decorators import action from rest_framework.exceptions import NotFound from rest_framework.response import Response from djoser import signals, utils from djoser.compat import get_user_email from djoser.conf import settings User = get_user_model() class TokenCreateView(utils.ActionViewMixin, generics.GenericAPIView): """ Use this endpoint to obtain user authentication token. """ serializer_class = settings.SERIALIZERS.token_create permission_classes = settings.PERMISSIONS.token_create def _action(self, serializer): token = utils.login_user(self.request, serializer.user) token_serializer_class = settings.SERIALIZERS.token return Response( data=token_serializer_class(token).data, status=status.HTTP_200_OK ) class TokenDestroyView(views.APIView): """ Use this endpoint to logout user (remove user authentication token). """ permission_classes = settings.PERMISSIONS.token_destroy def post(self, request): utils.logout_user(request) return Response(status=status.HTTP_204_NO_CONTENT) class UserViewSet(viewsets.ModelViewSet): serializer_class = settings.SERIALIZERS.user queryset = User.objects.all() permission_classes = settings.PERMISSIONS.user token_generator = default_token_generator def permission_denied(self, request, message=None): if ( settings.HIDE_USERS and request.user.is_authenticated and self.action in ["update", "partial_update", "list", "retrieve"] ): raise NotFound() super().permission_denied(request, message=message) def get_queryset(self): user = self.request.user queryset = super().get_queryset() if settings.HIDE_USERS and self.action == "list" and not user.is_staff: queryset = queryset.filter(pk=user.pk) return queryset def get_permissions(self): if self.action == "create": self.permission_classes = settings.PERMISSIONS.user_create elif self.action == "activation": self.permission_classes = settings.PERMISSIONS.activation elif self.action == "resend_activation": self.permission_classes = settings.PERMISSIONS.password_reset elif self.action == "list": self.permission_classes = settings.PERMISSIONS.user_list elif self.action == "reset_password": self.permission_classes = settings.PERMISSIONS.password_reset elif self.action == "reset_password_confirm": self.permission_classes = settings.PERMISSIONS.password_reset_confirm elif self.action == "set_password": self.permission_classes = settings.PERMISSIONS.set_password elif self.action == "set_username": self.permission_classes = settings.PERMISSIONS.set_username elif self.action == "reset_username": self.permission_classes = settings.PERMISSIONS.username_reset elif self.action == "reset_username_confirm": self.permission_classes = settings.PERMISSIONS.username_reset_confirm elif self.action == "destroy" or ( self.action == "me" and self.request and self.request.method == "DELETE" ): self.permission_classes = settings.PERMISSIONS.user_delete return super().get_permissions() def get_serializer_class(self): if self.action == "create": if settings.USER_CREATE_PASSWORD_RETYPE: return settings.SERIALIZERS.user_create_password_retype return settings.SERIALIZERS.user_create elif self.action == "destroy" or ( self.action == "me" and self.request and self.request.method == "DELETE" ): return settings.SERIALIZERS.user_delete elif self.action == "activation": return settings.SERIALIZERS.activation elif self.action == "resend_activation": return settings.SERIALIZERS.password_reset elif self.action == "reset_password": return settings.SERIALIZERS.password_reset elif self.action == "reset_password_confirm": if settings.PASSWORD_RESET_CONFIRM_RETYPE: return settings.SERIALIZERS.password_reset_confirm_retype return settings.SERIALIZERS.password_reset_confirm elif self.action == "set_password": if settings.SET_PASSWORD_RETYPE: return settings.SERIALIZERS.set_password_retype return settings.SERIALIZERS.set_password elif self.action == "set_username": if settings.SET_USERNAME_RETYPE: return settings.SERIALIZERS.set_username_retype return settings.SERIALIZERS.set_username elif self.action == "reset_username": return settings.SERIALIZERS.username_reset elif self.action == "reset_username_confirm": if settings.USERNAME_RESET_CONFIRM_RETYPE: return settings.SERIALIZERS.username_reset_confirm_retype return settings.SERIALIZERS.username_reset_confirm elif self.action == "me": return settings.SERIALIZERS.current_user return self.serializer_class def get_instance(self): return self.request.user def perform_create(self, serializer): user = serializer.save() signals.user_registered.send( sender=self.__class__, user=user, request=self.request ) context = {"user": user} to = [get_user_email(user)] if settings.SEND_ACTIVATION_EMAIL: settings.EMAIL.activation(self.request, context).send(to) elif settings.SEND_CONFIRMATION_EMAIL: settings.EMAIL.confirmation(self.request, context).send(to) def perform_update(self, serializer): super().perform_update(serializer) user = serializer.instance # should we send activation email after update? if settings.SEND_ACTIVATION_EMAIL and not user.is_active: context = {"user": user} to = [get_user_email(user)] settings.EMAIL.activation(self.request, context).send(to) def destroy(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance, data=request.data) serializer.is_valid(raise_exception=True) if instance == request.user: utils.logout_user(self.request) self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT) @action(["get", "put", "patch", "delete"], detail=False) def me(self, request, *args, **kwargs): self.get_object = self.get_instance if request.method == "GET": return self.retrieve(request, *args, **kwargs) elif request.method == "PUT": return self.update(request, *args, **kwargs) elif request.method == "PATCH": return self.partial_update(request, *args, **kwargs) elif request.method == "DELETE": return self.destroy(request, *args, **kwargs) @action(["post"], detail=False) def activation(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.user user.is_active = True user.save() signals.user_activated.send( sender=self.__class__, user=user, request=self.request ) if settings.SEND_CONFIRMATION_EMAIL: context = {"user": user} to = [get_user_email(user)] settings.EMAIL.confirmation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False) def resend_activation(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.get_user(is_active=False) if not settings.SEND_ACTIVATION_EMAIL or not user: return Response(status=status.HTTP_400_BAD_REQUEST) context = {"user": user} to = [get_user_email(user)] settings.EMAIL.activation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False) def set_password(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.request.user.set_password(serializer.data["new_password"]) self.request.user.save() if settings.LOGOUT_ON_PASSWORD_CHANGE: utils.logout_user(self.request) if settings.PASSWORD_CHANGED_EMAIL_CONFIRMATION: context = {"user": self.request.user} to = [get_user_email(self.request.user)] settings.EMAIL.password_changed_confirmation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False) def reset_password(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.get_user() if user: context = {"user": user} to = [get_user_email(user)] settings.EMAIL.password_reset(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False) def reset_password_confirm(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.user.set_password(serializer.data["new_password"]) if hasattr(serializer.user, "last_login"): serializer.user.last_login = now() serializer.user.save() if settings.PASSWORD_CHANGED_EMAIL_CONFIRMATION: context = {"user": serializer.user} to = [get_user_email(serializer.user)] settings.EMAIL.password_changed_confirmation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False, url_path="set_{}".format(User.USERNAME_FIELD)) def set_username(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = self.request.user new_username = serializer.data["new_" + User.USERNAME_FIELD] setattr(user, User.USERNAME_FIELD, new_username) user.save() if settings.USERNAME_CHANGED_EMAIL_CONFIRMATION: context = {"user": user} to = [get_user_email(user)] settings.EMAIL.username_changed_confirmation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action(["post"], detail=False, url_path="reset_{}".format(User.USERNAME_FIELD)) def reset_username(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.get_user() if user: context = {"user": user} to = [get_user_email(user)] settings.EMAIL.username_reset(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) @action( ["post"], detail=False, url_path="reset_{}_confirm".format(User.USERNAME_FIELD) ) def reset_username_confirm(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) new_username = serializer.data["new_" + User.USERNAME_FIELD] setattr(serializer.user, User.USERNAME_FIELD, new_username) if hasattr(serializer.user, "last_login"): serializer.user.last_login = now() serializer.user.save() if settings.USERNAME_CHANGED_EMAIL_CONFIRMATION: context = {"user": serializer.user} to = [get_user_email(serializer.user)] settings.EMAIL.username_changed_confirmation(self.request, context).send(to) return Response(status=status.HTTP_204_NO_CONTENT) djoser-2.0.3/djoser.egg-info/0000755000175000017500000000000013530256235016544 5ustar minderminder00000000000000djoser-2.0.3/djoser.egg-info/PKG-INFO0000644000175000017500000001216113530256235017642 0ustar minderminder00000000000000Metadata-Version: 1.1 Name: djoser Version: 2.0.3 Summary: REST version of Django authentication system. Home-page: https://github.com/sunscrapers/djoser Author: SUNSCRAPERS Author-email: info@sunscrapers.com License: MIT Description: ====== djoser ====== .. image:: https://img.shields.io/pypi/v/djoser.svg :target: https://pypi.org/project/djoser .. image:: https://img.shields.io/travis/sunscrapers/djoser/master.svg :target: https://travis-ci.org/sunscrapers/djoser .. image:: https://img.shields.io/codecov/c/github/sunscrapers/djoser.svg :target: https://codecov.io/gh/sunscrapers/djoser .. image:: https://api.codacy.com/project/badge/Grade/c9bf80318d2741e5bb63912a5e0b32dc :alt: Codacy Badge :target: https://app.codacy.com/app/dekoza/djoser?utm_source=github.com&utm_medium=referral&utm_content=sunscrapers/djoser&utm_campaign=Badge_Grade_Dashboard 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 `_. Instead of reusing Django code (e.g. ``PasswordResetForm``), we reimplemented few things to fit better into `Single Page App `_ architecture. 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 (3.5, 3.6, 3.7, 3.8) - Django (1.11, 2.2) - Django REST Framework (3.9, 3.10) If you need to support other versions, please use djoser<2. 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 `https://djoser.readthedocs.io `_ and in ``docs`` directory. Contributing and development ============================ To start developing on **djoser**, clone the repository: .. code-block:: bash $ git clone git@github.com:sunscrapers/djoser.git If you are a **pipenv** user you can quickly setup testing environment by using Make commands: .. code-block:: bash $ make init $ make test Otherwise, if you cannot use Make commands, please create virtualenv and install requirements manually: .. code-block:: bash $ pip install django djangorestframework $ pip install -r requirements.txt .. code-block:: bash $ cd testproject $ ./manage.py test If you need to run tests against all supported Python and Django versions then invoke: .. code-block:: bash $ pip install tox $ tox -p all You can also play with test project by running following commands: .. code-block:: bash $ ./manage.py migrate $ ./manage.py runserver Similar projects ================ List of projects related to Django, REST and authentication: - `django-rest-framework-simplejwt `_ - `django-oauth-toolkit `_ - `django-rest-auth `_ - `django-rest-framework-digestauth `_ (not maintained) Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Framework :: Django Classifier: Framework :: Django :: 1.11 Classifier: Framework :: Django :: 2.2 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 djoser-2.0.3/djoser.egg-info/SOURCES.txt0000644000175000017500000000213313530256235020427 0ustar minderminder00000000000000LICENSE MANIFEST.in README.rst requirements.txt setup.cfg setup.py djoser/__init__.py djoser/compat.py djoser/conf.py djoser/constants.py djoser/email.py djoser/permissions.py djoser/serializers.py djoser/signals.py djoser/utils.py djoser/views.py 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/locale/ka/LC_MESSAGES/django.mo djoser/locale/pl/LC_MESSAGES/django.mo djoser/locale/ru_RU/LC_MESSAGES/django.mo 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_changed_confirmation.html djoser/templates/email/password_reset.html djoser/templates/email/username_changed_confirmation.html djoser/templates/email/username_reset.html djoser/urls/__init__.py djoser/urls/authtoken.py djoser/urls/base.py djoser/urls/jwt.pydjoser-2.0.3/djoser.egg-info/dependency_links.txt0000644000175000017500000000000113530256235022612 0ustar minderminder00000000000000 djoser-2.0.3/djoser.egg-info/requires.txt0000644000175000017500000000002613530256235021142 0ustar minderminder00000000000000django-templated-mail djoser-2.0.3/djoser.egg-info/top_level.txt0000644000175000017500000000011413530256235021272 0ustar minderminder00000000000000djoser djoser/social djoser/social/backends djoser/social/token djoser/urls djoser-2.0.3/requirements.txt0000644000175000017500000000033113515647632017055 0ustar minderminder00000000000000-e . django-templated-mail==1.1.1 djangorestframework-simplejwt==4.3.0 djet==0.2.2 social-auth-app-django==3.1.0 coverage==4.5.3 coreapi pytest==5.0.1 pytest-cov==2.7.1 pytest-django==3.5.1 pytest-pythonpath==0.7.3 djoser-2.0.3/setup.cfg0000644000175000017500000000014313530256235015403 0ustar minderminder00000000000000[compile_catalog] domain = django directory = djoser/locale [egg_info] tag_build = tag_date = 0 djoser-2.0.3/setup.py0000644000175000017500000000243413530255713015301 0ustar minderminder00000000000000#!/usr/bin/env python import os from setuptools import setup with open("README.rst", "r") as f: readme = f.read() def get_packages(package): return [ dirpath for dirpath, dirnames, filenames in os.walk(package) if os.path.exists(os.path.join(dirpath, "__init__.py")) ] setup( name="djoser", version="2.0.3", 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=["django-templated-mail"], setup_requires=["Babel>=2.6.0"], include_package_data=True, url="https://github.com/sunscrapers/djoser", classifiers=[ "Development Status :: 5 - Production/Stable", "Framework :: Django", "Framework :: Django :: 1.11", "Framework :: Django :: 2.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", ], )