mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2025-04-16 14:52:00 +03:00
Compare commits
No commits in common. "master" and "v0.8.1" have entirely different histories.
|
@ -1,21 +1,8 @@
|
||||||
[bdist_wheel]
|
# .coveragerc to control coverage.py
|
||||||
universal = 1
|
[run]
|
||||||
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
license_file = LICENSE
|
|
||||||
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 120
|
|
||||||
exclude = docs/*,demo/*
|
|
||||||
ignore = F403
|
|
||||||
|
|
||||||
|
|
||||||
[coverage:run]
|
|
||||||
omit=*site-packages*,*distutils*,*migrations*
|
omit=*site-packages*,*distutils*,*migrations*
|
||||||
|
|
||||||
[coverage:report]
|
[report]
|
||||||
# Regexes for lines to exclude from consideration
|
# Regexes for lines to exclude from consideration
|
||||||
exclude_lines =
|
exclude_lines =
|
||||||
# Have to re-enable the standard pragma
|
# Have to re-enable the standard pragma
|
||||||
|
@ -35,5 +22,5 @@ exclude_lines =
|
||||||
|
|
||||||
ignore_errors = True
|
ignore_errors = True
|
||||||
|
|
||||||
[coverage:html]
|
[html]
|
||||||
directory = coverage_html
|
directory = coverage_html
|
77
.gitignore
vendored
77
.gitignore
vendored
|
@ -1,35 +1,26 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
|
||||||
# Distribution / packaging
|
# Distribution / packaging
|
||||||
.Python
|
.Python
|
||||||
|
env/
|
||||||
|
bin/
|
||||||
build/
|
build/
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
downloads/
|
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
|
||||||
lib/
|
lib/
|
||||||
lib64/
|
lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
var/
|
var/
|
||||||
wheels/
|
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
# Installer logs
|
||||||
pip-log.txt
|
pip-log.txt
|
||||||
|
@ -39,66 +30,28 @@ pip-delete-this-directory.txt
|
||||||
htmlcov/
|
htmlcov/
|
||||||
.tox/
|
.tox/
|
||||||
.coverage
|
.coverage
|
||||||
.coverage.*
|
|
||||||
.cache
|
.cache
|
||||||
nosetests.xml
|
nosetests.xml
|
||||||
coverage.xml
|
coverage.xml
|
||||||
*.cover
|
coverage_html
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
|
|
||||||
# Translations
|
# Mr Developer
|
||||||
*.mo
|
.mr.developer.cfg
|
||||||
*.pot
|
.project
|
||||||
|
.pydevproject
|
||||||
|
|
||||||
|
# Rope
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
# Django stuff:
|
# Django stuff:
|
||||||
*.log
|
*.log
|
||||||
local_settings.py
|
*.pot
|
||||||
db.sqlite3
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
# PyBuilder
|
.DS_Store
|
||||||
target/
|
db.sqlite3
|
||||||
|
|
||||||
# Jupyter Notebook
|
# IntelliJ IDE files
|
||||||
.ipynb_checkpoints
|
.idea
|
||||||
|
|
||||||
# pyenv
|
|
||||||
.python-version
|
|
||||||
|
|
||||||
# celery beat schedule file
|
|
||||||
celerybeat-schedule
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
|
|
19
.travis.yml
19
.travis.yml
|
@ -2,25 +2,20 @@ language: python
|
||||||
python:
|
python:
|
||||||
- "2.7"
|
- "2.7"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
- "3.6"
|
|
||||||
env:
|
env:
|
||||||
- DJANGO=1.11.* DRF=3.7.*
|
- DJANGO=1.8.13
|
||||||
- DJANGO=1.11.* DRF=3.8.*
|
- DJANGO=1.9.7
|
||||||
- DJANGO=2.0.* DRF=3.7.*
|
|
||||||
- DJANGO=2.0.* DRF=3.8.*
|
|
||||||
install:
|
install:
|
||||||
- pip install -q Django==$DJANGO djangorestframework==$DRF
|
- pip install -q Django==$DJANGO --use-mirrors
|
||||||
- pip install coveralls
|
- pip install coveralls
|
||||||
- pip install -r rest_auth/tests/requirements.pip
|
- pip install -r rest_auth/tests/requirements.pip
|
||||||
|
matrix:
|
||||||
|
exclude:
|
||||||
|
- python: "3.5"
|
||||||
|
env: DJANGO=1.8.13
|
||||||
script:
|
script:
|
||||||
- coverage run --source=rest_auth setup.py test
|
- coverage run --source=rest_auth setup.py test
|
||||||
after_success:
|
after_success:
|
||||||
- coveralls
|
- coveralls
|
||||||
before_script:
|
before_script:
|
||||||
- flake8 . --config=flake8
|
- flake8 . --config=flake8
|
||||||
matrix:
|
|
||||||
exclude:
|
|
||||||
- python: "2.7"
|
|
||||||
env: DJANGO=2.0.* DRF=3.7.*
|
|
||||||
- python: "2.7"
|
|
||||||
env: DJANGO=2.0.* DRF=3.8.*
|
|
||||||
|
|
|
@ -2,4 +2,3 @@ include AUTHORS
|
||||||
include LICENSE
|
include LICENSE
|
||||||
include MANIFEST.in
|
include MANIFEST.in
|
||||||
include README.md
|
include README.md
|
||||||
graft rest_auth
|
|
||||||
|
|
12
README.rst
12
README.rst
|
@ -1,17 +1,11 @@
|
||||||
===========
|
|
||||||
Deprecated
|
|
||||||
===========
|
|
||||||
Please use https://github.com/iMerica/dj-rest-auth as this project is no longer maintained. Thanks!
|
|
||||||
|
|
||||||
|
|
||||||
Welcome to django-rest-auth
|
Welcome to django-rest-auth
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/Tivix/django-rest-auth.svg
|
.. image:: https://travis-ci.org/Tivix/django-rest-auth.png
|
||||||
:target: https://travis-ci.org/Tivix/django-rest-auth
|
:target: https://travis-ci.org/Tivix/django-rest-auth
|
||||||
|
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.svg
|
.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.png
|
||||||
:target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master
|
:target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,4 +28,4 @@ https://github.com/Tivix/django-rest-auth
|
||||||
|
|
||||||
Stack Overflow
|
Stack Overflow
|
||||||
-----------
|
-----------
|
||||||
http://stackoverflow.com/questions/tagged/django-rest-auth
|
http://stackoverflow.com/questions/tagged/django-rest-auth
|
|
@ -10,9 +10,9 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
import os
|
import os
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
||||||
|
|
||||||
|
@ -22,8 +22,19 @@ SECRET_KEY = 'ma3c@7uu!%e0=tynp+i6+q%$)9v@$t(eulqurym_b=48z82&5n'
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
|
TEMPLATE_DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
"django.core.context_processors.request",
|
||||||
|
|
||||||
|
# Disabling due to alluth>=0.21.0 changes
|
||||||
|
# "allauth.account.context_processors.account",
|
||||||
|
# "allauth.socialaccount.context_processors.socialaccount",
|
||||||
|
)
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
|
@ -44,25 +55,23 @@ INSTALLED_APPS = (
|
||||||
'rest_auth.registration',
|
'rest_auth.registration',
|
||||||
'allauth.socialaccount',
|
'allauth.socialaccount',
|
||||||
'allauth.socialaccount.providers.facebook',
|
'allauth.socialaccount.providers.facebook',
|
||||||
'rest_framework_swagger',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
)
|
)
|
||||||
|
|
||||||
# For backwards compatibility for Django 1.8
|
|
||||||
MIDDLEWARE_CLASSES = MIDDLEWARE
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'demo.urls'
|
ROOT_URLCONF = 'demo.urls'
|
||||||
|
|
||||||
WSGI_APPLICATION = 'demo.wsgi.application'
|
WSGI_APPLICATION = 'demo.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
|
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
|
||||||
|
|
||||||
|
@ -86,30 +95,15 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
# TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
|
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
|
||||||
|
|
||||||
TEMPLATES = [
|
REST_SESSION_LOGIN = False
|
||||||
{
|
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
||||||
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
|
|
||||||
'APP_DIRS': True,
|
|
||||||
'OPTIONS': {
|
|
||||||
'context_processors': [
|
|
||||||
'django.template.context_processors.debug',
|
|
||||||
'django.template.context_processors.request',
|
|
||||||
'django.contrib.auth.context_processors.auth',
|
|
||||||
'django.contrib.messages.context_processors.messages',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
REST_SESSION_LOGIN = True
|
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
SITE_ID = 1
|
SITE_ID = 1
|
||||||
ACCOUNT_EMAIL_REQUIRED = False
|
ACCOUNT_EMAIL_REQUIRED = False
|
||||||
|
@ -122,8 +116,3 @@ REST_FRAMEWORK = {
|
||||||
'rest_framework.authentication.TokenAuthentication',
|
'rest_framework.authentication.TokenAuthentication',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
SWAGGER_SETTINGS = {
|
|
||||||
'LOGIN_URL': 'login',
|
|
||||||
'LOGOUT_URL': 'logout',
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.views.generic import TemplateView, RedirectView
|
from django.views.generic import TemplateView, RedirectView
|
||||||
|
|
||||||
from rest_framework_swagger.views import get_swagger_view
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
|
url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
|
||||||
url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
|
url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
|
||||||
|
@ -38,7 +36,6 @@ urlpatterns = [
|
||||||
url(r'^rest-auth/', include('rest_auth.urls')),
|
url(r'^rest-auth/', include('rest_auth.urls')),
|
||||||
url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
|
url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
|
||||||
url(r'^account/', include('allauth.urls')),
|
url(r'^account/', include('allauth.urls')),
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'),
|
url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'),
|
||||||
url(r'^docs/$', get_swagger_view(title='API Docs'), name='api_docs')
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
django>=1.9.0
|
django>=1.8.0
|
||||||
django-rest-auth==0.9.5
|
django-rest-auth==0.8.1
|
||||||
djangorestframework>=3.7.0
|
|
||||||
django-allauth>=0.24.1
|
django-allauth>=0.24.1
|
||||||
six==1.9.0
|
six==1.9.0
|
||||||
django-rest-swagger==2.0.7
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<meta name="description" content="Django-rest-auth demo">
|
<meta name="description" content="Django-rest-auth demo">
|
||||||
<meta name="author" content="Tivix, Inc.">
|
<meta name="author" content="Tivix, Inc.">
|
||||||
|
|
||||||
<title>django-rest-auth demo</title>
|
<title>Starter Template for Bootstrap</title>
|
||||||
|
|
||||||
<!-- Latest compiled and minified CSS -->
|
<!-- Latest compiled and minified CSS -->
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
|
@ -60,7 +60,6 @@
|
||||||
<li class="active"><a href="/">Demo</a></li>
|
<li class="active"><a href="/">Demo</a></li>
|
||||||
<li><a target="_blank" href="http://django-rest-auth.readthedocs.org/en/latest/">Documentation</a></li>
|
<li><a target="_blank" href="http://django-rest-auth.readthedocs.org/en/latest/">Documentation</a></li>
|
||||||
<li><a target="_blank" href="https://github.com/Tivix/django-rest-auth">Source code</a></li>
|
<li><a target="_blank" href="https://github.com/Tivix/django-rest-auth">Source code</a></li>
|
||||||
<li><a target="_blank" href="{% url 'api_docs' %}">API Docs</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button type="submit" class="btn btn-default">Logout</button>
|
<button type="submit" class="btn btn-default">Login</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
--editable .
|
|
||||||
responses>=0.5.0
|
|
||||||
djangorestframework-jwt
|
|
||||||
django-allauth
|
|
|
@ -6,15 +6,16 @@ Basic
|
||||||
|
|
||||||
- /rest-auth/login/ (POST)
|
- /rest-auth/login/ (POST)
|
||||||
|
|
||||||
- username
|
- username (string)
|
||||||
- email
|
- email (string)
|
||||||
- password
|
- password (string)
|
||||||
|
|
||||||
Returns Token key
|
|
||||||
|
|
||||||
- /rest-auth/logout/ (POST)
|
- /rest-auth/logout/ (POST, GET)
|
||||||
|
|
||||||
.. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET - this is the exact same configuration from allauth. NOT recommended, see: http://django-allauth.readthedocs.io/en/latest/views.html#logout
|
.. note:: ``ACCOUNT_LOGOUT_ON_GET = True`` to allow logout using GET (this is the exact same conf from allauth)
|
||||||
|
|
||||||
|
- token
|
||||||
|
|
||||||
- /rest-auth/password/reset/ (POST)
|
- /rest-auth/password/reset/ (POST)
|
||||||
|
|
||||||
|
@ -35,16 +36,18 @@ Basic
|
||||||
- new_password2
|
- new_password2
|
||||||
- old_password
|
- old_password
|
||||||
|
|
||||||
|
|
||||||
.. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password.
|
.. note:: ``OLD_PASSWORD_FIELD_ENABLED = True`` to use old_password.
|
||||||
.. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change
|
.. note:: ``LOGOUT_ON_PASSWORD_CHANGE = False`` to keep the user logged in after password change
|
||||||
|
|
||||||
- /rest-auth/user/ (GET, PUT, PATCH)
|
- /rest-auth/user/ (GET)
|
||||||
|
|
||||||
|
- /rest-auth/user/ (PUT/PATCH)
|
||||||
|
|
||||||
- username
|
- username
|
||||||
- first_name
|
- first_name
|
||||||
- last_name
|
- last_name
|
||||||
|
- email
|
||||||
Returns pk, username, email, first_name, last_name
|
|
||||||
|
|
||||||
|
|
||||||
Registration
|
Registration
|
||||||
|
@ -72,8 +75,6 @@ Basing on example from installation section :doc:`Installation </installation>`
|
||||||
- access_token
|
- access_token
|
||||||
- code
|
- code
|
||||||
|
|
||||||
.. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/views.py
|
|
||||||
|
|
||||||
- /rest-auth/twitter/ (POST)
|
- /rest-auth/twitter/ (POST)
|
||||||
|
|
||||||
- access_token
|
- access_token
|
||||||
|
|
|
@ -1,54 +1,6 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
0.9.5
|
|
||||||
-----
|
|
||||||
- fixed package distribution issue
|
|
||||||
|
|
||||||
0.9.4
|
|
||||||
-----
|
|
||||||
- Compatibility fixes (#437, #506)
|
|
||||||
- JWT auth cookie fix (#345)
|
|
||||||
- config & packaging fixes
|
|
||||||
- updated docs
|
|
||||||
- added new translations (Czech, Chinese, Turkish, Korean)
|
|
||||||
|
|
||||||
0.9.3
|
|
||||||
-----
|
|
||||||
- added social connect views
|
|
||||||
- added check for pre-existing accounts in social login
|
|
||||||
- prevent double-validation in LoginSerializer
|
|
||||||
- unit tests and demo project changes for Django 2.0
|
|
||||||
|
|
||||||
0.9.2
|
|
||||||
-----
|
|
||||||
- added permission classes configuration for registration
|
|
||||||
- added more info to JWT docs
|
|
||||||
- added Polish translations
|
|
||||||
|
|
||||||
0.9.1
|
|
||||||
-----
|
|
||||||
- fixed import error when extending rest_auth serializers
|
|
||||||
- added sensitive fields decorator
|
|
||||||
- added Spanish translations
|
|
||||||
|
|
||||||
0.9.0
|
|
||||||
-----
|
|
||||||
- allowed using custom UserDetailsSerializer with JWTSerializer
|
|
||||||
- fixed error with logout on GET
|
|
||||||
- updated api endpoints and configuration docs
|
|
||||||
- bugfixes
|
|
||||||
- minor text fixes
|
|
||||||
|
|
||||||
0.8.2
|
|
||||||
-----
|
|
||||||
- fixed allauth import error
|
|
||||||
- added swagger docs to demo project
|
|
||||||
|
|
||||||
0.8.1
|
|
||||||
-----
|
|
||||||
- added support for django-allauth hmac email confirmation pattern
|
|
||||||
|
|
||||||
0.8.0
|
0.8.0
|
||||||
-----
|
-----
|
||||||
- added support for django-rest-framework-jwt
|
- added support for django-rest-framework-jwt
|
||||||
|
|
|
@ -44,16 +44,16 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'django-rest-auth'
|
project = u'django-rest-auth'
|
||||||
copyright = u'2018, Tivix Inc.'
|
copyright = u'2014, Tivix Inc.'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.9.5'
|
version = '0.3.0'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.9.5'
|
release = '0.3.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
|
@ -36,9 +36,7 @@ Configuration
|
||||||
You can define your custom serializers for registration endpoint.
|
You can define your custom serializers for registration endpoint.
|
||||||
Possible key values:
|
Possible key values:
|
||||||
|
|
||||||
- REGISTER_SERIALIZER - serializer class in ``rest_auth.registration.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer``
|
- REGISTER_SERIALIZER - serializer class in ``rest_auth.register.views.RegisterView``, default value ``rest_auth.registration.serializers.RegisterSerializer``
|
||||||
|
|
||||||
.. note:: The custom REGISTER_SERIALIZER must define a ``def save(self, request)`` method that returns a user model instance
|
|
||||||
|
|
||||||
- **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models``
|
- **REST_AUTH_TOKEN_MODEL** - model class for tokens, default value ``rest_framework.authtoken.models``
|
||||||
|
|
||||||
|
@ -51,3 +49,20 @@ Configuration
|
||||||
- **OLD_PASSWORD_FIELD_ENABLED** - set it to True if you want to have old password verification on password change enpoint (default: False)
|
- **OLD_PASSWORD_FIELD_ENABLED** - set it to True if you want to have old password verification on password change enpoint (default: False)
|
||||||
|
|
||||||
- **LOGOUT_ON_PASSWORD_CHANGE** - set to False if you want to keep the current user logged in after a password change
|
- **LOGOUT_ON_PASSWORD_CHANGE** - set to False if you want to keep the current user logged in after a password change
|
||||||
|
|
||||||
|
|
||||||
|
Throttling
|
||||||
|
=============
|
||||||
|
|
||||||
|
You may specify custom throttling for ``rest_auth.register.views.RegisterView`` by specifying DRF settings:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
'DEFAULT_THROTTLE_RATES': {
|
||||||
|
'anon': '6/m',
|
||||||
|
'register_view':'1/h',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,14 @@ FAQ
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
url(r'^account-confirm-email/(?P<key>[-:\w]+)/$', TemplateView.as_view(),
|
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||||
name='account_confirm_email'),
|
name='account_confirm_email'),
|
||||||
|
|
||||||
This url is used by django-allauth. Empty TemplateView is defined just to allow reverse() call inside app - when email with verification link is being sent.
|
This url is used by django-allauth. Empty TemplateView is defined just to allow reverse() call inside app - when email with verification link is being sent.
|
||||||
|
|
||||||
You should override this view/url to handle it in your API client somehow and then, send post to /verify-email/ endpoint with proper key.
|
You should override this view/url to handle it in your API client somehow and then, send post to /verify-email/ endpoint with proper key.
|
||||||
If you don't want to use API on that step, then just use ConfirmEmailView view from:
|
If you don't want to use API on that step, then just use ConfirmEmailView view from:
|
||||||
django-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py
|
djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
||||||
|
|
||||||
|
|
||||||
2. I get an error: Reverse for 'password_reset_confirm' not found.
|
2. I get an error: Reverse for 'password_reset_confirm' not found.
|
||||||
|
|
|
@ -26,18 +26,12 @@ Installation
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = patterns('',
|
||||||
...,
|
...,
|
||||||
url(r'^rest-auth/', include('rest_auth.urls'))
|
url(r'^rest-auth/', include('rest_auth.urls'))
|
||||||
]
|
)
|
||||||
|
|
||||||
4. Migrate your database
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
|
|
||||||
You're good to go now!
|
You're good to go now!
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,11 +60,11 @@ Registration (optional)
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = patterns('',
|
||||||
...,
|
...,
|
||||||
url(r'^rest-auth/', include('rest_auth.urls')),
|
url(r'^rest-auth/', include('rest_auth.urls')),
|
||||||
url(r'^rest-auth/registration/', include('rest_auth.registration.urls'))
|
url(r'^rest-auth/registration/', include('rest_auth.registration.urls'))
|
||||||
]
|
)
|
||||||
|
|
||||||
|
|
||||||
Social Authentication (optional)
|
Social Authentication (optional)
|
||||||
|
@ -120,10 +114,10 @@ Facebook
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
urlpatterns += [
|
urlpatterns += patterns('',
|
||||||
...,
|
...,
|
||||||
url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login')
|
url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login')
|
||||||
]
|
)
|
||||||
|
|
||||||
|
|
||||||
Twitter
|
Twitter
|
||||||
|
@ -131,15 +125,15 @@ Twitter
|
||||||
|
|
||||||
If you are using Twitter for your social authentication, it is a bit different since Twitter uses OAuth 1.0.
|
If you are using Twitter for your social authentication, it is a bit different since Twitter uses OAuth 1.0.
|
||||||
|
|
||||||
3. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute:
|
3. Create new view as a subclass of ``rest_auth.views.LoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
||||||
from rest_auth.registration.views import SocialLoginView
|
from rest_auth.views import LoginView
|
||||||
from rest_auth.social_serializers import TwitterLoginSerializer
|
from rest_auth.social_serializers import TwitterLoginSerializer
|
||||||
|
|
||||||
class TwitterLogin(SocialLoginView):
|
class TwitterLogin(LoginView):
|
||||||
serializer_class = TwitterLoginSerializer
|
serializer_class = TwitterLoginSerializer
|
||||||
adapter_class = TwitterOAuthAdapter
|
adapter_class = TwitterOAuthAdapter
|
||||||
|
|
||||||
|
@ -147,114 +141,23 @@ If you are using Twitter for your social authentication, it is a bit different s
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
urlpatterns += [
|
urlpatterns += patterns('',
|
||||||
...,
|
...,
|
||||||
url(r'^rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login')
|
url(r'^rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login')
|
||||||
]
|
)
|
||||||
|
|
||||||
.. note:: Starting from v0.21.0, django-allauth has dropped support for context processors. Check out http://django-allauth.readthedocs.org/en/latest/changelog.html#from-0-21-0 for more details.
|
.. note:: Starting from v0.21.0, django-allauth has dropped support for context processors. Check out http://django-allauth.readthedocs.org/en/latest/changelog.html#from-0-21-0 for more details.
|
||||||
|
|
||||||
|
|
||||||
GitHub
|
JWT Support (optional)
|
||||||
######
|
----------------------
|
||||||
|
|
||||||
If you are using GitHub for your social authentication, it uses code and not AccessToken directly.
|
By default, ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, you need to install the following:
|
||||||
|
|
||||||
3. Create new view as a subclass of ``rest_auth.views.SocialLoginView`` with ``GitHubOAuth2Adapter`` adapter, an ``OAuth2Client`` and a callback_url as attributes:
|
1. Install ``django-rest-framework-jwt`` http://getblimp.github.io/django-rest-framework-jwt/ . Right now this is the only supported JWT library.
|
||||||
|
|
||||||
.. code-block:: python
|
2. Add the following to your settings
|
||||||
|
|
||||||
from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter
|
|
||||||
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
|
|
||||||
from rest_auth.registration.views import SocialLoginView
|
|
||||||
|
|
||||||
class GithubLogin(SocialLoginView):
|
|
||||||
adapter_class = GitHubOAuth2Adapter
|
|
||||||
callback_url = CALLBACK_URL_YOU_SET_ON_GITHUB
|
|
||||||
client_class = OAuth2Client
|
|
||||||
|
|
||||||
4. Create url for GitHubLogin view:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
urlpatterns += [
|
|
||||||
...,
|
|
||||||
url(r'^rest-auth/github/$', GitHubLogin.as_view(), name='github_login')
|
|
||||||
]
|
|
||||||
|
|
||||||
Additional Social Connect Views
|
|
||||||
###############################
|
|
||||||
|
|
||||||
If you want to allow connecting existing accounts in addition to login, you can use connect views:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
|
|
||||||
from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter
|
|
||||||
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
|
||||||
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
|
|
||||||
from rest_auth.registration.views import SocialConnectView
|
|
||||||
from rest_auth.social_serializers import TwitterConnectSerializer
|
|
||||||
|
|
||||||
class FacebookConnect(SocialConnectView):
|
|
||||||
adapter_class = FacebookOAuth2Adapter
|
|
||||||
|
|
||||||
class TwitterConnect(SocialConnectView):
|
|
||||||
serializer_class = TwitterConnectSerializer
|
|
||||||
adapter_class = TwitterOAuthAdapter
|
|
||||||
|
|
||||||
class GithubConnect(SocialConnectView):
|
|
||||||
adapter_class = GitHubOAuth2Adapter
|
|
||||||
callback_url = CALLBACK_URL_YOU_SET_ON_GITHUB
|
|
||||||
client_class = OAuth2Client
|
|
||||||
|
|
||||||
|
|
||||||
In urls.py:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
urlpatterns += [
|
|
||||||
...,
|
|
||||||
url(r'^rest-auth/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect')
|
|
||||||
url(r'^rest-auth/twitter/connect/$', TwitterConnect.as_view(), name='twitter_connect')
|
|
||||||
url(r'^rest-auth/github/connect/$', GithubConnect.as_view(), name='github_connect')
|
|
||||||
]
|
|
||||||
|
|
||||||
You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from rest_auth.registration.views import (
|
|
||||||
SocialAccountListView, SocialAccountDisconnectView
|
|
||||||
)
|
|
||||||
|
|
||||||
urlpatterns += [
|
|
||||||
...,
|
|
||||||
url(
|
|
||||||
r'^socialaccounts/$',
|
|
||||||
SocialAccountListView.as_view(),
|
|
||||||
name='social_account_list'
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r'^socialaccounts/(?P<pk>\d+)/disconnect/$',
|
|
||||||
SocialAccountDisconnectView.as_view(),
|
|
||||||
name='social_account_disconnect'
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
JSON Web Token (JWT) Support (optional)
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
By default ``django-rest-auth`` uses Django's Token-based authentication. If you want to use JWT authentication, follow these steps:
|
|
||||||
|
|
||||||
1. Install `djangorestframework-jwt <http://getblimp.github.io/django-rest-framework-jwt/>`_
|
|
||||||
- ``djangorestframework-jwt`` is currently the only supported JWT library.
|
|
||||||
2. The ``JWT_PAYLOAD_HANDLER`` and ``JWT_ENCODE_HANDLER`` settings are imported from the ``django-rest-framework-jwt`` settings object.
|
|
||||||
- Refer to `the library's documentation <http://getblimp.github.io/django-rest-framework-jwt/#additional-settings>`_ for information on using different encoders.
|
|
||||||
|
|
||||||
3. Add the following configuration value to your settings file to enable JWT authentication.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
REST_USE_JWT = True
|
REST_USE_JWT = True
|
||||||
|
|
||||||
|
|
4
flake8
Normal file
4
flake8
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 160
|
||||||
|
exclude = docs/*,demo/*
|
||||||
|
ignore = F403
|
Binary file not shown.
|
@ -1,102 +0,0 @@
|
||||||
# Czech translations of Tivix/django-rest-auth
|
|
||||||
#
|
|
||||||
# This file is distributed under the same license as the Tivix/django-rest-auth package.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: Tivix/django-rest-auth\n"
|
|
||||||
"Report-Msgid-Bugs-To: https://github.com/Tivix/django-rest-auth/issues\n"
|
|
||||||
"POT-Creation-Date: 2018-06-27 23:05+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-06-27 23:22+0200\n"
|
|
||||||
"Language: cs\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
|
||||||
"Last-Translator: Václav Dohnal <vaclav.dohnal@gmail.com>\n"
|
|
||||||
"Language-Team: N/A\n"
|
|
||||||
"X-Generator: Poedit 2.0.8\n"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:67
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "View není definováno, předejte jej jako proměnnou kontextu"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:72
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Definujte adapter_class ve view"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:91
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Definujte callback_url ve view"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:95
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Definujte client_class ve view"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:116
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Nesprávný vstup. access_token je povinný."
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:125
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Nesprávná hodnota"
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:139
|
|
||||||
msgid "User is already registered with this e-mail address."
|
|
||||||
msgstr "Uživatel s touto adresou je již registrován."
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:185
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Uživatel s touto adresou je již registrován."
|
|
||||||
|
|
||||||
#: .\registration\serializers.py:193
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Zadaná hesla se neshodují."
|
|
||||||
|
|
||||||
#: .\registration\views.py:51
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "Ověřovací e-mail odeslán."
|
|
||||||
|
|
||||||
#: .\registration\views.py:98
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "ok"
|
|
||||||
|
|
||||||
#: .\serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Musí obsahovat \"e-mail\" a \"heslo\"."
|
|
||||||
|
|
||||||
#: .\serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Musí obsahovat \"uživatelské jméno\" a \"heslo\"."
|
|
||||||
|
|
||||||
#: .\serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Musí obsahovat \"uživatelské jméno\" nebo \"e-mail\" a \"heslo\"."
|
|
||||||
|
|
||||||
#: .\serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Uživatelský účet je zakázán."
|
|
||||||
|
|
||||||
#: .\serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Pomocí zadaných údajů se nelze přihlásit."
|
|
||||||
|
|
||||||
#: .\serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "E-mail není ověřený."
|
|
||||||
|
|
||||||
#: .\views.py:127
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Byli jste úspěšně odhlášeni."
|
|
||||||
|
|
||||||
#: .\views.py:175
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "E-mail pro resetování hesla byl odeslán."
|
|
||||||
|
|
||||||
#: .\views.py:201
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Vaše heslo bylo resetováno."
|
|
||||||
|
|
||||||
#: .\views.py:223
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Nové heslo bylo uloženo."
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
"POT-Creation-Date: 2016-02-02 14:11+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -18,19 +18,19 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
#: registration/serializers.py:54
|
||||||
msgid "View is not defined, pass it as a context variable"
|
msgid "View is not defined, pass it as a context variable"
|
||||||
msgstr "\"View\" ist nicht definiert, übergib es als Contextvariable"
|
msgstr "\"View\" ist nicht definiert, übergib es als Contextvariable"
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
#: registration/serializers.py:59
|
||||||
msgid "Define adapter_class in view"
|
msgid "Define adapter_class in view"
|
||||||
msgstr "Definier \"adapter_class\" in view"
|
msgstr "Definier \"adapter_class\" in view"
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
#: registration/serializers.py:78
|
||||||
msgid "Define callback_url in view"
|
msgid "Define callback_url in view"
|
||||||
msgstr "Definier \"callback_url\" in view"
|
msgstr "Definier \"callback_url\" in view"
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
#: registration/serializers.py:82
|
||||||
msgid "Define client_class in view"
|
msgid "Define client_class in view"
|
||||||
msgstr "Definier \"client_class\" in view"
|
msgstr "Definier \"client_class\" in view"
|
||||||
|
|
||||||
|
@ -50,49 +50,50 @@ msgstr "Ein User mit dieser E-Mail Adresse ist schon registriert."
|
||||||
msgid "The two password fields didn't match."
|
msgid "The two password fields didn't match."
|
||||||
msgstr "Die beiden Passwörter sind nicht identisch."
|
msgstr "Die beiden Passwörter sind nicht identisch."
|
||||||
|
|
||||||
#: registration/views.py:91
|
#: registration/views.py:64
|
||||||
msgid "ok"
|
msgid "ok"
|
||||||
msgstr "Ok"
|
msgstr "Ok"
|
||||||
|
|
||||||
#: serializers.py:30
|
#: serializers.py:29
|
||||||
msgid "Must include \"email\" and \"password\"."
|
msgid "Must include \"email\" and \"password\"."
|
||||||
msgstr "Muss \"email\" und \"password\" enthalten."
|
msgstr "Muss \"email\" und \"password\" enthalten."
|
||||||
|
|
||||||
#: serializers.py:41
|
#: serializers.py:40
|
||||||
msgid "Must include \"username\" and \"password\"."
|
msgid "Must include \"username\" and \"password\"."
|
||||||
msgstr "Muss \"username\" und \"password\" enthalten."
|
msgstr "Muss \"username\" und \"password\" enthalten."
|
||||||
|
|
||||||
#: serializers.py:54
|
#: serializers.py:53
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
||||||
msgstr "Muss entweder \"username\" oder \"email\" und password \"password\""
|
msgstr "Muss entweder \"username\" oder \"email\" und password \"password\""
|
||||||
|
|
||||||
#: serializers.py:95
|
#: serializers.py:94
|
||||||
msgid "User account is disabled."
|
msgid "User account is disabled."
|
||||||
msgstr "Der Useraccount ist deaktiviert."
|
msgstr "Der Useraccount ist deaktiviert."
|
||||||
|
|
||||||
#: serializers.py:98
|
#: serializers.py:97
|
||||||
msgid "Unable to log in with provided credentials."
|
msgid "Unable to log in with provided credentials."
|
||||||
msgstr "Kann nicht mit den angegeben Zugangsdaten anmelden."
|
msgstr "Kann nicht mit den angegeben Zugangsdaten anmelden."
|
||||||
|
|
||||||
#: serializers.py:107
|
#: serializers.py:106
|
||||||
msgid "E-mail is not verified."
|
msgid "E-mail is not verified."
|
||||||
msgstr "E-Mail Adresse ist nicht verifiziert."
|
msgstr "E-Mail Adresse ist nicht verifiziert."
|
||||||
|
|
||||||
#: views.py:126
|
#: serializers.py:152
|
||||||
|
msgid "Error"
|
||||||
|
msgstr "Fehler"
|
||||||
|
|
||||||
|
#: views.py:71
|
||||||
msgid "Successfully logged out."
|
msgid "Successfully logged out."
|
||||||
msgstr "Erfolgreich ausgeloggt."
|
msgstr "Erfolgreich ausgeloggt."
|
||||||
|
|
||||||
#: views.py:174
|
#: views.py:111
|
||||||
msgid "Password reset e-mail has been sent."
|
msgid "Password reset e-mail has been sent."
|
||||||
msgstr "Die E-Mail zum Zurücksetzen des Passwortes wurde verschickt."
|
msgstr "Die E-Mail zum Zurücksetzen des Passwortes wurde verschickt."
|
||||||
|
|
||||||
#: views.py:200
|
#: views.py:132
|
||||||
msgid "Password has been reset with the new password."
|
msgid "Password has been reset with the new password."
|
||||||
msgstr "Das Passwort wurde mit dem neuen Passwort ersetzt."
|
msgstr "Das Passwort wurde mit dem neuen Passwort ersetzt."
|
||||||
|
|
||||||
#: views.py:222
|
#: views.py:150
|
||||||
msgid "New password has been saved."
|
msgid "New password has been saved."
|
||||||
msgstr "Das neue Passwort wurde gespeichert."
|
msgstr "Das neue Passwort wurde gespeichert."
|
||||||
|
|
||||||
#~ msgid "Error"
|
|
||||||
#~ msgstr "Fehler"
|
|
||||||
|
|
Binary file not shown.
|
@ -1,99 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: Carlos de las Heras <cahersan@gmail.com>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "\"View\" no está definida, pásala como una variable de contexto"
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Defina \"adapter_class\" en view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Defina \"callback_url\" en view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Defina \"client_class\" en view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Entrada incorrecta. Se requiere \"access_token\" o \"code\"."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Valor incorrecto"
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Ya existe un usuario registrado con esa dirección de correo electrónico."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Las contraseñas no coinciden"
|
|
||||||
|
|
||||||
#: registration/views.py:44
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "Se ha enviado un correo de verificación."
|
|
||||||
|
|
||||||
#: registration/views.py:91
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "Ok"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Debe incluir \"correo electrónico\" y \"contraseña\"."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Debe incluir \"nombre de usuario\" y \"contraseña\"."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Debe incluir \"nombre de usuario\" o \"correo electrónico\" y \"contraseña\"."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Cuenta de usuario deshabilitada"
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "No puede iniciar sesión con las credenciales proporcionadas."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "El correo electrónico no ha sido verificado."
|
|
||||||
|
|
||||||
#: views.py:126
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Sesión cerrada con éxito."
|
|
||||||
|
|
||||||
#: views.py:174
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "Se ha enviado un correo electrónico para restablecer la contraseña."
|
|
||||||
|
|
||||||
#: views.py:200
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "La contraseña ha sido restablecida con la nueva contraseña."
|
|
||||||
|
|
||||||
#: views.py:222
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "La nueva contraseña ha sido guardada."
|
|
Binary file not shown.
|
@ -1,98 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2016-12-22 11:37-0800\n"
|
|
||||||
"PO-Revision-Date: 2017-02-14 13:27+0100\n"
|
|
||||||
"Language: fr\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"X-Generator: Poedit 1.8.11\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "La “View” n’est pas définie, passez la en variable contextuelle"
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Définissez “adapter_class” dans la vue"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Définissez “callback_url” dans la vue"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Définissez “client_class” dans la vue"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Paramètres incorrects. Il faut “access_token” ou “code”."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Paramètre incorrect"
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Un utilisateur existe déjà avec cette adresse email."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Les deux mots de passes ne sont pas les mêmes."
|
|
||||||
|
|
||||||
#: registration/views.py:82
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "Ok"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Doit inclure “email” et “password”."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Doit inclure “username” et “password”."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Doit inclure un “username” ou “email”, et un “password”."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Le compte utilisateur est désactivé."
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Connexion impossible avec les informations fournies."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "L’adresse email n’a pas été vérifiée."
|
|
||||||
|
|
||||||
#: views.py:114
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Déconnexion effectuée avec succès."
|
|
||||||
|
|
||||||
#: views.py:162
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "L’email de réinitialisation du mot de passe a été envoyé."
|
|
||||||
|
|
||||||
#: views.py:184
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Le mot de passe a été réinitialisé."
|
|
||||||
|
|
||||||
#: views.py:202
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Le nouveau mot de passe est sauvé."
|
|
||||||
|
|
||||||
#~ msgid "Error"
|
|
||||||
#~ msgstr "Fehler"
|
|
Binary file not shown.
|
@ -1,99 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
|
||||||
"PO-Revision-Date: 2018-03-20 17:52+0900\n"
|
|
||||||
"Last-Translator: Jeonsgoo Park <toracle@gmail.com>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: ko\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "View가 정의되지 않았습니다. 컨텍스트 변수에 포함해주세요"
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "view에 adapter_class를 정의하세요"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "view에 callback_url을 정의하세요"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "view에 client_class를 정의하세요"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "올바르지 않은 입력입니다. access_token이나 code가 필요합니다."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "올바르지 않은 값"
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "이미 이 이메일 주소로 등록된 사용자가 있습니다."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "두 개의 패스워드 필드가 서로 맞지 않습니다."
|
|
||||||
|
|
||||||
#: registration/views.py:44
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "확인 이메일을 발송했습니다."
|
|
||||||
|
|
||||||
#: registration/views.py:91
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "ok"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "\"email\"과 \"password\"를 반드시 포함해야 합니다."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "\"username\"과 \"password\"를 반드시 포함해야 합니다."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "\"username\"이나 \"email\", 그리고 \"password\"를 반드시 포함해야 합니다."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "사용자 계정이 비활성화 되어있습니다."
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "주어진 자격 증명으로 로그인이 불가능합니다."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "이메일 주소가 확인되지 않았습니다."
|
|
||||||
|
|
||||||
#: views.py:126
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "로그아웃되었습니다."
|
|
||||||
|
|
||||||
#: views.py:174
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "패스워드 초기화 이메일이 발송되었습니다."
|
|
||||||
|
|
||||||
#: views.py:200
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "새로운 패스워드로 패스워드가 초기화 되었습니다."
|
|
||||||
|
|
||||||
#: views.py:222
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "새로운 패스워드가 저장되었습니다."
|
|
Binary file not shown.
|
@ -1,99 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
|
||||||
"PO-Revision-Date: 2017-03-11 12:10+0100\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"X-Generator: Poedit 1.8.11\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language: pl\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "Widok nie został zdefiniowany, przekaż go przez zmienną \"context\""
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Zdefiniuj \"adapter_class\" w widoku"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Zdefiniuj \"callback_url\" w widoku"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Zdefiniuj \"client_class\" w widoku"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Podano błędne dane. \"access_token\" lub \"code\" są wymagne."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Niepoprawna wartość."
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Istnieje już użytkownik z takim adresem email."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Hasła nie są identyczne."
|
|
||||||
|
|
||||||
#: registration/views.py:44
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "Email weryfikacyjny został wysłany."
|
|
||||||
|
|
||||||
#: registration/views.py:91
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "ok"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Musisz podać email i hasło."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Musisz podać nazwę użytkownika i hasło."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Musisz podać nazwę użytkownika (lub email) i hasło."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Konto użytkownika zostało wyłączone."
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Podane dane do logowania są niepoprawne."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "Email nie został zweryfikowany."
|
|
||||||
|
|
||||||
#: views.py:126
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Wylogowano."
|
|
||||||
|
|
||||||
#: views.py:174
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "Email z linkiem do resetu hasła został wysłany."
|
|
||||||
|
|
||||||
#: views.py:200
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Hasło zostało zresetowane."
|
|
||||||
|
|
||||||
#: views.py:222
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Nowe hasło zostało zapisane."
|
|
|
@ -1,99 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# Bruno Barreto Freitas <brunobarretofreitas@outlook.com>, 2019.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2019-04-16 09:48-0800\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: Bruno Barreto Freitas <brunobarretofreitas@outlook.com>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "\"View\" não está definida, passe-a como uma variável de contexto"
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Defina \"adapter_class\" na view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Defina \"callback_url\" na view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Defina \"client_class\" na view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Entrada incorreta. \"access_token\" ou \"code\" são obrigatórios."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Valor incorreto"
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Já existe um usuário cadastrado com este endereço de e-mail."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Os dois campos de senha não correspondem."
|
|
||||||
|
|
||||||
#: registration/views.py:44
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "E-mail de verificação enviado."
|
|
||||||
|
|
||||||
#: registration/views.py:91
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "Ok"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Deve-se incluir \"email\" e \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Deve-se incluir \"username\" e \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Deve-se incluir \"username\" ou \"email\" e \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Conta de usuário está desativada"
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Não foi possível realizar o login com as credenciais fornecidas."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "E-mail não foi verificado."
|
|
||||||
|
|
||||||
#: views.py:126
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Logout realizado com sucesso."
|
|
||||||
|
|
||||||
#: views.py:174
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "E-mail de redefinição de senha foi enviado."
|
|
||||||
|
|
||||||
#: views.py:200
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Senha foi redefinida com a nova senha."
|
|
||||||
|
|
||||||
#: views.py:222
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Nova senha foi salva com sucesso."
|
|
Binary file not shown.
|
@ -1,101 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
|
||||||
"PO-Revision-Date: 2016-08-01 07:48+0300\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: ru\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
|
||||||
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
|
|
||||||
"%100>=11 && n%100<=14)? 2 : 3);\n"
|
|
||||||
"X-Generator: Poedit 1.8.5\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:53
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "View неизвестен, передайте его как переменную контекста"
|
|
||||||
|
|
||||||
#: registration/serializers.py:58
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "Установите adapter_class в view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:77
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "Установите callback_url в view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:81
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "Установите client_class в view"
|
|
||||||
|
|
||||||
#: registration/serializers.py:102
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Некорректный ввод. Необходим access_token или code."
|
|
||||||
|
|
||||||
#: registration/serializers.py:111
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Некорректное значение"
|
|
||||||
|
|
||||||
#: registration/serializers.py:140
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Пользователь с таким e-mail адресом уже зарегистрирован."
|
|
||||||
|
|
||||||
#: registration/serializers.py:148
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "Пароли не совпадают."
|
|
||||||
|
|
||||||
#: registration/views.py:44
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "Письмо с подтверждением выслано."
|
|
||||||
|
|
||||||
#: registration/views.py:91
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "ок"
|
|
||||||
|
|
||||||
#: serializers.py:30
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "Должно включать \"email\" и \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:41
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "Должно включать \"username\" и \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:54
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Должно включать либо \"username\" либо \"email\" и \"password\"."
|
|
||||||
|
|
||||||
#: serializers.py:95
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Пользовательский аккаунт отключён."
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Невозможно войти в систему с указанными учётными данными."
|
|
||||||
|
|
||||||
#: serializers.py:107
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "E-mail не подтверждён."
|
|
||||||
|
|
||||||
#: views.py:126
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Успешно вышли."
|
|
||||||
|
|
||||||
#: views.py:174
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "Письмо с инструкциями по восстановлению пароля выслано."
|
|
||||||
|
|
||||||
#: views.py:200
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Пароль изменён на новый."
|
|
||||||
|
|
||||||
#: views.py:222
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Новый пароль сохранён."
|
|
|
@ -1,95 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2017-03-05 21:56-0800\n"
|
|
||||||
"PO-Revision-Date: 2018-10-13 19:37+0300\n"
|
|
||||||
"Language: tr\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"X-Generator: Poedit 2.2\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:67
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "“View” tanımlanmadı, “context” değişkeni olarak tanımla"
|
|
||||||
|
|
||||||
#: registration/serializers.py:72
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "“view” içerisinde “adapter_class” tanımla"
|
|
||||||
|
|
||||||
#: registration/serializers.py:91
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "“view” içerisinde “callback_url” tanımla"
|
|
||||||
|
|
||||||
#: registration/serializers.py:95
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "“view” içerisinde “client_class” tanımla"
|
|
||||||
|
|
||||||
#: registration/serializers.py:116
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "Geçersiz girdi. “access_token” veya “code” gerekli."
|
|
||||||
|
|
||||||
#: registration/serializers.py:125
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "Geçersiz değer"
|
|
||||||
|
|
||||||
#: registration/serializers.py:185
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "Bu e-posta adresi ile bir kullanıcı zaten kayıt olmuştu."
|
|
||||||
|
|
||||||
#: registration/serializers.py:193
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "İki şifre alanı eşleşmiyor."
|
|
||||||
|
|
||||||
#: registration/views.py:98
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "tamam"
|
|
||||||
|
|
||||||
#: serializers.py:33
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "\"email\" ve \"password\" içermelidir."
|
|
||||||
|
|
||||||
#: serializers.py:44
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "“username\" und \"password\" içermelidir."
|
|
||||||
|
|
||||||
#: serializers.py:57
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "Ya ”username\" yada \"email\" ve \"password\" içermelidir."
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "Kullanıcı hesap pasiftir."
|
|
||||||
|
|
||||||
#: serializers.py:101
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "Sağlanan kimlik bilgileri ile giriş yapılamıyor."
|
|
||||||
|
|
||||||
#: serializers.py:110
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "E-posta adresi doğrulanmadı."
|
|
||||||
|
|
||||||
#: views.py:127
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "Başarılı bir şekilde çıkış yapıldı."
|
|
||||||
|
|
||||||
#: views.py:175
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "Şifre sıfırlama e-postası gönderildi."
|
|
||||||
|
|
||||||
#: views.py:201
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "Yeni şifre ile şifre sıfırlandı."
|
|
||||||
|
|
||||||
#: views.py:223
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "Yeni şifre kaydedildi."
|
|
Binary file not shown.
|
@ -1,104 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-10-28 11:41+0800\n"
|
|
||||||
"PO-Revision-Date: 2018-10-28 11:45+0806\n"
|
|
||||||
"Last-Translator: b' <admin@xx.com>'\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
|
||||||
"X-Translated-Using: django-rosetta 0.9.0\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:67
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr "View未定义,请通过context变量传入"
|
|
||||||
|
|
||||||
#: registration/serializers.py:72
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr "请在View中定义adapter_class"
|
|
||||||
|
|
||||||
#: registration/serializers.py:91
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr "请在view中定义callback_url"
|
|
||||||
|
|
||||||
#: registration/serializers.py:95
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr "请在view中定义client_class"
|
|
||||||
|
|
||||||
#: registration/serializers.py:116
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr "输入错误。access_token或code是必填项。"
|
|
||||||
|
|
||||||
#: registration/serializers.py:125
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr "错误的值"
|
|
||||||
|
|
||||||
#: registration/serializers.py:139
|
|
||||||
msgid "User is already registered with this e-mail address."
|
|
||||||
msgstr "该邮箱地址已被注册。"
|
|
||||||
|
|
||||||
#: registration/serializers.py:185
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr "该邮箱地址已被注册。"
|
|
||||||
|
|
||||||
#: registration/serializers.py:193
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr "两次输入的密码不相同"
|
|
||||||
|
|
||||||
#: registration/views.py:51
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr "验证邮件已发送。"
|
|
||||||
|
|
||||||
#: registration/views.py:98
|
|
||||||
msgid "ok"
|
|
||||||
msgstr "好的"
|
|
||||||
|
|
||||||
#: serializers.py:33
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr "比如包含\"email\"和\"password\"。"
|
|
||||||
|
|
||||||
#: serializers.py:44
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr "比如包含\"username\"和\"password\"。"
|
|
||||||
|
|
||||||
#: serializers.py:57
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr "比如包含\"username\",\"email\",\"password\"其中一个。"
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr "用户账号已被禁用。"
|
|
||||||
|
|
||||||
#: serializers.py:101
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr "无法使用提供的信息登录。"
|
|
||||||
|
|
||||||
#: serializers.py:110
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr "邮箱未验证。"
|
|
||||||
|
|
||||||
#: views.py:127
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr "已成功登出。"
|
|
||||||
|
|
||||||
#: views.py:175
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr "密码重置邮件已发送。"
|
|
||||||
|
|
||||||
#: views.py:201
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr "密码重置成功。"
|
|
||||||
|
|
||||||
#: views.py:223
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr "新密码已设置成功。"
|
|
Binary file not shown.
|
@ -1,103 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-10-28 11:41+0800\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
|
||||||
|
|
||||||
#: registration/serializers.py:67
|
|
||||||
msgid "View is not defined, pass it as a context variable"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:72
|
|
||||||
msgid "Define adapter_class in view"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:91
|
|
||||||
msgid "Define callback_url in view"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:95
|
|
||||||
msgid "Define client_class in view"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:116
|
|
||||||
msgid "Incorrect input. access_token or code is required."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:125
|
|
||||||
msgid "Incorrect value"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:139
|
|
||||||
msgid "User is already registered with this e-mail address."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:185
|
|
||||||
msgid "A user is already registered with this e-mail address."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/serializers.py:193
|
|
||||||
msgid "The two password fields didn't match."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/views.py:51
|
|
||||||
msgid "Verification e-mail sent."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: registration/views.py:98
|
|
||||||
msgid "ok"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:33
|
|
||||||
msgid "Must include \"email\" and \"password\"."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:44
|
|
||||||
msgid "Must include \"username\" and \"password\"."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:57
|
|
||||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:98
|
|
||||||
msgid "User account is disabled."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:101
|
|
||||||
msgid "Unable to log in with provided credentials."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: serializers.py:110
|
|
||||||
msgid "E-mail is not verified."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: views.py:127
|
|
||||||
msgid "Successfully logged out."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: views.py:175
|
|
||||||
msgid "Password reset e-mail has been sent."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: views.py:201
|
|
||||||
msgid "Password has been reset with the new password."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: views.py:223
|
|
||||||
msgid "New password has been saved."
|
|
||||||
msgstr ""
|
|
|
@ -1,6 +1,5 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from rest_framework.permissions import AllowAny
|
|
||||||
from rest_auth.registration.serializers import (
|
from rest_auth.registration.serializers import (
|
||||||
RegisterSerializer as DefaultRegisterSerializer)
|
RegisterSerializer as DefaultRegisterSerializer)
|
||||||
from ..utils import import_callable
|
from ..utils import import_callable
|
||||||
|
@ -10,10 +9,3 @@ serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {})
|
||||||
|
|
||||||
RegisterSerializer = import_callable(
|
RegisterSerializer = import_callable(
|
||||||
serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer))
|
serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer))
|
||||||
|
|
||||||
|
|
||||||
def register_permission_classes():
|
|
||||||
permission_classes = [AllowAny, ]
|
|
||||||
for klass in getattr(settings, 'REST_AUTH_REGISTER_PERMISSION_CLASSES', tuple()):
|
|
||||||
permission_classes.append(import_callable(klass))
|
|
||||||
return tuple(permission_classes)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from allauth.account import app_settings as allauth_settings
|
from allauth.account import app_settings as allauth_settings
|
||||||
|
@ -8,29 +8,15 @@ try:
|
||||||
get_username_max_length)
|
get_username_max_length)
|
||||||
from allauth.account.adapter import get_adapter
|
from allauth.account.adapter import get_adapter
|
||||||
from allauth.account.utils import setup_user_email
|
from allauth.account.utils import setup_user_email
|
||||||
from allauth.socialaccount.helpers import complete_social_login
|
|
||||||
from allauth.socialaccount.models import SocialAccount
|
|
||||||
from allauth.socialaccount.providers.base import AuthProcess
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("allauth needs to be added to INSTALLED_APPS.")
|
raise ImportError('allauth needs to be added to INSTALLED_APPS.')
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
|
# Import is needed only if we are using social login, in which
|
||||||
|
# case the allauth.socialaccount will be declared
|
||||||
class SocialAccountSerializer(serializers.ModelSerializer):
|
if 'allauth.socialaccount' in settings.INSTALLED_APPS:
|
||||||
"""
|
from allauth.socialaccount.helpers import complete_social_login
|
||||||
serialize allauth SocialAccounts for use with a REST API
|
|
||||||
"""
|
|
||||||
class Meta:
|
|
||||||
model = SocialAccount
|
|
||||||
fields = (
|
|
||||||
'id',
|
|
||||||
'provider',
|
|
||||||
'uid',
|
|
||||||
'last_login',
|
|
||||||
'date_joined',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SocialLoginSerializer(serializers.Serializer):
|
class SocialLoginSerializer(serializers.Serializer):
|
||||||
|
@ -45,13 +31,12 @@ class SocialLoginSerializer(serializers.Serializer):
|
||||||
|
|
||||||
def get_social_login(self, adapter, app, token, response):
|
def get_social_login(self, adapter, app, token, response):
|
||||||
"""
|
"""
|
||||||
:param adapter: allauth.socialaccount Adapter subclass.
|
|
||||||
Usually OAuthAdapter or Auth2Adapter
|
:param adapter: allauth.socialaccount Adapter subclass. Usually OAuthAdapter or Auth2Adapter
|
||||||
:param app: `allauth.socialaccount.SocialApp` instance
|
:param app: `allauth.socialaccount.SocialApp` instance
|
||||||
:param token: `allauth.socialaccount.SocialToken` instance
|
:param token: `allauth.socialaccount.SocialToken` instance
|
||||||
:param response: Provider's response for OAuth1. Not used in the
|
:param response: Provider's response for OAuth1. Not used in the
|
||||||
:returns: A populated instance of the
|
:return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance
|
||||||
`allauth.socialaccount.SocialLoginView` instance
|
|
||||||
"""
|
"""
|
||||||
request = self._get_request()
|
request = self._get_request()
|
||||||
social_login = adapter.complete_login(request, app, token, response=response)
|
social_login = adapter.complete_login(request, app, token, response=response)
|
||||||
|
@ -64,12 +49,12 @@ class SocialLoginSerializer(serializers.Serializer):
|
||||||
|
|
||||||
if not view:
|
if not view:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
_("View is not defined, pass it as a context variable")
|
_('View is not defined, pass it as a context variable')
|
||||||
)
|
)
|
||||||
|
|
||||||
adapter_class = getattr(view, 'adapter_class', None)
|
adapter_class = getattr(view, 'adapter_class', None)
|
||||||
if not adapter_class:
|
if not adapter_class:
|
||||||
raise serializers.ValidationError(_("Define adapter_class in view"))
|
raise serializers.ValidationError(_('Define adapter_class in view'))
|
||||||
|
|
||||||
adapter = adapter_class(request)
|
adapter = adapter_class(request)
|
||||||
app = adapter.get_provider().get_app(request)
|
app = adapter.get_provider().get_app(request)
|
||||||
|
@ -78,21 +63,21 @@ class SocialLoginSerializer(serializers.Serializer):
|
||||||
# http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token
|
# http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token
|
||||||
|
|
||||||
# Case 1: We received the access_token
|
# Case 1: We received the access_token
|
||||||
if attrs.get('access_token'):
|
if('access_token' in attrs):
|
||||||
access_token = attrs.get('access_token')
|
access_token = attrs.get('access_token')
|
||||||
|
|
||||||
# Case 2: We received the authorization code
|
# Case 2: We received the authorization code
|
||||||
elif attrs.get('code'):
|
elif('code' in attrs):
|
||||||
self.callback_url = getattr(view, 'callback_url', None)
|
self.callback_url = getattr(view, 'callback_url', None)
|
||||||
self.client_class = getattr(view, 'client_class', None)
|
self.client_class = getattr(view, 'client_class', None)
|
||||||
|
|
||||||
if not self.callback_url:
|
if not self.callback_url:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
_("Define callback_url in view")
|
_('Define callback_url in view')
|
||||||
)
|
)
|
||||||
if not self.client_class:
|
if not self.client_class:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
_("Define client_class in view")
|
_('Define client_class in view')
|
||||||
)
|
)
|
||||||
|
|
||||||
code = attrs.get('code')
|
code = attrs.get('code')
|
||||||
|
@ -112,57 +97,25 @@ class SocialLoginSerializer(serializers.Serializer):
|
||||||
access_token = token['access_token']
|
access_token = token['access_token']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(_('Incorrect input. access_token or code is required.'))
|
||||||
_("Incorrect input. access_token or code is required."))
|
|
||||||
|
|
||||||
social_token = adapter.parse_token({'access_token': access_token})
|
token = adapter.parse_token({'access_token': access_token})
|
||||||
social_token.app = app
|
token.app = app
|
||||||
|
|
||||||
try:
|
try:
|
||||||
login = self.get_social_login(adapter, app, social_token, access_token)
|
login = self.get_social_login(adapter, app, token, access_token)
|
||||||
complete_social_login(request, login)
|
complete_social_login(request, login)
|
||||||
except HTTPError:
|
except HTTPError:
|
||||||
raise serializers.ValidationError(_("Incorrect value"))
|
raise serializers.ValidationError(_('Incorrect value'))
|
||||||
|
|
||||||
if not login.is_existing:
|
if not login.is_existing:
|
||||||
# We have an account already signed up in a different flow
|
|
||||||
# with the same email address: raise an exception.
|
|
||||||
# This needs to be handled in the frontend. We can not just
|
|
||||||
# link up the accounts due to security constraints
|
|
||||||
if allauth_settings.UNIQUE_EMAIL:
|
|
||||||
# Do we have an account already with this email address?
|
|
||||||
account_exists = get_user_model().objects.filter(
|
|
||||||
email=login.user.email,
|
|
||||||
).exists()
|
|
||||||
if account_exists:
|
|
||||||
raise serializers.ValidationError(
|
|
||||||
_("User is already registered with this e-mail address.")
|
|
||||||
)
|
|
||||||
|
|
||||||
login.lookup()
|
login.lookup()
|
||||||
login.save(request, connect=True)
|
login.save(request, connect=True)
|
||||||
|
|
||||||
attrs['user'] = login.account.user
|
attrs['user'] = login.account.user
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class SocialConnectMixin(object):
|
|
||||||
def get_social_login(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Set the social login process state to connect rather than login
|
|
||||||
Refer to the implementation of get_social_login in base class and to the
|
|
||||||
allauth.socialaccount.helpers module complete_social_login function.
|
|
||||||
"""
|
|
||||||
social_login = super(SocialConnectMixin, self).get_social_login(*args, **kwargs)
|
|
||||||
social_login.state['process'] = AuthProcess.CONNECT
|
|
||||||
return social_login
|
|
||||||
|
|
||||||
|
|
||||||
class SocialConnectSerializer(SocialConnectMixin, SocialLoginSerializer):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterSerializer(serializers.Serializer):
|
class RegisterSerializer(serializers.Serializer):
|
||||||
username = serializers.CharField(
|
username = serializers.CharField(
|
||||||
max_length=get_username_max_length(),
|
max_length=get_username_max_length(),
|
||||||
|
@ -170,8 +123,8 @@ class RegisterSerializer(serializers.Serializer):
|
||||||
required=allauth_settings.USERNAME_REQUIRED
|
required=allauth_settings.USERNAME_REQUIRED
|
||||||
)
|
)
|
||||||
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
|
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
|
||||||
password1 = serializers.CharField(write_only=True)
|
password1 = serializers.CharField(required=True, write_only=True)
|
||||||
password2 = serializers.CharField(write_only=True)
|
password2 = serializers.CharField(required=True, write_only=True)
|
||||||
|
|
||||||
def validate_username(self, username):
|
def validate_username(self, username):
|
||||||
username = get_adapter().clean_username(username)
|
username = get_adapter().clean_username(username)
|
||||||
|
|
|
@ -17,7 +17,7 @@ urlpatterns = [
|
||||||
# with proper key.
|
# with proper key.
|
||||||
# If you don't want to use API on that step, then just use ConfirmEmailView
|
# If you don't want to use API on that step, then just use ConfirmEmailView
|
||||||
# view from:
|
# view from:
|
||||||
# django-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py
|
# django-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
||||||
url(r'^account-confirm-email/(?P<key>[-:\w]+)/$', TemplateView.as_view(),
|
url(r'^account-confirm-email/(?P<key>[-:\w]+)/$', TemplateView.as_view(),
|
||||||
name='account_confirm_email'),
|
name='account_confirm_email'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,54 +1,39 @@
|
||||||
from django.conf import settings
|
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.decorators.debug import sensitive_post_parameters
|
from django.conf import settings
|
||||||
|
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.permissions import (AllowAny,
|
from rest_framework.permissions import AllowAny
|
||||||
IsAuthenticated)
|
from rest_framework.generics import CreateAPIView
|
||||||
from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView
|
|
||||||
from rest_framework.exceptions import NotFound
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from allauth.account.adapter import get_adapter
|
from allauth.account.adapter import get_adapter
|
||||||
from allauth.account.views import ConfirmEmailView
|
from allauth.account.views import ConfirmEmailView
|
||||||
from allauth.account.utils import complete_signup
|
from allauth.account.utils import complete_signup
|
||||||
from allauth.account import app_settings as allauth_settings
|
from allauth.account import app_settings as allauth_settings
|
||||||
from allauth.socialaccount import signals
|
|
||||||
from allauth.socialaccount.adapter import get_adapter as get_social_adapter
|
|
||||||
from allauth.socialaccount.models import SocialAccount
|
|
||||||
|
|
||||||
from rest_auth.app_settings import (TokenSerializer,
|
from rest_auth.app_settings import (TokenSerializer,
|
||||||
JWTSerializer,
|
JWTSerializer,
|
||||||
create_token)
|
create_token)
|
||||||
from rest_auth.models import TokenModel
|
from rest_auth.registration.serializers import (SocialLoginSerializer,
|
||||||
from rest_auth.registration.serializers import (VerifyEmailSerializer,
|
VerifyEmailSerializer)
|
||||||
SocialLoginSerializer,
|
|
||||||
SocialAccountSerializer,
|
|
||||||
SocialConnectSerializer)
|
|
||||||
from rest_auth.utils import jwt_encode
|
|
||||||
from rest_auth.views import LoginView
|
from rest_auth.views import LoginView
|
||||||
from .app_settings import RegisterSerializer, register_permission_classes
|
from rest_auth.models import TokenModel
|
||||||
|
from .app_settings import RegisterSerializer
|
||||||
|
|
||||||
sensitive_post_parameters_m = method_decorator(
|
from rest_auth.utils import jwt_encode
|
||||||
sensitive_post_parameters('password1', 'password2')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterView(CreateAPIView):
|
class RegisterView(CreateAPIView):
|
||||||
serializer_class = RegisterSerializer
|
serializer_class = RegisterSerializer
|
||||||
permission_classes = register_permission_classes()
|
permission_classes = (AllowAny, )
|
||||||
token_model = TokenModel
|
token_model = TokenModel
|
||||||
|
throttle_scope = 'register_view'
|
||||||
@sensitive_post_parameters_m
|
|
||||||
def dispatch(self, *args, **kwargs):
|
|
||||||
return super(RegisterView, self).dispatch(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_response_data(self, user):
|
def get_response_data(self, user):
|
||||||
if allauth_settings.EMAIL_VERIFICATION == \
|
if allauth_settings.EMAIL_VERIFICATION == \
|
||||||
allauth_settings.EmailVerificationMethod.MANDATORY:
|
allauth_settings.EmailVerificationMethod.MANDATORY:
|
||||||
return {"detail": _("Verification e-mail sent.")}
|
return {}
|
||||||
|
|
||||||
if getattr(settings, 'REST_USE_JWT', False):
|
if getattr(settings, 'REST_USE_JWT', False):
|
||||||
data = {
|
data = {
|
||||||
|
@ -65,9 +50,7 @@ class RegisterView(CreateAPIView):
|
||||||
user = self.perform_create(serializer)
|
user = self.perform_create(serializer)
|
||||||
headers = self.get_success_headers(serializer.data)
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
|
||||||
return Response(self.get_response_data(user),
|
return Response(self.get_response_data(user), status=status.HTTP_201_CREATED, headers=headers)
|
||||||
status=status.HTTP_201_CREATED,
|
|
||||||
headers=headers)
|
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
user = serializer.save(self.request)
|
user = serializer.save(self.request)
|
||||||
|
@ -83,19 +66,17 @@ class RegisterView(CreateAPIView):
|
||||||
|
|
||||||
|
|
||||||
class VerifyEmailView(APIView, ConfirmEmailView):
|
class VerifyEmailView(APIView, ConfirmEmailView):
|
||||||
|
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
|
||||||
return VerifyEmailSerializer(*args, **kwargs)
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = VerifyEmailSerializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
self.kwargs['key'] = serializer.validated_data['key']
|
self.kwargs['key'] = serializer.validated_data['key']
|
||||||
confirmation = self.get_object()
|
confirmation = self.get_object()
|
||||||
confirmation.confirm(self.request)
|
confirmation.confirm(self.request)
|
||||||
return Response({'detail': _('ok')}, status=status.HTTP_200_OK)
|
return Response({'message': _('ok')}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class SocialLoginView(LoginView):
|
class SocialLoginView(LoginView):
|
||||||
|
@ -117,70 +98,12 @@ class SocialLoginView(LoginView):
|
||||||
|
|
||||||
class FacebookLogin(SocialLoginView):
|
class FacebookLogin(SocialLoginView):
|
||||||
adapter_class = FacebookOAuth2Adapter
|
adapter_class = FacebookOAuth2Adapter
|
||||||
client_class = OAuth2Client
|
client_class = OAuth2Client
|
||||||
callback_url = 'localhost:8000'
|
callback_url = 'localhost:8000'
|
||||||
-------------
|
-------------
|
||||||
"""
|
"""
|
||||||
|
|
||||||
serializer_class = SocialLoginSerializer
|
serializer_class = SocialLoginSerializer
|
||||||
|
|
||||||
def process_login(self):
|
def process_login(self):
|
||||||
get_adapter(self.request).login(self.request, self.user)
|
get_adapter(self.request).login(self.request, self.user)
|
||||||
|
|
||||||
|
|
||||||
class SocialConnectView(LoginView):
|
|
||||||
"""
|
|
||||||
class used for social account linking
|
|
||||||
|
|
||||||
example usage for facebook with access_token
|
|
||||||
-------------
|
|
||||||
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
|
|
||||||
|
|
||||||
class FacebookConnect(SocialConnectView):
|
|
||||||
adapter_class = FacebookOAuth2Adapter
|
|
||||||
-------------
|
|
||||||
"""
|
|
||||||
serializer_class = SocialConnectSerializer
|
|
||||||
permission_classes = (IsAuthenticated,)
|
|
||||||
|
|
||||||
def process_login(self):
|
|
||||||
get_adapter(self.request).login(self.request, self.user)
|
|
||||||
|
|
||||||
|
|
||||||
class SocialAccountListView(ListAPIView):
|
|
||||||
"""
|
|
||||||
List SocialAccounts for the currently logged in user
|
|
||||||
"""
|
|
||||||
serializer_class = SocialAccountSerializer
|
|
||||||
permission_classes = (IsAuthenticated,)
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return SocialAccount.objects.filter(user=self.request.user)
|
|
||||||
|
|
||||||
|
|
||||||
class SocialAccountDisconnectView(GenericAPIView):
|
|
||||||
"""
|
|
||||||
Disconnect SocialAccount from remote service for
|
|
||||||
the currently logged in user
|
|
||||||
"""
|
|
||||||
serializer_class = SocialConnectSerializer
|
|
||||||
permission_classes = (IsAuthenticated,)
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return SocialAccount.objects.filter(user=self.request.user)
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
accounts = self.get_queryset()
|
|
||||||
account = accounts.filter(pk=kwargs['pk']).first()
|
|
||||||
if not account:
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
get_social_adapter(self.request).validate_disconnect(account, accounts)
|
|
||||||
|
|
||||||
account.delete()
|
|
||||||
signals.social_account_removed.send(
|
|
||||||
sender=SocialAccount,
|
|
||||||
request=self.request,
|
|
||||||
socialaccount=account
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response(self.get_serializer(account).data)
|
|
||||||
|
|
|
@ -6,12 +6,11 @@ from django.utils.http import urlsafe_base64_decode as uid_decoder
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
|
from .models import TokenModel
|
||||||
|
|
||||||
from rest_framework import serializers, exceptions
|
from rest_framework import serializers, exceptions
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
from .models import TokenModel
|
|
||||||
from .utils import import_callable
|
|
||||||
|
|
||||||
# Get the UserModel
|
# Get the UserModel
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
|
|
||||||
|
@ -21,14 +20,11 @@ class LoginSerializer(serializers.Serializer):
|
||||||
email = serializers.EmailField(required=False, allow_blank=True)
|
email = serializers.EmailField(required=False, allow_blank=True)
|
||||||
password = serializers.CharField(style={'input_type': 'password'})
|
password = serializers.CharField(style={'input_type': 'password'})
|
||||||
|
|
||||||
def authenticate(self, **kwargs):
|
|
||||||
return authenticate(self.context['request'], **kwargs)
|
|
||||||
|
|
||||||
def _validate_email(self, email, password):
|
def _validate_email(self, email, password):
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
if email and password:
|
if email and password:
|
||||||
user = self.authenticate(email=email, password=password)
|
user = authenticate(email=email, password=password)
|
||||||
else:
|
else:
|
||||||
msg = _('Must include "email" and "password".')
|
msg = _('Must include "email" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
raise exceptions.ValidationError(msg)
|
||||||
|
@ -39,7 +35,7 @@ class LoginSerializer(serializers.Serializer):
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
if username and password:
|
if username and password:
|
||||||
user = self.authenticate(username=username, password=password)
|
user = authenticate(username=username, password=password)
|
||||||
else:
|
else:
|
||||||
msg = _('Must include "username" and "password".')
|
msg = _('Must include "username" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
raise exceptions.ValidationError(msg)
|
||||||
|
@ -50,9 +46,9 @@ class LoginSerializer(serializers.Serializer):
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
if email and password:
|
if email and password:
|
||||||
user = self.authenticate(email=email, password=password)
|
user = authenticate(email=email, password=password)
|
||||||
elif username and password:
|
elif username and password:
|
||||||
user = self.authenticate(username=username, password=password)
|
user = authenticate(username=username, password=password)
|
||||||
else:
|
else:
|
||||||
msg = _('Must include either "username" or "email" and "password".')
|
msg = _('Must include either "username" or "email" and "password".')
|
||||||
raise exceptions.ValidationError(msg)
|
raise exceptions.ValidationError(msg)
|
||||||
|
@ -74,7 +70,7 @@ class LoginSerializer(serializers.Serializer):
|
||||||
user = self._validate_email(email, password)
|
user = self._validate_email(email, password)
|
||||||
|
|
||||||
# Authentication through username
|
# Authentication through username
|
||||||
elif app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
|
if app_settings.AUTHENTICATION_METHOD == app_settings.AuthenticationMethod.USERNAME:
|
||||||
user = self._validate_username(username, password)
|
user = self._validate_username(username, password)
|
||||||
|
|
||||||
# Authentication through either username or email
|
# Authentication through either username or email
|
||||||
|
@ -124,12 +120,13 @@ class TokenSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class UserDetailsSerializer(serializers.ModelSerializer):
|
class UserDetailsSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
User model w/o password
|
User model w/o password
|
||||||
"""
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserModel
|
model = UserModel
|
||||||
fields = ('pk', 'username', 'email', 'first_name', 'last_name')
|
fields = ('username', 'email', 'first_name', 'last_name')
|
||||||
read_only_fields = ('email', )
|
read_only_fields = ('email', )
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,31 +135,22 @@ class JWTSerializer(serializers.Serializer):
|
||||||
Serializer for JWT authentication.
|
Serializer for JWT authentication.
|
||||||
"""
|
"""
|
||||||
token = serializers.CharField()
|
token = serializers.CharField()
|
||||||
user = serializers.SerializerMethodField()
|
user = UserDetailsSerializer()
|
||||||
|
|
||||||
def get_user(self, obj):
|
|
||||||
"""
|
|
||||||
Required to allow using custom USER_DETAILS_SERIALIZER in
|
|
||||||
JWTSerializer. Defining it here to avoid circular imports
|
|
||||||
"""
|
|
||||||
rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
|
|
||||||
JWTUserDetailsSerializer = import_callable(
|
|
||||||
rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer)
|
|
||||||
)
|
|
||||||
user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data
|
|
||||||
return user_data
|
|
||||||
|
|
||||||
|
|
||||||
class PasswordResetSerializer(serializers.Serializer):
|
class PasswordResetSerializer(serializers.Serializer):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Serializer for requesting a password reset e-mail.
|
Serializer for requesting a password reset e-mail.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
email = serializers.EmailField()
|
email = serializers.EmailField()
|
||||||
|
|
||||||
password_reset_form_class = PasswordResetForm
|
password_reset_form_class = PasswordResetForm
|
||||||
|
|
||||||
def get_email_options(self):
|
def get_email_options(self):
|
||||||
"""Override this method to change default e-mail options"""
|
""" Override this method to change default e-mail options
|
||||||
|
"""
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def validate_email(self, value):
|
def validate_email(self, value):
|
||||||
|
@ -190,10 +178,12 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
|
||||||
"""
|
"""
|
||||||
Serializer for requesting a password reset e-mail.
|
Serializer for requesting a password reset e-mail.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
new_password1 = serializers.CharField(max_length=128)
|
new_password1 = serializers.CharField(max_length=128)
|
||||||
new_password2 = serializers.CharField(max_length=128)
|
new_password2 = serializers.CharField(max_length=128)
|
||||||
uid = serializers.CharField()
|
|
||||||
token = serializers.CharField()
|
uid = serializers.CharField(required=True)
|
||||||
|
token = serializers.CharField(required=True)
|
||||||
|
|
||||||
set_password_form_class = SetPasswordForm
|
set_password_form_class = SetPasswordForm
|
||||||
|
|
||||||
|
@ -223,10 +213,11 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
return self.set_password_form.save()
|
self.set_password_form.save()
|
||||||
|
|
||||||
|
|
||||||
class PasswordChangeSerializer(serializers.Serializer):
|
class PasswordChangeSerializer(serializers.Serializer):
|
||||||
|
|
||||||
old_password = serializers.CharField(max_length=128)
|
old_password = serializers.CharField(max_length=128)
|
||||||
new_password1 = serializers.CharField(max_length=128)
|
new_password1 = serializers.CharField(max_length=128)
|
||||||
new_password2 = serializers.CharField(max_length=128)
|
new_password2 = serializers.CharField(max_length=128)
|
||||||
|
@ -256,8 +247,7 @@ class PasswordChangeSerializer(serializers.Serializer):
|
||||||
)
|
)
|
||||||
|
|
||||||
if all(invalid_password_conditions):
|
if all(invalid_password_conditions):
|
||||||
err_msg = _("Your old password was entered incorrectly. Please enter it again.")
|
raise serializers.ValidationError('Invalid password')
|
||||||
raise serializers.ValidationError(err_msg)
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
|
|
@ -8,12 +8,10 @@ if 'allauth.socialaccount' in settings.INSTALLED_APPS:
|
||||||
from allauth.socialaccount.models import SocialToken
|
from allauth.socialaccount.models import SocialToken
|
||||||
from allauth.socialaccount.providers.oauth.client import OAuthError
|
from allauth.socialaccount.providers.oauth.client import OAuthError
|
||||||
|
|
||||||
from rest_auth.registration.serializers import SocialConnectMixin
|
|
||||||
|
|
||||||
|
|
||||||
class TwitterLoginSerializer(serializers.Serializer):
|
class TwitterLoginSerializer(serializers.Serializer):
|
||||||
access_token = serializers.CharField()
|
access_token = serializers.CharField(required=True)
|
||||||
token_secret = serializers.CharField()
|
token_secret = serializers.CharField(required=True)
|
||||||
|
|
||||||
def _get_request(self):
|
def _get_request(self):
|
||||||
request = self.context.get('request')
|
request = self.context.get('request')
|
||||||
|
@ -23,17 +21,15 @@ class TwitterLoginSerializer(serializers.Serializer):
|
||||||
|
|
||||||
def get_social_login(self, adapter, app, token, response):
|
def get_social_login(self, adapter, app, token, response):
|
||||||
"""
|
"""
|
||||||
:param adapter: allauth.socialaccount Adapter subclass.
|
|
||||||
Usually OAuthAdapter or Auth2Adapter
|
:param adapter: allauth.socialaccount Adapter subclass. Usually OAuthAdapter or Auth2Adapter
|
||||||
:param app: `allauth.socialaccount.SocialApp` instance
|
:param app: `allauth.socialaccount.SocialApp` instance
|
||||||
:param token: `allauth.socialaccount.SocialToken` instance
|
:param token: `allauth.socialaccount.SocialToken` instance
|
||||||
:param response: Provider's response for OAuth1. Not used in the
|
:param response: Provider's response for OAuth1. Not used in the
|
||||||
:returns: A populated instance of the
|
:return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance
|
||||||
`allauth.socialaccount.SocialLoginView` instance
|
|
||||||
"""
|
"""
|
||||||
request = self._get_request()
|
request = self._get_request()
|
||||||
social_login = adapter.complete_login(request, app, token,
|
social_login = adapter.complete_login(request, app, token, response=response)
|
||||||
response=response)
|
|
||||||
social_login.token = token
|
social_login.token = token
|
||||||
return social_login
|
return social_login
|
||||||
|
|
||||||
|
@ -43,12 +39,12 @@ class TwitterLoginSerializer(serializers.Serializer):
|
||||||
|
|
||||||
if not view:
|
if not view:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
"View is not defined, pass it as a context variable"
|
'View is not defined, pass it as a context variable'
|
||||||
)
|
)
|
||||||
|
|
||||||
adapter_class = getattr(view, 'adapter_class', None)
|
adapter_class = getattr(view, 'adapter_class', None)
|
||||||
if not adapter_class:
|
if not adapter_class:
|
||||||
raise serializers.ValidationError("Define adapter_class in view")
|
raise serializers.ValidationError('Define adapter_class in view')
|
||||||
|
|
||||||
adapter = adapter_class(request)
|
adapter = adapter_class(request)
|
||||||
app = adapter.get_provider().get_app(request)
|
app = adapter.get_provider().get_app(request)
|
||||||
|
@ -75,7 +71,3 @@ class TwitterLoginSerializer(serializers.Serializer):
|
||||||
attrs['user'] = login.account.user
|
attrs['user'] = login.account.user
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class TwitterConnectSerializer(SocialConnectMixin, TwitterLoginSerializer):
|
|
||||||
pass
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
django-allauth>=0.25.0
|
django-allauth>=0.19.1
|
||||||
responses>=0.3.0
|
responses>=0.3.0
|
||||||
flake8==2.4.0
|
flake8==2.4.0
|
||||||
djangorestframework-jwt>=1.7.2
|
djangorestframework-jwt>=1.7.2
|
||||||
djangorestframework>=3.6.4
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE_CLASSES = [
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
@ -33,9 +33,6 @@ MIDDLEWARE = [
|
||||||
'django.contrib.messages.middleware.MessageMiddleware'
|
'django.contrib.messages.middleware.MessageMiddleware'
|
||||||
]
|
]
|
||||||
|
|
||||||
# Adding for backwards compatibility for Django 1.8 tests
|
|
||||||
MIDDLEWARE_CLASSES = MIDDLEWARE
|
|
||||||
|
|
||||||
TEMPLATE_CONTEXT_PROCESSORS = [
|
TEMPLATE_CONTEXT_PROCESSORS = [
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.core.context_processors.debug',
|
'django.core.context_processors.debug',
|
||||||
|
|
|
@ -1,26 +1,17 @@
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from allauth.account import app_settings as account_app_settings
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APIRequestFactory
|
from allauth.account import app_settings as account_app_settings
|
||||||
|
from .test_base import BaseAPITestCase
|
||||||
from rest_auth.registration.views import RegisterView
|
|
||||||
from rest_auth.registration.app_settings import register_permission_classes
|
|
||||||
|
|
||||||
from .mixins import TestsMixin, CustomPermissionClass
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.urls import reverse
|
|
||||||
except ImportError:
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF="tests.urls")
|
@override_settings(ROOT_URLCONF="tests.urls")
|
||||||
class APIBasicTests(TestsMixin, TestCase):
|
class APITestCase1(TestCase, BaseAPITestCase):
|
||||||
"""
|
"""
|
||||||
Case #1:
|
Case #1:
|
||||||
- user profile: defined
|
- user profile: defined
|
||||||
|
@ -407,20 +398,6 @@ class APIBasicTests(TestsMixin, TestCase):
|
||||||
self._login()
|
self._login()
|
||||||
self._logout()
|
self._logout()
|
||||||
|
|
||||||
@override_settings(REST_AUTH_REGISTER_PERMISSION_CLASSES=(CustomPermissionClass,))
|
|
||||||
def test_registration_with_custom_permission_class(self):
|
|
||||||
|
|
||||||
class CustomRegisterView(RegisterView):
|
|
||||||
permission_classes = register_permission_classes()
|
|
||||||
authentication_classes = ()
|
|
||||||
|
|
||||||
factory = APIRequestFactory()
|
|
||||||
request = factory.post('/customer/details', self.REGISTRATION_DATA, format='json')
|
|
||||||
|
|
||||||
response = CustomRegisterView.as_view()(request)
|
|
||||||
self.assertEqual(response.data['detail'], CustomPermissionClass.message)
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
||||||
|
|
||||||
@override_settings(REST_USE_JWT=True)
|
@override_settings(REST_USE_JWT=True)
|
||||||
def test_registration_with_jwt(self):
|
def test_registration_with_jwt(self):
|
||||||
user_count = get_user_model().objects.all().count()
|
user_count = get_user_model().objects.all().count()
|
||||||
|
@ -482,7 +459,7 @@ class APIBasicTests(TestsMixin, TestCase):
|
||||||
email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL)\
|
email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL)\
|
||||||
.emailconfirmation_set.order_by('-created')[0]
|
.emailconfirmation_set.order_by('-created')[0]
|
||||||
self.post(
|
self.post(
|
||||||
self.verify_email_url,
|
self.veirfy_email_url,
|
||||||
data={"key": email_confirmation.key},
|
data={"key": email_confirmation.key},
|
||||||
status_code=status.HTTP_200_OK
|
status_code=status.HTTP_200_OK
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,23 +1,11 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.test.client import Client, MULTIPART_CONTENT
|
from django.test.client import Client, MULTIPART_CONTENT
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework import permissions
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.urls import reverse
|
|
||||||
except ImportError:
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
|
|
||||||
|
|
||||||
class CustomPermissionClass(permissions.BasePermission):
|
|
||||||
message = 'You shall not pass!'
|
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class APIClient(Client):
|
class APIClient(Client):
|
||||||
|
@ -29,7 +17,8 @@ class APIClient(Client):
|
||||||
return self.generic('OPTIONS', path, data, content_type, **extra)
|
return self.generic('OPTIONS', path, data, content_type, **extra)
|
||||||
|
|
||||||
|
|
||||||
class TestsMixin(object):
|
class BaseAPITestCase(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
base for API tests:
|
base for API tests:
|
||||||
* easy request calls, f.e.: self.post(url, data), self.get(url)
|
* easy request calls, f.e.: self.post(url, data), self.get(url)
|
||||||
|
@ -75,6 +64,29 @@ class TestsMixin(object):
|
||||||
def patch(self, *args, **kwargs):
|
def patch(self, *args, **kwargs):
|
||||||
return self.send_request('patch', *args, **kwargs)
|
return self.send_request('patch', *args, **kwargs)
|
||||||
|
|
||||||
|
# def put(self, *args, **kwargs):
|
||||||
|
# return self.send_request('put', *args, **kwargs)
|
||||||
|
|
||||||
|
# def delete(self, *args, **kwargs):
|
||||||
|
# return self.send_request('delete', *args, **kwargs)
|
||||||
|
|
||||||
|
# def options(self, *args, **kwargs):
|
||||||
|
# return self.send_request('options', *args, **kwargs)
|
||||||
|
|
||||||
|
# def post_file(self, *args, **kwargs):
|
||||||
|
# kwargs['content_type'] = MULTIPART_CONTENT
|
||||||
|
# return self.send_request('post', *args, **kwargs)
|
||||||
|
|
||||||
|
# def get_file(self, *args, **kwargs):
|
||||||
|
# content_type = None
|
||||||
|
# if 'content_type' in kwargs:
|
||||||
|
# content_type = kwargs.pop('content_type')
|
||||||
|
# response = self.send_request('get', *args, **kwargs)
|
||||||
|
# if content_type:
|
||||||
|
# self.assertEqual(
|
||||||
|
# bool(filter(lambda x: content_type in x, response._headers['content-type'])), True)
|
||||||
|
# return response
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
settings.DEBUG = True
|
settings.DEBUG = True
|
||||||
self.client = APIClient()
|
self.client = APIClient()
|
||||||
|
@ -85,14 +97,11 @@ class TestsMixin(object):
|
||||||
self.register_url = reverse('rest_register')
|
self.register_url = reverse('rest_register')
|
||||||
self.password_reset_url = reverse('rest_password_reset')
|
self.password_reset_url = reverse('rest_password_reset')
|
||||||
self.user_url = reverse('rest_user_details')
|
self.user_url = reverse('rest_user_details')
|
||||||
self.verify_email_url = reverse('rest_verify_email')
|
self.veirfy_email_url = reverse('rest_verify_email')
|
||||||
self.fb_login_url = reverse('fb_login')
|
self.fb_login_url = reverse('fb_login')
|
||||||
self.tw_login_url = reverse('tw_login')
|
self.tw_login_url = reverse('tw_login')
|
||||||
self.tw_login_no_view_url = reverse('tw_login_no_view')
|
self.tw_login_no_view_url = reverse('tw_login_no_view')
|
||||||
self.tw_login_no_adapter_url = reverse('tw_login_no_adapter')
|
self.tw_login_no_adapter_url = reverse('tw_login_no_adapter')
|
||||||
self.fb_connect_url = reverse('fb_connect')
|
|
||||||
self.tw_connect_url = reverse('tw_connect')
|
|
||||||
self.social_account_list_url = reverse('social_account_list')
|
|
||||||
|
|
||||||
def _login(self):
|
def _login(self):
|
||||||
payload = {
|
payload = {
|
|
@ -5,22 +5,17 @@ from django.contrib.auth import get_user_model
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
|
||||||
try:
|
|
||||||
from django.urls import reverse
|
|
||||||
except ImportError:
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
|
|
||||||
from allauth.socialaccount.models import SocialApp
|
from allauth.socialaccount.models import SocialApp
|
||||||
from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL
|
from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL
|
||||||
import responses
|
import responses
|
||||||
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from .mixins import TestsMixin
|
from .test_base import BaseAPITestCase
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF="tests.urls")
|
@override_settings(ROOT_URLCONF="tests.urls")
|
||||||
class TestSocialAuth(TestsMixin, TestCase):
|
class TestSocialAuth(TestCase, BaseAPITestCase):
|
||||||
|
|
||||||
USERNAME = 'person'
|
USERNAME = 'person'
|
||||||
PASS = 'person'
|
PASS = 'person'
|
||||||
|
@ -230,7 +225,7 @@ class TestSocialAuth(TestsMixin, TestCase):
|
||||||
REST_SESSION_LOGIN=False,
|
REST_SESSION_LOGIN=False,
|
||||||
ACCOUNT_EMAIL_CONFIRMATION_HMAC=False
|
ACCOUNT_EMAIL_CONFIRMATION_HMAC=False
|
||||||
)
|
)
|
||||||
def test_email_clash_with_existing_account(self):
|
def test_edge_case(self):
|
||||||
resp_body = {
|
resp_body = {
|
||||||
"id": "123123123123",
|
"id": "123123123123",
|
||||||
"first_name": "John",
|
"first_name": "John",
|
||||||
|
@ -256,8 +251,6 @@ class TestSocialAuth(TestsMixin, TestCase):
|
||||||
|
|
||||||
# test empty payload
|
# test empty payload
|
||||||
self.post(self.register_url, data={}, status_code=400)
|
self.post(self.register_url, data={}, status_code=400)
|
||||||
|
|
||||||
# register user and send email confirmation
|
|
||||||
self.post(
|
self.post(
|
||||||
self.register_url,
|
self.register_url,
|
||||||
data=self.REGISTRATION_DATA,
|
data=self.REGISTRATION_DATA,
|
||||||
|
@ -270,7 +263,7 @@ class TestSocialAuth(TestsMixin, TestCase):
|
||||||
email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL)\
|
email_confirmation = new_user.emailaddress_set.get(email=self.EMAIL)\
|
||||||
.emailconfirmation_set.order_by('-created')[0]
|
.emailconfirmation_set.order_by('-created')[0]
|
||||||
self.post(
|
self.post(
|
||||||
self.verify_email_url,
|
self.veirfy_email_url,
|
||||||
data={"key": email_confirmation.key},
|
data={"key": email_confirmation.key},
|
||||||
status_code=status.HTTP_200_OK
|
status_code=status.HTTP_200_OK
|
||||||
)
|
)
|
||||||
|
@ -278,11 +271,12 @@ class TestSocialAuth(TestsMixin, TestCase):
|
||||||
self._login()
|
self._login()
|
||||||
self._logout()
|
self._logout()
|
||||||
|
|
||||||
# fb log in with already existing email
|
|
||||||
payload = {
|
payload = {
|
||||||
'access_token': 'abc123'
|
'access_token': 'abc123'
|
||||||
}
|
}
|
||||||
self.post(self.fb_login_url, data=payload, status_code=400)
|
|
||||||
|
self.post(self.fb_login_url, data=payload, status_code=200)
|
||||||
|
self.assertIn('key', self.response.json.keys())
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
@override_settings(
|
@override_settings(
|
||||||
|
@ -308,140 +302,3 @@ class TestSocialAuth(TestsMixin, TestCase):
|
||||||
self.assertIn('user', self.response.json.keys())
|
self.assertIn('user', self.response.json.keys())
|
||||||
|
|
||||||
self.assertEqual(get_user_model().objects.all().count(), users_count + 1)
|
self.assertEqual(get_user_model().objects.all().count(), users_count + 1)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF="tests.urls")
|
|
||||||
class TestSocialConnectAuth(TestsMixin, TestCase):
|
|
||||||
|
|
||||||
USERNAME = 'person'
|
|
||||||
PASS = 'person'
|
|
||||||
EMAIL = "person1@world.com"
|
|
||||||
REGISTRATION_DATA = {
|
|
||||||
"username": USERNAME,
|
|
||||||
"password1": PASS,
|
|
||||||
"password2": PASS,
|
|
||||||
"email": EMAIL
|
|
||||||
}
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.init()
|
|
||||||
|
|
||||||
facebook_social_app = SocialApp.objects.create(
|
|
||||||
provider='facebook',
|
|
||||||
name='Facebook',
|
|
||||||
client_id='123123123',
|
|
||||||
secret='321321321',
|
|
||||||
)
|
|
||||||
|
|
||||||
twitter_social_app = SocialApp.objects.create(
|
|
||||||
provider='twitter',
|
|
||||||
name='Twitter',
|
|
||||||
client_id='11223344',
|
|
||||||
secret='55667788',
|
|
||||||
)
|
|
||||||
|
|
||||||
site = Site.objects.get_current()
|
|
||||||
facebook_social_app.sites.add(site)
|
|
||||||
twitter_social_app.sites.add(site)
|
|
||||||
self.graph_api_url = GRAPH_API_URL + '/me'
|
|
||||||
self.twitter_url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
|
|
||||||
|
|
||||||
@responses.activate
|
|
||||||
def test_social_connect_no_auth(self):
|
|
||||||
responses.add(
|
|
||||||
responses.GET,
|
|
||||||
self.graph_api_url,
|
|
||||||
body='',
|
|
||||||
status=200,
|
|
||||||
content_type='application/json'
|
|
||||||
)
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
'access_token': 'abc123'
|
|
||||||
}
|
|
||||||
self.post(self.fb_connect_url, data=payload, status_code=403)
|
|
||||||
self.post(self.tw_connect_url, data=payload, status_code=403)
|
|
||||||
|
|
||||||
@responses.activate
|
|
||||||
def test_social_connect(self):
|
|
||||||
# register user
|
|
||||||
self.post(
|
|
||||||
self.register_url,
|
|
||||||
data=self.REGISTRATION_DATA,
|
|
||||||
status_code=201
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test Facebook
|
|
||||||
resp_body = {
|
|
||||||
"id": "123123123123",
|
|
||||||
"first_name": "John",
|
|
||||||
"gender": "male",
|
|
||||||
"last_name": "Smith",
|
|
||||||
"link": "https://www.facebook.com/john.smith",
|
|
||||||
"locale": "en_US",
|
|
||||||
"name": "John Smith",
|
|
||||||
"timezone": 2,
|
|
||||||
"updated_time": "2014-08-13T10:14:38+0000",
|
|
||||||
"username": "john.smith",
|
|
||||||
"verified": True
|
|
||||||
}
|
|
||||||
|
|
||||||
responses.add(
|
|
||||||
responses.GET,
|
|
||||||
self.graph_api_url,
|
|
||||||
body=json.dumps(resp_body),
|
|
||||||
status=200,
|
|
||||||
content_type='application/json'
|
|
||||||
)
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
'access_token': 'abc123'
|
|
||||||
}
|
|
||||||
self.post(self.fb_connect_url, data=payload, status_code=200)
|
|
||||||
self.assertIn('key', self.response.json.keys())
|
|
||||||
|
|
||||||
# Test Twitter
|
|
||||||
resp_body = {
|
|
||||||
"id": "123123123123",
|
|
||||||
}
|
|
||||||
|
|
||||||
responses.add(
|
|
||||||
responses.GET,
|
|
||||||
self.twitter_url,
|
|
||||||
body=json.dumps(resp_body),
|
|
||||||
status=200,
|
|
||||||
content_type='application/json'
|
|
||||||
)
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
'access_token': 'abc123',
|
|
||||||
'token_secret': '1111222233334444'
|
|
||||||
}
|
|
||||||
|
|
||||||
self.post(self.tw_connect_url, data=payload)
|
|
||||||
|
|
||||||
self.assertIn('key', self.response.json.keys())
|
|
||||||
|
|
||||||
# Check current social accounts
|
|
||||||
self.get(self.social_account_list_url)
|
|
||||||
self.assertEqual(len(self.response.json), 2)
|
|
||||||
self.assertEqual(self.response.json[0]['provider'], 'facebook')
|
|
||||||
self.assertEqual(self.response.json[1]['provider'], 'twitter')
|
|
||||||
|
|
||||||
facebook_social_account_id = self.response.json[0]['id']
|
|
||||||
|
|
||||||
# Try disconnecting accounts
|
|
||||||
self.incorrect_disconnect_url = reverse(
|
|
||||||
'social_account_disconnect', args=[999999999]
|
|
||||||
)
|
|
||||||
self.post(self.incorrect_disconnect_url, status_code=404)
|
|
||||||
|
|
||||||
self.disconnect_url = reverse(
|
|
||||||
'social_account_disconnect', args=[facebook_social_account_id]
|
|
||||||
)
|
|
||||||
self.post(self.disconnect_url, status_code=200)
|
|
||||||
|
|
||||||
# Check social accounts after disconnecting
|
|
||||||
self.get(self.social_account_list_url)
|
|
||||||
self.assertEqual(len(self.response.json), 1)
|
|
||||||
self.assertEqual(self.response.json[0]['provider'], 'twitter')
|
|
||||||
|
|
|
@ -8,13 +8,8 @@ from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
||||||
from rest_framework.decorators import api_view
|
from rest_framework.decorators import api_view
|
||||||
|
|
||||||
from rest_auth.urls import urlpatterns
|
from rest_auth.urls import urlpatterns
|
||||||
from rest_auth.registration.views import (
|
from rest_auth.registration.views import SocialLoginView
|
||||||
SocialLoginView, SocialConnectView, SocialAccountListView,
|
from rest_auth.social_serializers import TwitterLoginSerializer
|
||||||
SocialAccountDisconnectView
|
|
||||||
)
|
|
||||||
from rest_auth.social_serializers import (
|
|
||||||
TwitterLoginSerializer, TwitterConnectSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class FacebookLogin(SocialLoginView):
|
class FacebookLogin(SocialLoginView):
|
||||||
|
@ -26,15 +21,6 @@ class TwitterLogin(SocialLoginView):
|
||||||
serializer_class = TwitterLoginSerializer
|
serializer_class = TwitterLoginSerializer
|
||||||
|
|
||||||
|
|
||||||
class FacebookConnect(SocialConnectView):
|
|
||||||
adapter_class = FacebookOAuth2Adapter
|
|
||||||
|
|
||||||
|
|
||||||
class TwitterConnect(SocialConnectView):
|
|
||||||
adapter_class = TwitterOAuthAdapter
|
|
||||||
serializer_class = TwitterConnectSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class TwitterLoginSerializerFoo(TwitterLoginSerializer):
|
class TwitterLoginSerializerFoo(TwitterLoginSerializer):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -63,10 +49,5 @@ urlpatterns += [
|
||||||
url(r'^social-login/twitter/$', TwitterLogin.as_view(), name='tw_login'),
|
url(r'^social-login/twitter/$', TwitterLogin.as_view(), name='tw_login'),
|
||||||
url(r'^social-login/twitter-no-view/$', twitter_login_view, name='tw_login_no_view'),
|
url(r'^social-login/twitter-no-view/$', twitter_login_view, name='tw_login_no_view'),
|
||||||
url(r'^social-login/twitter-no-adapter/$', TwitterLoginNoAdapter.as_view(), name='tw_login_no_adapter'),
|
url(r'^social-login/twitter-no-adapter/$', TwitterLoginNoAdapter.as_view(), name='tw_login_no_adapter'),
|
||||||
url(r'^social-login/facebook/connect/$', FacebookConnect.as_view(), name='fb_connect'),
|
|
||||||
url(r'^social-login/twitter/connect/$', TwitterConnect.as_view(), name='tw_connect'),
|
|
||||||
url(r'^socialaccounts/$', SocialAccountListView.as_view(), name='social_account_list'),
|
|
||||||
url(r'^socialaccounts/(?P<pk>\d+)/disconnect/$', SocialAccountDisconnectView.as_view(),
|
|
||||||
name='social_account_disconnect'),
|
|
||||||
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
||||||
]
|
]
|
||||||
|
|
|
@ -20,7 +20,7 @@ def jwt_encode(user):
|
||||||
try:
|
try:
|
||||||
from rest_framework_jwt.settings import api_settings
|
from rest_framework_jwt.settings import api_settings
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("djangorestframework_jwt needs to be installed")
|
raise ImportError('rest_framework_jwt needs to be installed')
|
||||||
|
|
||||||
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
||||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
||||||
|
|
|
@ -3,17 +3,17 @@ from django.contrib.auth import (
|
||||||
logout as django_logout
|
logout as django_logout
|
||||||
)
|
)
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.decorators.debug import sensitive_post_parameters
|
|
||||||
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
from rest_framework.generics import GenericAPIView
|
||||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
|
from rest_framework.generics import RetrieveUpdateAPIView
|
||||||
|
|
||||||
|
from allauth.account import app_settings as allauth_settings
|
||||||
|
|
||||||
from .app_settings import (
|
from .app_settings import (
|
||||||
TokenSerializer, UserDetailsSerializer, LoginSerializer,
|
TokenSerializer, UserDetailsSerializer, LoginSerializer,
|
||||||
|
@ -21,16 +21,12 @@ from .app_settings import (
|
||||||
PasswordChangeSerializer, JWTSerializer, create_token
|
PasswordChangeSerializer, JWTSerializer, create_token
|
||||||
)
|
)
|
||||||
from .models import TokenModel
|
from .models import TokenModel
|
||||||
from .utils import jwt_encode
|
|
||||||
|
|
||||||
sensitive_post_parameters_m = method_decorator(
|
from .utils import jwt_encode
|
||||||
sensitive_post_parameters(
|
|
||||||
'password', 'old_password', 'new_password1', 'new_password2'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class LoginView(GenericAPIView):
|
class LoginView(GenericAPIView):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Check the credentials and return the REST Token
|
Check the credentials and return the REST Token
|
||||||
if the credentials are valid and authenticated.
|
if the credentials are valid and authenticated.
|
||||||
|
@ -44,10 +40,6 @@ class LoginView(GenericAPIView):
|
||||||
serializer_class = LoginSerializer
|
serializer_class = LoginSerializer
|
||||||
token_model = TokenModel
|
token_model = TokenModel
|
||||||
|
|
||||||
@sensitive_post_parameters_m
|
|
||||||
def dispatch(self, *args, **kwargs):
|
|
||||||
return super(LoginView, self).dispatch(*args, **kwargs)
|
|
||||||
|
|
||||||
def process_login(self):
|
def process_login(self):
|
||||||
django_login(self.request, self.user)
|
django_login(self.request, self.user)
|
||||||
|
|
||||||
|
@ -64,8 +56,7 @@ class LoginView(GenericAPIView):
|
||||||
if getattr(settings, 'REST_USE_JWT', False):
|
if getattr(settings, 'REST_USE_JWT', False):
|
||||||
self.token = jwt_encode(self.user)
|
self.token = jwt_encode(self.user)
|
||||||
else:
|
else:
|
||||||
self.token = create_token(self.token_model, self.user,
|
self.token = create_token(self.token_model, self.user, self.serializer)
|
||||||
self.serializer)
|
|
||||||
|
|
||||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
||||||
self.process_login()
|
self.process_login()
|
||||||
|
@ -78,28 +69,15 @@ class LoginView(GenericAPIView):
|
||||||
'user': self.user,
|
'user': self.user,
|
||||||
'token': self.token
|
'token': self.token
|
||||||
}
|
}
|
||||||
serializer = serializer_class(instance=data,
|
serializer = serializer_class(instance=data, context={'request': self.request})
|
||||||
context={'request': self.request})
|
|
||||||
else:
|
else:
|
||||||
serializer = serializer_class(instance=self.token,
|
serializer = serializer_class(instance=self.token, context={'request': self.request})
|
||||||
context={'request': self.request})
|
|
||||||
|
|
||||||
response = Response(serializer.data, status=status.HTTP_200_OK)
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
if getattr(settings, 'REST_USE_JWT', False):
|
|
||||||
from rest_framework_jwt.settings import api_settings as jwt_settings
|
|
||||||
if jwt_settings.JWT_AUTH_COOKIE:
|
|
||||||
from datetime import datetime
|
|
||||||
expiration = (datetime.utcnow() + jwt_settings.JWT_EXPIRATION_DELTA)
|
|
||||||
response.set_cookie(jwt_settings.JWT_AUTH_COOKIE,
|
|
||||||
self.token,
|
|
||||||
expires=expiration,
|
|
||||||
httponly=True)
|
|
||||||
return response
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
self.request = request
|
self.request = request
|
||||||
self.serializer = self.get_serializer(data=self.request.data,
|
self.serializer = self.get_serializer(data=self.request.data)
|
||||||
context={'request': request})
|
|
||||||
self.serializer.is_valid(raise_exception=True)
|
self.serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -107,6 +85,7 @@ class LoginView(GenericAPIView):
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(APIView):
|
class LogoutView(APIView):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Calls Django logout method and delete the Token object
|
Calls Django logout method and delete the Token object
|
||||||
assigned to the current User object.
|
assigned to the current User object.
|
||||||
|
@ -116,14 +95,17 @@ class LogoutView(APIView):
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
try:
|
||||||
response = self.logout(request)
|
if allauth_settings.LOGOUT_ON_GET:
|
||||||
else:
|
response = self.logout(request)
|
||||||
response = self.http_method_not_allowed(request, *args, **kwargs)
|
else:
|
||||||
|
response = self.http_method_not_allowed(request, *args, **kwargs)
|
||||||
|
except Exception as exc:
|
||||||
|
response = self.handle_exception(exc)
|
||||||
|
|
||||||
return self.finalize_response(request, response, *args, **kwargs)
|
return self.finalize_response(request, response, *args, **kwargs)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request):
|
||||||
return self.logout(request)
|
return self.logout(request)
|
||||||
|
|
||||||
def logout(self, request):
|
def logout(self, request):
|
||||||
|
@ -131,28 +113,22 @@ class LogoutView(APIView):
|
||||||
request.user.auth_token.delete()
|
request.user.auth_token.delete()
|
||||||
except (AttributeError, ObjectDoesNotExist):
|
except (AttributeError, ObjectDoesNotExist):
|
||||||
pass
|
pass
|
||||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
|
||||||
django_logout(request)
|
|
||||||
|
|
||||||
response = Response({"detail": _("Successfully logged out.")},
|
django_logout(request)
|
||||||
status=status.HTTP_200_OK)
|
|
||||||
if getattr(settings, 'REST_USE_JWT', False):
|
return Response({"success": _("Successfully logged out.")},
|
||||||
from rest_framework_jwt.settings import api_settings as jwt_settings
|
status=status.HTTP_200_OK)
|
||||||
if jwt_settings.JWT_AUTH_COOKIE:
|
|
||||||
response.delete_cookie(jwt_settings.JWT_AUTH_COOKIE)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
class UserDetailsView(RetrieveUpdateAPIView):
|
class UserDetailsView(RetrieveUpdateAPIView):
|
||||||
"""
|
"""
|
||||||
Reads and updates UserModel fields
|
Returns User's details in JSON format.
|
||||||
Accepts GET, PUT, PATCH methods.
|
|
||||||
|
|
||||||
Default accepted fields: username, first_name, last_name
|
Accepts the following GET parameters: token
|
||||||
Default display fields: pk, username, email, first_name, last_name
|
Accepts the following POST parameters:
|
||||||
Read-only fields: pk, email
|
Required: token
|
||||||
|
Optional: email, first_name, last_name and UserProfile fields
|
||||||
Returns UserModel fields.
|
Returns the updated UserProfile and/or User object.
|
||||||
"""
|
"""
|
||||||
serializer_class = UserDetailsSerializer
|
serializer_class = UserDetailsSerializer
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
|
@ -160,22 +136,16 @@ class UserDetailsView(RetrieveUpdateAPIView):
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.request.user
|
return self.request.user
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
"""
|
|
||||||
Adding this method since it is sometimes called when using
|
|
||||||
django-rest-swagger
|
|
||||||
https://github.com/Tivix/django-rest-auth/issues/275
|
|
||||||
"""
|
|
||||||
return get_user_model().objects.none()
|
|
||||||
|
|
||||||
|
|
||||||
class PasswordResetView(GenericAPIView):
|
class PasswordResetView(GenericAPIView):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Calls Django Auth PasswordResetForm save method.
|
Calls Django Auth PasswordResetForm save method.
|
||||||
|
|
||||||
Accepts the following POST parameters: email
|
Accepts the following POST parameters: email
|
||||||
Returns the success/fail message.
|
Returns the success/fail message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
serializer_class = PasswordResetSerializer
|
serializer_class = PasswordResetSerializer
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
|
@ -187,34 +157,28 @@ class PasswordResetView(GenericAPIView):
|
||||||
serializer.save()
|
serializer.save()
|
||||||
# Return the success message with OK HTTP status
|
# Return the success message with OK HTTP status
|
||||||
return Response(
|
return Response(
|
||||||
{"detail": _("Password reset e-mail has been sent.")},
|
{"success": _("Password reset e-mail has been sent.")},
|
||||||
status=status.HTTP_200_OK
|
status=status.HTTP_200_OK
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class PasswordResetConfirmView(GenericAPIView):
|
class PasswordResetConfirmView(GenericAPIView):
|
||||||
"""
|
"""
|
||||||
Password reset e-mail link is confirmed, therefore
|
Password reset e-mail link is confirmed, therefore this resets the user's password.
|
||||||
this resets the user's password.
|
|
||||||
|
|
||||||
Accepts the following POST parameters: token, uid,
|
Accepts the following POST parameters: new_password1, new_password2
|
||||||
new_password1, new_password2
|
Accepts the following Django URL arguments: token, uid
|
||||||
Returns the success/fail message.
|
Returns the success/fail message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
serializer_class = PasswordResetConfirmSerializer
|
serializer_class = PasswordResetConfirmSerializer
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
@sensitive_post_parameters_m
|
def post(self, request):
|
||||||
def dispatch(self, *args, **kwargs):
|
|
||||||
return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return Response(
|
return Response({"success": _("Password has been reset with the new password.")})
|
||||||
{"detail": _("Password has been reset with the new password.")}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PasswordChangeView(GenericAPIView):
|
class PasswordChangeView(GenericAPIView):
|
||||||
|
@ -224,15 +188,12 @@ class PasswordChangeView(GenericAPIView):
|
||||||
Accepts the following POST parameters: new_password1, new_password2
|
Accepts the following POST parameters: new_password1, new_password2
|
||||||
Returns the success/fail message.
|
Returns the success/fail message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
serializer_class = PasswordChangeSerializer
|
serializer_class = PasswordChangeSerializer
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
@sensitive_post_parameters_m
|
def post(self, request):
|
||||||
def dispatch(self, *args, **kwargs):
|
|
||||||
return super(PasswordChangeView, self).dispatch(*args, **kwargs)
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return Response({"detail": _("New password has been saved.")})
|
return Response({"success": _("New password has been saved.")})
|
||||||
|
|
16
setup.py
16
setup.py
|
@ -1,9 +1,15 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import os
|
try:
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
except ImportError:
|
||||||
|
from ez_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
here = os.path.dirname(os.path.abspath(__file__))
|
here = os.path.dirname(os.path.abspath(__file__))
|
||||||
f = open(os.path.join(here, 'README.rst'))
|
f = open(os.path.join(here, 'README.rst'))
|
||||||
long_description = f.read().strip()
|
long_description = f.read().strip()
|
||||||
|
@ -12,7 +18,7 @@ f.close()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='django-rest-auth',
|
name='django-rest-auth',
|
||||||
version='0.9.5',
|
version='0.8.1',
|
||||||
author='Sumit Chachra',
|
author='Sumit Chachra',
|
||||||
author_email='chachra@tivix.com',
|
author_email='chachra@tivix.com',
|
||||||
url='http://github.com/Tivix/django-rest-auth',
|
url='http://github.com/Tivix/django-rest-auth',
|
||||||
|
@ -23,7 +29,7 @@ setup(
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'Django>=1.8.0',
|
'Django>=1.8.0',
|
||||||
'djangorestframework>=3.1.3',
|
'djangorestframework>=3.1.0',
|
||||||
'six>=1.9.0',
|
'six>=1.9.0',
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
|
@ -32,10 +38,10 @@ setup(
|
||||||
tests_require=[
|
tests_require=[
|
||||||
'responses>=0.5.0',
|
'responses>=0.5.0',
|
||||||
'django-allauth>=0.25.0',
|
'django-allauth>=0.25.0',
|
||||||
'djangorestframework-jwt>=1.9.0',
|
|
||||||
],
|
],
|
||||||
test_suite='runtests.runtests',
|
test_suite='runtests.runtests',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
# cmdclass={},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Framework :: Django',
|
'Framework :: Django',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user