mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-12-02 13:53:43 +03:00
fix merge issue
This commit is contained in:
commit
c03558bd2f
34
.circleci/config.yml
Normal file
34
.circleci/config.yml
Normal file
|
@ -0,0 +1,34 @@
|
|||
version: 2.1
|
||||
orbs:
|
||||
docker: circleci/docker@0.6.0
|
||||
|
||||
jobs:
|
||||
test-django-3: &template
|
||||
docker:
|
||||
- image: circleci/python:3.8.0
|
||||
environment:
|
||||
DJANGO_VERSION: 3.0.3
|
||||
DRF: 3.11
|
||||
executor: docker/docker
|
||||
steps:
|
||||
- checkout
|
||||
- run: pip install --user -r dev-requirements.txt
|
||||
- run: pip install --user -r dj_rest_auth/tests/requirements.pip
|
||||
- run: pip install -q --user coveralls djangorestframework==$DRF Django==$DJANGO_VERSION
|
||||
- run:
|
||||
command: coverage run --source=dj_rest_auth setup.py test
|
||||
name: Test
|
||||
- run:
|
||||
command: COVERALLS_REPO_TOKEN=Q58WdUuZOi89XHyDeDsGE2lxUGQ2IfqP3 coveralls
|
||||
name: Coverage
|
||||
test-django-2:
|
||||
<<: *template
|
||||
environment:
|
||||
DJANGO_VERSION: 2.2.10
|
||||
DRF: 3.9
|
||||
|
||||
workflows:
|
||||
main:
|
||||
jobs:
|
||||
- test-django-3
|
||||
- test-django-2
|
2
.coveralls.yml
Normal file
2
.coveralls.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
service_name: travis-pro
|
||||
repo_token: Q58WdUuZOi89XHyDeDsGE2lxUGQ2IfqP3
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -72,6 +72,9 @@ target/
|
|||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
|
@ -102,3 +105,5 @@ venv.bak/
|
|||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
demo/react-spa/node_modules/
|
||||
demo/react-spa/yarn.lock
|
26
.travis.yml
26
.travis.yml
|
@ -1,26 +0,0 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
env:
|
||||
- DJANGO=1.11.* DRF=3.7.*
|
||||
- DJANGO=1.11.* DRF=3.8.*
|
||||
- DJANGO=2.0.* DRF=3.7.*
|
||||
- DJANGO=2.0.* DRF=3.8.*
|
||||
install:
|
||||
- pip install -q Django==$DJANGO djangorestframework==$DRF
|
||||
- pip install coveralls
|
||||
- pip install -r rest_auth/tests/requirements.pip
|
||||
script:
|
||||
- coverage run --source=rest_auth setup.py test
|
||||
after_success:
|
||||
- coveralls
|
||||
before_script:
|
||||
- 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
AUTHORS
2
AUTHORS
|
@ -1 +1 @@
|
|||
http://github.com/Tivix/django-rest-auth/contributors
|
||||
http://github.com/jazzband/dj-rest-auth/contributors
|
||||
|
|
3
CONTRIBUTING.md
Normal file
3
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/)
|
||||
|
||||
This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines).
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Tivix
|
||||
Copyright (c) 2014 iMerica https://github.com/iMerica/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -2,4 +2,4 @@ include AUTHORS
|
|||
include LICENSE
|
||||
include MANIFEST.in
|
||||
include README.md
|
||||
graft rest_auth
|
||||
graft dj_rest_auth
|
||||
|
|
77
README.md
Normal file
77
README.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Dj-Rest-Auth
|
||||
[![<iMerica>](https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg)](https://app.circleci.com/pipelines/github/jazzband/dj-rest-auth)
|
||||
[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/jazzband/dj-rest-auth/badge.svg?branch=master)](https://coveralls.io/github/jazzband/dj-rest-auth?branch=master)
|
||||
|
||||
Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well
|
||||
with SPAs (e.g React, Vue, Angular), and Mobile applications.
|
||||
|
||||
## Requirements
|
||||
- Django 2 or 3.
|
||||
- Python 3
|
||||
|
||||
## Quick Setup
|
||||
|
||||
Install package
|
||||
|
||||
pip install dj-rest-auth
|
||||
|
||||
Add `dj_rest_auth` app to INSTALLED_APPS in your django settings.py:
|
||||
|
||||
```python
|
||||
INSTALLED_APPS = (
|
||||
...,
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
...,
|
||||
'dj_rest_auth'
|
||||
)
|
||||
```
|
||||
|
||||
Add URL patterns
|
||||
|
||||
```python
|
||||
urlpatterns = [
|
||||
url(r'^dj-rest-auth/', include('dj_rest_auth.urls'))
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
(Optional) Use Http-Only cookies
|
||||
|
||||
```python
|
||||
REST_USE_JWT = True
|
||||
JWT_AUTH_COOKIE = 'jwt-auth'
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
To run the tests within a virtualenv, run `python runtests.py` from the repository directory.
|
||||
The easiest way to run test coverage is with [`coverage`](https://pypi.org/project/coverage/),
|
||||
which runs the tests against all supported Django installs. To run the test coverage
|
||||
within a virtualenv, run `coverage run ./runtests.py` from the repository directory then run `coverage report`.
|
||||
|
||||
#### Tox
|
||||
|
||||
Testing may also be done using [`tox`](https://pypi.org/project/tox/), which
|
||||
will run the tests against all supported combinations of python and django.
|
||||
|
||||
Install tox, either globally or within a virtualenv, and then simply run `tox`
|
||||
from the repository directory. As there are many combinations, you may run them
|
||||
in [`parallel`](https://tox.readthedocs.io/en/latest/config.html#cmdoption-tox-p)
|
||||
using `tox --parallel`.
|
||||
|
||||
The `tox.ini` includes an environment for testing code [`coverage`](https://pypi.org/project/coverage/)
|
||||
and you can run it and view this report with `tox -e coverage`.
|
||||
|
||||
Linting may also be performed via [`flake8`](https://pypi.org/project/flake8/)
|
||||
by running `tox -e flake8`.
|
||||
|
||||
### Documentation
|
||||
|
||||
View the full documentation here: https://dj-rest-auth.readthedocs.io/en/latest/index.html
|
||||
|
||||
|
||||
### Acknowledgements
|
||||
|
||||
This project began as a fork of `django-rest-auth`. Big thanks to everyone who contributed to that repo!
|
31
README.rst
31
README.rst
|
@ -1,31 +0,0 @@
|
|||
Welcome to django-rest-auth
|
||||
===========================
|
||||
|
||||
.. image:: https://travis-ci.org/Tivix/django-rest-auth.svg
|
||||
:target: https://travis-ci.org/Tivix/django-rest-auth
|
||||
|
||||
|
||||
.. image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.svg
|
||||
:target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master
|
||||
|
||||
|
||||
.. image:: https://readthedocs.org/projects/django-rest-auth/badge/?version=latest
|
||||
:target: https://readthedocs.org/projects/django-rest-auth/?badge=latest
|
||||
|
||||
|
||||
Django-rest-auth provides a set of REST API endpoints for Authentication and Registration
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
http://django-rest-auth.readthedocs.org/en/latest/
|
||||
|
||||
|
||||
Source code
|
||||
-----------
|
||||
https://github.com/Tivix/django-rest-auth
|
||||
|
||||
|
||||
Stack Overflow
|
||||
-----------
|
||||
http://stackoverflow.com/questions/tagged/django-rest-auth
|
|
@ -31,23 +31,23 @@ INSTALLED_APPS = (
|
|||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
# 'django.contrib.messages',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.sites',
|
||||
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
'rest_auth',
|
||||
|
||||
'dj_rest_auth',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'rest_auth.registration',
|
||||
'dj_rest_auth.registration',
|
||||
'allauth.socialaccount',
|
||||
'allauth.socialaccount.providers.facebook',
|
||||
'rest_framework_swagger',
|
||||
'corsheaders'
|
||||
)
|
||||
|
||||
MIDDLEWARE = (
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
|
@ -116,14 +116,23 @@ ACCOUNT_EMAIL_REQUIRED = False
|
|||
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
||||
ACCOUNT_EMAIL_VERIFICATION = 'optional'
|
||||
|
||||
REST_USE_JWT = True
|
||||
JWT_AUTH_COOKIE = 'auth'
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
)
|
||||
'dj_rest_auth.utils.JWTCookieAuthentication'
|
||||
),
|
||||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
|
||||
}
|
||||
|
||||
SWAGGER_SETTINGS = {
|
||||
'LOGIN_URL': 'login',
|
||||
'LOGOUT_URL': 'logout',
|
||||
}
|
||||
|
||||
|
||||
# For demo purposes only. Use a white list in the real world.
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
from django.views.generic import TemplateView, RedirectView
|
||||
|
||||
from django.views.generic import RedirectView, TemplateView
|
||||
from rest_framework_swagger.views import get_swagger_view
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -35,8 +34,8 @@ urlpatterns = [
|
|||
TemplateView.as_view(template_name="password_reset_confirm.html"),
|
||||
name='password_reset_confirm'),
|
||||
|
||||
url(r'^rest-auth/', include('rest_auth.urls')),
|
||||
url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
|
||||
url(r'^dj-rest-auth/', include('dj_rest_auth.urls')),
|
||||
url(r'^dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
|
||||
url(r'^account/', include('allauth.urls')),
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^accounts/profile/$', RedirectView.as_view(url='/', permanent=True), name='profile-redirect'),
|
||||
|
|
|
@ -8,7 +8,9 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
|
|||
"""
|
||||
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
|
|
23
demo/react-spa/.gitignore
vendored
Normal file
23
demo/react-spa/.gitignore
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
68
demo/react-spa/README.md
Normal file
68
demo/react-spa/README.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `yarn build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
34
demo/react-spa/package.json
Normal file
34
demo/react-spa/package.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "react-spa",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
BIN
demo/react-spa/public/favicon.ico
Normal file
BIN
demo/react-spa/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
43
demo/react-spa/public/index.html
Normal file
43
demo/react-spa/public/index.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
BIN
demo/react-spa/public/logo192.png
Normal file
BIN
demo/react-spa/public/logo192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
demo/react-spa/public/logo512.png
Normal file
BIN
demo/react-spa/public/logo512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
25
demo/react-spa/public/manifest.json
Normal file
25
demo/react-spa/public/manifest.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
3
demo/react-spa/public/robots.txt
Normal file
3
demo/react-spa/public/robots.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
40
demo/react-spa/src/App.css
Normal file
40
demo/react-spa/src/App.css
Normal file
|
@ -0,0 +1,40 @@
|
|||
.App {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
66
demo/react-spa/src/App.js
vendored
Normal file
66
demo/react-spa/src/App.js
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
import React, { useState } from 'react';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const [ resp, changeResponse ] = useState(null);
|
||||
const [ username, changeUsername ] = useState('');
|
||||
const [ password, changePassword ] = useState('');
|
||||
|
||||
function onSubmit(e) {
|
||||
e.preventDefault();
|
||||
return fetch('http://localhost:8000/dj-rest-auth/login/', {
|
||||
method: 'POST',
|
||||
credentials: 'omit',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({username, password})
|
||||
}).then(resp => resp.json()).then(data => {
|
||||
changeResponse(data)
|
||||
}).catch(error => console.log('error ->', error))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<h1>
|
||||
Login
|
||||
</h1>
|
||||
<div className={'help-text'}>
|
||||
Inspect the network requests in your browser to view headers returned by dj-rest-auth.
|
||||
</div>
|
||||
<div>
|
||||
{resp &&
|
||||
<div className={'response'}>
|
||||
<code>
|
||||
{JSON.stringify(resp)}
|
||||
</code>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<form onSubmit={onSubmit}>
|
||||
<div>
|
||||
<input
|
||||
onChange={(e) => changeUsername(e.target.value)}
|
||||
value={username}
|
||||
type={'input'}
|
||||
name={'username'}/>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
onChange={(e) => changePassword(e.target.value)}
|
||||
value={password}
|
||||
type={'password'}
|
||||
name={'password'}/>
|
||||
</div>
|
||||
<button type={'submit'}>Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
9
demo/react-spa/src/App.test.js
Normal file
9
demo/react-spa/src/App.test.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
const { getByText } = render(<App />);
|
||||
const linkElement = getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
48
demo/react-spa/src/index.css
Normal file
48
demo/react-spa/src/index.css
Normal file
|
@ -0,0 +1,48 @@
|
|||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
body div {
|
||||
flex-direction: row;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 240px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
word-break: break-all;
|
||||
height: 200px;
|
||||
color: #0f0f0f;
|
||||
}
|
||||
|
||||
.response {
|
||||
margin: 20px;
|
||||
background-color: #eee;
|
||||
width: 80%;
|
||||
height: 200px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
font-size: 11px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
form > div {
|
||||
margin: 20px;
|
||||
}
|
17
demo/react-spa/src/index.js
vendored
Normal file
17
demo/react-spa/src/index.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
7
demo/react-spa/src/logo.svg
Normal file
7
demo/react-spa/src/logo.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
|
||||
<g fill="#61DAFB">
|
||||
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
|
||||
<circle cx="420.9" cy="296.5" r="45.7"/>
|
||||
<path d="M520.5 78.1z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
141
demo/react-spa/src/serviceWorker.js
vendored
Normal file
141
demo/react-spa/src/serviceWorker.js
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then(registration => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
5
demo/react-spa/src/setupTests.js
vendored
Normal file
5
demo/react-spa/src/setupTests.js
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
|
@ -1,6 +1,8 @@
|
|||
django>=1.9.0
|
||||
django-rest-auth==0.9.5
|
||||
djangorestframework>=3.7.0
|
||||
git+https://github.com/jazzband/dj-rest-auth.git@master
|
||||
djangorestframework>=3.11.0
|
||||
djangorestframework-simplejwt==4.4.0
|
||||
django-allauth>=0.24.1
|
||||
six==1.9.0
|
||||
django-rest-swagger==2.0.7
|
||||
django-cors-headers==3.2.1
|
||||
coreapi==2.3.3
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Django-rest-auth demo">
|
||||
<meta name="author" content="Tivix, Inc.">
|
||||
<meta name="description" content="Django-dj-rest-auth demo">
|
||||
<meta name="author" content="iMerica, Inc.">
|
||||
|
||||
<title>django-rest-auth demo</title>
|
||||
<title>dj-rest-auth demo</title>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||
|
@ -53,13 +53,13 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">django-rest-auth demo</a>
|
||||
<a class="navbar-brand" href="/">dj-rest-auth demo</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<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="https://github.com/Tivix/django-rest-auth">Source code</a></li>
|
||||
<li><a target="_blank" href="http://dj-rest-auth.readthedocs.org/en/latest/">Documentation</a></li>
|
||||
<li><a target="_blank" href="https://github.com/jazzband/dj-rest-auth">Source code</a></li>
|
||||
<li><a target="_blank" href="{% url 'api_docs' %}">API Docs</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block content %}
|
||||
<!-- Main jumbotron for a primary marketing message or call to action -->
|
||||
<div class="jumbotron">
|
||||
<h1>django-rest-auth demo</h1>
|
||||
<p>Welcome in django-rest-auth demo project!</p>
|
||||
<h1>dj-rest-auth demo</h1>
|
||||
<p>Welcome in dj-rest-auth demo project!</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
--editable .
|
||||
responses>=0.5.0
|
||||
djangorestframework-jwt
|
||||
djangorestframework-simplejwt==4.4.0
|
||||
django-allauth
|
||||
coveralls>=1.11.1
|
8
dj_rest_auth/__version__.py
Normal file
8
dj_rest_auth/__version__.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
__title__ = 'dj-rest-auth'
|
||||
__description__ = 'Authentication and Registration in Django Rest Framework.'
|
||||
__url__ = 'http://github.com/jazzband/dj-rest-auth'
|
||||
__version__ = '1.0.6'
|
||||
__author__ = '@iMerica https://github.com/iMerica'
|
||||
__author_email__ = 'imichael@pm.me'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright 2020 @iMerica https://github.com/iMerica'
|
40
dj_rest_auth/app_settings.py
Normal file
40
dj_rest_auth/app_settings.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from dj_rest_auth.serializers import JWTSerializer as DefaultJWTSerializer
|
||||
from dj_rest_auth.serializers import LoginSerializer as DefaultLoginSerializer
|
||||
from dj_rest_auth.serializers import \
|
||||
PasswordChangeSerializer as DefaultPasswordChangeSerializer
|
||||
from dj_rest_auth.serializers import \
|
||||
PasswordResetConfirmSerializer as DefaultPasswordResetConfirmSerializer
|
||||
from dj_rest_auth.serializers import \
|
||||
PasswordResetSerializer as DefaultPasswordResetSerializer
|
||||
from dj_rest_auth.serializers import TokenSerializer as DefaultTokenSerializer
|
||||
from dj_rest_auth.serializers import \
|
||||
UserDetailsSerializer as DefaultUserDetailsSerializer
|
||||
from django.conf import settings
|
||||
|
||||
from .utils import default_create_token, import_callable
|
||||
|
||||
create_token = import_callable(getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token))
|
||||
|
||||
serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
|
||||
|
||||
TokenSerializer = import_callable(serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer))
|
||||
|
||||
JWTSerializer = import_callable(serializers.get('JWT_SERIALIZER', DefaultJWTSerializer))
|
||||
|
||||
UserDetailsSerializer = import_callable(serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer))
|
||||
|
||||
LoginSerializer = import_callable(serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer))
|
||||
|
||||
PasswordResetSerializer = import_callable(serializers.get(
|
||||
'PASSWORD_RESET_SERIALIZER', DefaultPasswordResetSerializer
|
||||
))
|
||||
|
||||
PasswordResetConfirmSerializer = import_callable(serializers.get(
|
||||
'PASSWORD_RESET_CONFIRM_SERIALIZER', DefaultPasswordResetConfirmSerializer
|
||||
))
|
||||
|
||||
PasswordChangeSerializer = import_callable(
|
||||
serializers.get('PASSWORD_CHANGE_SERIALIZER', DefaultPasswordChangeSerializer)
|
||||
)
|
||||
|
||||
JWT_AUTH_COOKIE = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
|
@ -1,11 +1,11 @@
|
|||
# Czech translations of Tivix/django-rest-auth
|
||||
# Czech translations of jazzband/dj-rest-auth
|
||||
#
|
||||
# This file is distributed under the same license as the Tivix/django-rest-auth package.
|
||||
# This file is distributed under the same license as the jazzband/dj-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"
|
||||
"Project-Id-Version: jazzband/dj-rest-auth\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jazzband/dj-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"
|
BIN
dj_rest_auth/locale/it/LC_MESSAGES/django.mo
Normal file
BIN
dj_rest_auth/locale/it/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
123
dj_rest_auth/locale/it/LC_MESSAGES/django.po
Normal file
123
dj_rest_auth/locale/it/LC_MESSAGES/django.po
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Italian language.
|
||||
# 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: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-07 09:46+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Francesco Pinzauti <info@pinzauti.tech>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: it\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:67
|
||||
msgid "View is not defined, pass it as a context variable"
|
||||
msgstr "\"view\" non è definito, passalo come variabile di contesto"
|
||||
|
||||
#: .\registration\serializers.py:72
|
||||
msgid "Define adapter_class in view"
|
||||
msgstr "Definisci \"adapter_class\" in view"
|
||||
|
||||
#: .\registration\serializers.py:91
|
||||
msgid "Define callback_url in view"
|
||||
msgstr "Definisci \"callback_url\" in view"
|
||||
|
||||
#: .\registration\serializers.py:95
|
||||
msgid "Define client_class in view"
|
||||
msgstr "Definisci \"client_class\" in view"
|
||||
|
||||
#: .\registration\serializers.py:116
|
||||
msgid "Incorrect input. access_token or code is required."
|
||||
msgstr "Input errato. È richiesto \"access_token\" o \"code\"."
|
||||
|
||||
#: .\registration\serializers.py:125
|
||||
msgid "Incorrect value"
|
||||
msgstr "Valore errato"
|
||||
|
||||
#: .\registration\serializers.py:139
|
||||
msgid "User is already registered with this e-mail address."
|
||||
msgstr "Un altro utente è già registrato con questo indirizzo e-mail."
|
||||
|
||||
#: .\registration\serializers.py:185
|
||||
msgid "A user is already registered with this e-mail address."
|
||||
msgstr "Un altro utente è già registrato con questo indirizzo e-mail."
|
||||
|
||||
#: .\registration\serializers.py:193
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Le password non corrispondono."
|
||||
|
||||
#: .\registration\views.py:47
|
||||
msgid "Verification e-mail sent."
|
||||
msgstr "E-mail di verifica inviata."
|
||||
|
||||
#: .\registration\views.py:95
|
||||
msgid "ok"
|
||||
msgstr "ok"
|
||||
|
||||
#: .\serializers.py:32
|
||||
msgid "Must include \"email\" and \"password\"."
|
||||
msgstr "Deve includere \"email\" e \"password\"."
|
||||
|
||||
#: .\serializers.py:43
|
||||
msgid "Must include \"username\" and \"password\"."
|
||||
msgstr "Deve includere \"email\" e \"password\"."
|
||||
|
||||
#: .\serializers.py:56
|
||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
||||
msgstr "Deve includere o \"username\" o \"email\" e \"password\"."
|
||||
|
||||
#: .\serializers.py:97
|
||||
msgid "User account is disabled."
|
||||
msgstr "L'account è disabilitato."
|
||||
|
||||
#: .\serializers.py:100
|
||||
msgid "Unable to log in with provided credentials."
|
||||
msgstr "Impossibile accedere con le credenziali fornite."
|
||||
|
||||
#: .\serializers.py:109
|
||||
msgid "E-mail is not verified."
|
||||
msgstr "L'e-mail non è verificata."
|
||||
|
||||
#: .\serializers.py:264
|
||||
msgid "Your old password was entered incorrectly. Please enter it again."
|
||||
msgstr "La tua password precedente non è corretta. Inseriscila nuovamente."
|
||||
|
||||
#: .\views.py:139
|
||||
msgid "Successfully logged out."
|
||||
msgstr "Disconnesso con successo."
|
||||
|
||||
#: .\views.py:161
|
||||
msgid "Refresh token was not included in request data."
|
||||
msgstr "Il \"Refresh token\" non è presente nei dati della richiesta."
|
||||
|
||||
#: .\views.py:171 .\views.py:175
|
||||
msgid "An error has occurred."
|
||||
msgstr "Si è verificato un errore."
|
||||
|
||||
#: .\views.py:180
|
||||
msgid ""
|
||||
"Neither cookies or blacklist are enabled, so the token has not been deleted "
|
||||
"server side. Please make sure the token is deleted client side."
|
||||
msgstr ""
|
||||
"Né i cookies né la blacklist sono abilitati, quindi il token non è stato eliminato "
|
||||
"lato server. Assicurarsi che il token sia eliminato lato client."
|
||||
|
||||
#: .\views.py:230
|
||||
msgid "Password reset e-mail has been sent."
|
||||
msgstr "L'e-mail per il recupero della password è stata inviata."
|
||||
|
||||
#: .\views.py:256
|
||||
msgid "Password has been reset with the new password."
|
||||
msgstr "Password aggiornata."
|
||||
|
||||
#: .\views.py:278
|
||||
msgid "New password has been saved."
|
||||
msgstr "Nuova password salvata."
|
BIN
dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo
Normal file
BIN
dj_rest_auth/locale/pt_BR/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
101
dj_rest_auth/locale/uk/django.po
Normal file
101
dj_rest_auth/locale/uk/django.po
Normal file
|
@ -0,0 +1,101 @@
|
|||
# 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: 2020-05-23 21:56-0800\n"
|
||||
"PO-Revision-Date: 2020-05-23 00:56+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 2.3.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 "Встановіть 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 "Лист з підтвердженням вислано на email."
|
||||
|
||||
#: registration/views.py:91
|
||||
msgid "ok"
|
||||
msgstr "добре"
|
||||
|
||||
#: serializers.py:30
|
||||
msgid "Must include \"email\" and \"password\"."
|
||||
msgstr "Має включати \"email\" и \"пароль\"."
|
||||
|
||||
#: serializers.py:41
|
||||
msgid "Must include \"username\" and \"password\"."
|
||||
msgstr "Має включати \"юзернейм\" и \"пароль\"."
|
||||
|
||||
#: serializers.py:54
|
||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
||||
msgstr "Повинно включати або \"юзернейм\" либо \"email\" и \"пароль\"."
|
||||
|
||||
#: 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 "Новий пароль збережений."
|
4
dj_rest_auth/models.py
Normal file
4
dj_rest_auth/models.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from django.conf import settings
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
TokenModel = import_string(getattr(settings, 'REST_AUTH_TOKEN_MODEL', 'rest_framework.authtoken.models.Token'))
|
|
@ -1,19 +1,17 @@
|
|||
from dj_rest_auth.registration.serializers import \
|
||||
RegisterSerializer as DefaultRegisterSerializer
|
||||
from django.conf import settings
|
||||
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_auth.registration.serializers import (
|
||||
RegisterSerializer as DefaultRegisterSerializer)
|
||||
from ..utils import import_callable
|
||||
|
||||
from ..utils import import_callable
|
||||
|
||||
serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {})
|
||||
|
||||
RegisterSerializer = import_callable(
|
||||
serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer))
|
||||
RegisterSerializer = import_callable(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))
|
||||
permission_classes.append(klass)
|
||||
return tuple(permission_classes)
|
|
@ -1,6 +1,8 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.http import HttpRequest
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth import get_user_model
|
||||
from requests.exceptions import HTTPError
|
||||
from rest_framework import serializers
|
||||
|
||||
try:
|
||||
from allauth.account import app_settings as allauth_settings
|
||||
|
@ -14,9 +16,6 @@ try:
|
|||
except ImportError:
|
||||
raise ImportError("allauth needs to be added to INSTALLED_APPS.")
|
||||
|
||||
from rest_framework import serializers
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
|
||||
class SocialAccountSerializer(serializers.ModelSerializer):
|
||||
"""
|
|
@ -1,5 +1,5 @@
|
|||
from django.views.generic import TemplateView
|
||||
from django.conf.urls import url
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from .views import RegisterView, VerifyEmailView
|
||||
|
|
@ -1,34 +1,30 @@
|
|||
from allauth.account import app_settings as allauth_settings
|
||||
from allauth.account.adapter import get_adapter
|
||||
from allauth.account.utils import complete_signup
|
||||
from allauth.account.views import ConfirmEmailView
|
||||
from allauth.socialaccount import signals
|
||||
from allauth.socialaccount.adapter import get_adapter as get_social_adapter
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
from dj_rest_auth.app_settings import (JWTSerializer, TokenSerializer,
|
||||
create_token)
|
||||
from dj_rest_auth.models import TokenModel
|
||||
from dj_rest_auth.registration.serializers import (SocialAccountSerializer,
|
||||
SocialConnectSerializer,
|
||||
SocialLoginSerializer,
|
||||
VerifyEmailSerializer)
|
||||
from dj_rest_auth.utils import jwt_encode
|
||||
from dj_rest_auth.views import LoginView
|
||||
from django.conf import settings
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import (AllowAny,
|
||||
IsAuthenticated)
|
||||
from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework import status
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework.generics import CreateAPIView, GenericAPIView, ListAPIView
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from allauth.account.adapter import get_adapter
|
||||
from allauth.account.views import ConfirmEmailView
|
||||
from allauth.account.utils import complete_signup
|
||||
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,
|
||||
JWTSerializer,
|
||||
create_token)
|
||||
from rest_auth.models import TokenModel
|
||||
from rest_auth.registration.serializers import (VerifyEmailSerializer,
|
||||
SocialLoginSerializer,
|
||||
SocialAccountSerializer,
|
||||
SocialConnectSerializer)
|
||||
from rest_auth.utils import jwt_encode
|
||||
from rest_auth.views import LoginView
|
||||
from .app_settings import RegisterSerializer, register_permission_classes
|
||||
|
||||
sensitive_post_parameters_m = method_decorator(
|
||||
|
@ -54,11 +50,12 @@ class RegisterView(CreateAPIView):
|
|||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
data = {
|
||||
'user': user,
|
||||
'token': self.token
|
||||
'access_token': self.access_token,
|
||||
'refresh_token': self.refresh_token
|
||||
}
|
||||
return JWTSerializer(data).data
|
||||
return JWTSerializer(data, context=self.get_serializer_context()).data
|
||||
else:
|
||||
return TokenSerializer(user.auth_token).data
|
||||
return TokenSerializer(user.auth_token, context=self.get_serializer_context()).data
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
|
@ -73,7 +70,7 @@ class RegisterView(CreateAPIView):
|
|||
def perform_create(self, serializer):
|
||||
user = serializer.save(self.request)
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
self.token = jwt_encode(user)
|
||||
self.access_token, self.refresh_token = jwt_encode(user)
|
||||
else:
|
||||
create_token(self.token_model, user, serializer)
|
||||
|
|
@ -1,16 +1,18 @@
|
|||
from django.contrib.auth import get_user_model, authenticate
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate, get_user_model
|
||||
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
from django.utils.http import urlsafe_base64_decode as uid_decoder
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from rest_framework import serializers, exceptions
|
||||
from django.utils.http import urlsafe_base64_decode as uid_decoder
|
||||
from django.utils.module_loading import import_string
|
||||
try:
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
except ImportError:
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import exceptions, serializers
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from .models import TokenModel
|
||||
from .utils import import_callable
|
||||
|
||||
# Get the UserModel
|
||||
UserModel = get_user_model()
|
||||
|
@ -102,7 +104,7 @@ class LoginSerializer(serializers.Serializer):
|
|||
raise exceptions.ValidationError(msg)
|
||||
|
||||
# If required, is the email verified?
|
||||
if 'rest_auth.registration' in settings.INSTALLED_APPS:
|
||||
if 'dj_rest_auth.registration' in settings.INSTALLED_APPS:
|
||||
from allauth.account import app_settings
|
||||
if app_settings.EMAIL_VERIFICATION == app_settings.EmailVerificationMethod.MANDATORY:
|
||||
email_address = user.emailaddress_set.get(email=user.email)
|
||||
|
@ -137,7 +139,8 @@ class JWTSerializer(serializers.Serializer):
|
|||
"""
|
||||
Serializer for JWT authentication.
|
||||
"""
|
||||
token = serializers.CharField()
|
||||
access_token = serializers.CharField()
|
||||
refresh_token = serializers.CharField()
|
||||
user = serializers.SerializerMethodField()
|
||||
|
||||
def get_user(self, obj):
|
||||
|
@ -146,9 +149,14 @@ class JWTSerializer(serializers.Serializer):
|
|||
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)
|
||||
|
||||
JWTUserDetailsSerializer = import_string(
|
||||
rest_auth_serializers.get(
|
||||
'USER_DETAILS_SERIALIZER',
|
||||
'dj_rest_auth.serializers.UserDetailsSerializer'
|
||||
)
|
||||
)
|
||||
|
||||
user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data
|
||||
return user_data
|
||||
|
||||
|
@ -188,7 +196,7 @@ class PasswordResetSerializer(serializers.Serializer):
|
|||
|
||||
class PasswordResetConfirmSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for requesting a password reset e-mail.
|
||||
Serializer for confirming a password reset attempt.
|
||||
"""
|
||||
new_password1 = serializers.CharField(max_length=128)
|
||||
new_password2 = serializers.CharField(max_length=128)
|
||||
|
@ -210,6 +218,9 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
|
|||
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
|
||||
raise ValidationError({'uid': ['Invalid value']})
|
||||
|
||||
if not default_token_generator.check_token(self.user, attrs['token']):
|
||||
raise ValidationError({'token': ['Invalid value']})
|
||||
|
||||
self.custom_validation(attrs)
|
||||
# Construct SetPasswordForm instance
|
||||
self.set_password_form = self.set_password_form_class(
|
||||
|
@ -217,8 +228,6 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
|
|||
)
|
||||
if not self.set_password_form.is_valid():
|
||||
raise serializers.ValidationError(self.set_password_form.errors)
|
||||
if not default_token_generator.check_token(self.user, attrs['token']):
|
||||
raise ValidationError({'token': ['Invalid value']})
|
||||
|
||||
return attrs
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.http import HttpRequest
|
||||
from rest_framework import serializers
|
||||
|
||||
# Import is needed only if we are using social login, in which
|
||||
# case the allauth.socialaccount will be declared
|
||||
if 'allauth.socialaccount' in settings.INSTALLED_APPS:
|
||||
|
@ -8,7 +9,7 @@ if 'allauth.socialaccount' in settings.INSTALLED_APPS:
|
|||
from allauth.socialaccount.models import SocialToken
|
||||
from allauth.socialaccount.providers.oauth.client import OAuthError
|
||||
|
||||
from rest_auth.registration.serializers import SocialConnectMixin
|
||||
from dj_rest_auth.registration.serializers import SocialConnectMixin
|
||||
|
||||
|
||||
class TwitterLoginSerializer(serializers.Serializer):
|
45
dj_rest_auth/tests/django_urls.py
Normal file
45
dj_rest_auth/tests/django_urls.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Moved in Django 1.8 from django to tests/auth_tests/urls.py
|
||||
|
||||
from django.conf.urls import url
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.urls import urlpatterns
|
||||
|
||||
try:
|
||||
from django.contrib.auth.views import (
|
||||
logout, login, password_reset,
|
||||
password_change, password_reset_confirm
|
||||
)
|
||||
except ImportError:
|
||||
from django.contrib.auth.views import (
|
||||
LoginView, LogoutView, PasswordResetView,
|
||||
PasswordChangeView, PasswordResetConfirmView
|
||||
)
|
||||
logout = LogoutView.as_view()
|
||||
login = LoginView.as_view()
|
||||
password_reset = PasswordResetView.as_view()
|
||||
password_change = PasswordChangeView.as_view()
|
||||
password_reset_confirm = PasswordResetConfirmView.as_view()
|
||||
|
||||
|
||||
# special urls for auth test cases
|
||||
urlpatterns += [
|
||||
url(r'^logout/custom_query/$', logout, dict(redirect_field_name='follow')),
|
||||
url(r'^logout/next_page/$', logout, dict(next_page='/somewhere/')),
|
||||
url(r'^logout/next_page/named/$', logout, dict(next_page='password_reset')),
|
||||
url(r'^password_reset_from_email/$', password_reset, dict(from_email='staffmember@example.com')),
|
||||
url(r'^password_reset/custom_redirect/$', password_reset, dict(post_reset_redirect='/custom/')),
|
||||
url(r'^password_reset/custom_redirect/named/$', password_reset, dict(post_reset_redirect='password_reset')),
|
||||
url(r'^password_reset/html_email_template/$', password_reset,
|
||||
dict(html_email_template_name='registration/html_password_reset_email.html')),
|
||||
url(r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
|
||||
password_reset_confirm,
|
||||
dict(post_reset_redirect='/custom/')),
|
||||
url(r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
|
||||
password_reset_confirm,
|
||||
dict(post_reset_redirect='password_reset')),
|
||||
url(r'^password_change/custom/$', password_change, dict(post_change_redirect='/custom/')),
|
||||
url(r'^password_change/custom/named/$', password_change, dict(post_change_redirect='password_reset')),
|
||||
url(r'^admin_password_reset/$', password_reset, dict(is_admin_site=True)),
|
||||
url(r'^login_required/$', login_required(password_reset)),
|
||||
url(r'^login_required_login_url/$', login_required(password_reset, login_url='/somewhere/')),
|
||||
]
|
|
@ -1,11 +1,9 @@
|
|||
import json
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.client import Client, MULTIPART_CONTENT
|
||||
from django.test.client import MULTIPART_CONTENT, Client
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework import permissions
|
||||
from rest_framework import permissions, status
|
||||
|
||||
try:
|
||||
from django.urls import reverse
|
4
dj_rest_auth/tests/requirements.pip
Normal file
4
dj_rest_auth/tests/requirements.pip
Normal file
|
@ -0,0 +1,4 @@
|
|||
django-allauth>=0.25.0
|
||||
responses>=0.3.0
|
||||
flake8==2.4.0
|
||||
djangorestframework-simplejwt==4.4.0
|
|
@ -1,8 +1,11 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.split(os.path.split(__file__)[0])[0])
|
||||
|
||||
|
||||
logging.disable(logging.CRITICAL)
|
||||
ROOT_URLCONF = 'urls'
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = '%s/staticserve' % PROJECT_ROOT
|
||||
|
@ -65,11 +68,12 @@ TEMPLATES = [
|
|||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
|
||||
'dj_rest_auth.utils.JWTCookieAuthentication',
|
||||
)
|
||||
}
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.messages',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.humanize',
|
||||
|
@ -88,10 +92,10 @@ INSTALLED_APPS = [
|
|||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
|
||||
'rest_auth',
|
||||
'rest_auth.registration',
|
||||
'dj_rest_auth',
|
||||
'dj_rest_auth.registration',
|
||||
|
||||
'rest_framework_jwt'
|
||||
'rest_framework_simplejwt.token_blacklist'
|
||||
]
|
||||
|
||||
SECRET_KEY = "38dh*skf8sjfhs287dh&^hd8&3hdg*j2&sd"
|
|
@ -1,17 +1,17 @@
|
|||
from django.test import TestCase, override_settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core import mail
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
import json
|
||||
|
||||
from allauth.account import app_settings as account_app_settings
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core import mail
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils.encoding import force_text
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
from rest_auth.registration.views import RegisterView
|
||||
from rest_auth.registration.app_settings import register_permission_classes
|
||||
|
||||
from .mixins import TestsMixin, CustomPermissionClass
|
||||
from dj_rest_auth.registration.app_settings import register_permission_classes
|
||||
from dj_rest_auth.registration.views import RegisterView
|
||||
from .mixins import CustomPermissionClass, TestsMixin
|
||||
|
||||
try:
|
||||
from django.urls import reverse
|
||||
|
@ -154,8 +154,8 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertEqual('token' in self.response.json.keys(), True)
|
||||
self.token = self.response.json['token']
|
||||
self.assertEqual('access_token' in self.response.json.keys(), True)
|
||||
self.token = self.response.json['access_token']
|
||||
|
||||
def test_login_by_email(self):
|
||||
# starting test without allauth app
|
||||
|
@ -384,7 +384,7 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
"password": self.PASS
|
||||
}
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
self.token = self.response.json['token']
|
||||
self.token = self.response.json['access_token']
|
||||
self.get(self.user_url, status_code=200)
|
||||
|
||||
self.patch(self.user_url, data=self.BASIC_USER_DATA, status_code=200)
|
||||
|
@ -409,7 +409,6 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
|
||||
@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 = ()
|
||||
|
@ -428,7 +427,7 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
self.post(self.register_url, data={}, status_code=400)
|
||||
|
||||
result = self.post(self.register_url, data=self.REGISTRATION_DATA, status_code=201)
|
||||
self.assertIn('token', result.data)
|
||||
self.assertIn('access_token', result.data)
|
||||
self.assertEqual(get_user_model().objects.all().count(), user_count + 1)
|
||||
|
||||
self._login()
|
||||
|
@ -479,7 +478,7 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
)
|
||||
|
||||
# verify email
|
||||
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]
|
||||
self.post(
|
||||
self.verify_email_url,
|
||||
|
@ -516,3 +515,86 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
|
||||
self.post(self.login_url, data=payload, status_code=status.HTTP_200_OK)
|
||||
self.get(self.logout_url, status_code=status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
@override_settings(JWT_AUTH_COOKIE='jwt-auth')
|
||||
def test_login_jwt_sets_cookie(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertTrue('jwt-auth' in resp.cookies.keys())
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
@override_settings(JWT_AUTH_COOKIE='jwt-auth')
|
||||
def test_logout_jwt_deletes_cookie(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
self.post(self.login_url, data=payload, status_code=200)
|
||||
resp = self.post(self.logout_url, status=200)
|
||||
self.assertEqual('', resp.cookies.get('jwt-auth').value)
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
@override_settings(JWT_AUTH_COOKIE='jwt-auth')
|
||||
@override_settings(REST_FRAMEWORK=dict(
|
||||
DEFAULT_AUTHENTICATION_CLASSES=[
|
||||
'dj_rest_auth.utils.JWTCookieAuthentication'
|
||||
]
|
||||
))
|
||||
@override_settings(REST_SESSION_LOGIN=False)
|
||||
def test_cookie_authentication(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
self.assertEqual(['jwt-auth'], list(resp.cookies.keys()))
|
||||
resp = self.get('/protected-view/')
|
||||
self.assertEquals(resp.status_code, 200)
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
def test_blacklisting_not_installed(self):
|
||||
settings.INSTALLED_APPS.remove('rest_framework_simplejwt.token_blacklist')
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
token = resp.data['refresh_token']
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data["detail"],
|
||||
"Neither cookies or blacklist are enabled, so the token has not been deleted server side. "
|
||||
"Please make sure the token is deleted client side.")
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
def test_blacklisting(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
token = resp.data['refresh_token']
|
||||
# test refresh token not included in request data
|
||||
resp = self.post(self.logout_url, status=200)
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test token is invalid or expired
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': '1'})
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test successful logout
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
# test token is blacklisted
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test other TokenError, AttributeError, TypeError (invalid format)
|
||||
resp = self.post(self.logout_url, status=200, data=json.dumps({'refresh': token}))
|
||||
self.assertEqual(resp.status_code, 500)
|
|
@ -1,23 +1,21 @@
|
|||
import json
|
||||
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
from allauth.socialaccount.models import SocialApp
|
||||
from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.test.utils import override_settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from rest_framework import status
|
||||
|
||||
from .mixins import TestsMixin
|
||||
|
||||
try:
|
||||
from django.urls import reverse
|
||||
except ImportError:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from allauth.socialaccount.models import SocialApp
|
||||
from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL
|
||||
import responses
|
||||
|
||||
from rest_framework import status
|
||||
|
||||
from .mixins import TestsMixin
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF="tests.urls")
|
||||
class TestSocialAuth(TestsMixin, TestCase):
|
||||
|
@ -304,7 +302,7 @@ class TestSocialAuth(TestsMixin, TestCase):
|
|||
}
|
||||
|
||||
self.post(self.fb_login_url, data=payload, status_code=200)
|
||||
self.assertIn('token', self.response.json.keys())
|
||||
self.assertIn('access_token', self.response.json.keys())
|
||||
self.assertIn('user', self.response.json.keys())
|
||||
|
||||
self.assertEqual(get_user_model().objects.all().count(), users_count + 1)
|
|
@ -1,20 +1,28 @@
|
|||
from django.conf.urls import url, include
|
||||
from allauth.socialaccount.providers.facebook.views import \
|
||||
FacebookOAuth2Adapter
|
||||
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
||||
from dj_rest_auth.registration.views import (SocialAccountDisconnectView,
|
||||
SocialAccountListView,
|
||||
SocialConnectView,
|
||||
SocialLoginView)
|
||||
from dj_rest_auth.social_serializers import (TwitterConnectSerializer,
|
||||
TwitterLoginSerializer)
|
||||
from dj_rest_auth.urls import urlpatterns
|
||||
from django.conf.urls import include, url
|
||||
from django.views.generic import TemplateView
|
||||
from rest_framework import permissions
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from . import django_urls
|
||||
|
||||
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
|
||||
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
||||
|
||||
from rest_framework.decorators import api_view
|
||||
class ExampleProtectedView(APIView):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
from rest_auth.urls import urlpatterns
|
||||
from rest_auth.registration.views import (
|
||||
SocialLoginView, SocialConnectView, SocialAccountListView,
|
||||
SocialAccountDisconnectView
|
||||
)
|
||||
from rest_auth.social_serializers import (
|
||||
TwitterLoginSerializer, TwitterConnectSerializer
|
||||
)
|
||||
def get(self, *args, **kwargs):
|
||||
return Response(dict(success=True))
|
||||
|
||||
|
||||
class FacebookLogin(SocialLoginView):
|
||||
|
@ -53,7 +61,7 @@ class TwitterLoginNoAdapter(SocialLoginView):
|
|||
|
||||
|
||||
urlpatterns += [
|
||||
url(r'^rest-registration/', include('rest_auth.registration.urls')),
|
||||
url(r'^rest-registration/', include('dj_rest_auth.registration.urls')),
|
||||
url(r'^test-admin/', include(django_urls)),
|
||||
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
||||
name='account_email_verification_sent'),
|
||||
|
@ -66,6 +74,7 @@ urlpatterns += [
|
|||
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'^protected-view/$', ExampleProtectedView.as_view()),
|
||||
url(r'^socialaccounts/(?P<pk>\d+)/disconnect/$', SocialAccountDisconnectView.as_view(),
|
||||
name='social_account_disconnect'),
|
||||
url(r'^accounts/', include('allauth.socialaccount.urls'))
|
|
@ -1,9 +1,8 @@
|
|||
from dj_rest_auth.views import (LoginView, LogoutView, PasswordChangeView,
|
||||
PasswordResetConfirmView, PasswordResetView,
|
||||
UserDetailsView)
|
||||
from django.conf.urls import url
|
||||
|
||||
from rest_auth.views import (
|
||||
LoginView, LogoutView, UserDetailsView, PasswordChangeView,
|
||||
PasswordResetView, PasswordResetConfirmView
|
||||
)
|
||||
from django.conf import settings
|
||||
|
||||
urlpatterns = [
|
||||
# URLs that do not require a session or valid token
|
||||
|
@ -18,3 +17,13 @@ urlpatterns = [
|
|||
url(r'^password/change/$', PasswordChangeView.as_view(),
|
||||
name='rest_password_change'),
|
||||
]
|
||||
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
from rest_framework_simplejwt.views import (
|
||||
TokenRefreshView, TokenVerifyView,
|
||||
)
|
||||
|
||||
urlpatterns += [
|
||||
url(r'^token/verify/$', TokenVerifyView.as_view(), name='token_verify'),
|
||||
url(r'^token/refresh/$', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
]
|
56
dj_rest_auth/utils.py
Normal file
56
dj_rest_auth/utils.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
from importlib import import_module
|
||||
|
||||
|
||||
def import_callable(path_or_callable):
|
||||
if hasattr(path_or_callable, '__call__'):
|
||||
return path_or_callable
|
||||
else:
|
||||
assert isinstance(path_or_callable, str)
|
||||
package, attr = path_or_callable.rsplit('.', 1)
|
||||
return getattr(import_module(package), attr)
|
||||
|
||||
|
||||
def default_create_token(token_model, user, serializer):
|
||||
token, _ = token_model.objects.get_or_create(user=user)
|
||||
return token
|
||||
|
||||
|
||||
def jwt_encode(user):
|
||||
try:
|
||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||
except ImportError:
|
||||
raise ImportError("rest-framework-simplejwt needs to be installed")
|
||||
|
||||
refresh = TokenObtainPairSerializer.get_token(user)
|
||||
return refresh.access_token, refresh
|
||||
|
||||
|
||||
try:
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
|
||||
class JWTCookieAuthentication(JWTAuthentication):
|
||||
"""
|
||||
An authentication plugin that hopefully authenticates requests through a JSON web
|
||||
token provided in a request cookie (and through the header as normal, with a
|
||||
preference to the header).
|
||||
"""
|
||||
def authenticate(self, request):
|
||||
from django.conf import settings
|
||||
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
||||
header = self.get_header(request)
|
||||
if header is None:
|
||||
if cookie_name:
|
||||
raw_token = request.COOKIES.get(cookie_name)
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
raw_token = self.get_raw_token(header)
|
||||
|
||||
if raw_token is None:
|
||||
return None
|
||||
|
||||
validated_token = self.get_validated_token(raw_token)
|
||||
return self.get_user(validated_token), validated_token
|
||||
|
||||
except ImportError:
|
||||
pass
|
|
@ -1,25 +1,22 @@
|
|||
from django.contrib.auth import (
|
||||
login as django_login,
|
||||
logout as django_logout
|
||||
)
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth import login as django_login
|
||||
from django.contrib.auth import logout as django_logout
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.decorators import method_decorator
|
||||
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.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from .app_settings import (
|
||||
TokenSerializer, UserDetailsSerializer, LoginSerializer,
|
||||
PasswordResetSerializer, PasswordResetConfirmSerializer,
|
||||
PasswordChangeSerializer, JWTSerializer, create_token
|
||||
)
|
||||
from .app_settings import (JWTSerializer, LoginSerializer,
|
||||
PasswordChangeSerializer,
|
||||
PasswordResetConfirmSerializer,
|
||||
PasswordResetSerializer, TokenSerializer,
|
||||
UserDetailsSerializer, create_token)
|
||||
from .models import TokenModel
|
||||
from .utils import jwt_encode
|
||||
|
||||
|
@ -63,7 +60,7 @@ class LoginView(GenericAPIView):
|
|||
self.user = self.serializer.validated_data['user']
|
||||
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
self.token = jwt_encode(self.user)
|
||||
self.access_token, self.refresh_token = jwt_encode(self.user)
|
||||
else:
|
||||
self.token = create_token(self.token_model, self.user,
|
||||
self.serializer)
|
||||
|
@ -77,7 +74,8 @@ class LoginView(GenericAPIView):
|
|||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
data = {
|
||||
'user': self.user,
|
||||
'token': self.token
|
||||
'access_token': self.access_token,
|
||||
'refresh_token': self.refresh_token
|
||||
}
|
||||
serializer = serializer_class(instance=data,
|
||||
context={'request': self.request})
|
||||
|
@ -87,14 +85,17 @@ class LoginView(GenericAPIView):
|
|||
|
||||
response = 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:
|
||||
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
||||
from rest_framework_simplejwt.settings import api_settings as jwt_settings
|
||||
if cookie_name:
|
||||
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)
|
||||
expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME)
|
||||
response.set_cookie(
|
||||
cookie_name,
|
||||
self.access_token,
|
||||
expires=expiration,
|
||||
httponly=True
|
||||
)
|
||||
return response
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
@ -129,15 +130,58 @@ class LogoutView(APIView):
|
|||
return self.logout(request)
|
||||
|
||||
def logout(self, request):
|
||||
try:
|
||||
request.user.auth_token.delete()
|
||||
except (AttributeError, ObjectDoesNotExist):
|
||||
pass
|
||||
|
||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
||||
django_logout(request)
|
||||
|
||||
response = Response({"detail": _("Successfully logged out.")},
|
||||
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:
|
||||
response.delete_cookie(jwt_settings.JWT_AUTH_COOKIE)
|
||||
# NOTE: this import occurs here rather than at the top level
|
||||
# because JWT support is optional, and if `REST_USE_JWT` isn't
|
||||
# True we shouldn't need the dependency
|
||||
from rest_framework_simplejwt.exceptions import TokenError
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
||||
if cookie_name:
|
||||
response.delete_cookie(cookie_name)
|
||||
|
||||
elif 'rest_framework_simplejwt.token_blacklist' in settings.INSTALLED_APPS:
|
||||
# add refresh token to blacklist
|
||||
try:
|
||||
token = RefreshToken(request.data['refresh'])
|
||||
token.blacklist()
|
||||
|
||||
except KeyError:
|
||||
response = Response({"detail": _("Refresh token was not included in request data.")},
|
||||
status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
except (TokenError, AttributeError, TypeError) as error:
|
||||
if hasattr(error, 'args'):
|
||||
if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args:
|
||||
response = Response({"detail": _(error.args[0])},
|
||||
status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
else:
|
||||
response = Response({"detail": _("An error has occurred.")},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
else:
|
||||
response = Response({"detail": _("An error has occurred.")},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
else:
|
||||
response = Response({
|
||||
"detail": _("Neither cookies or blacklist are enabled, so the token has not been deleted server "
|
||||
"side. Please make sure the token is deleted client side."
|
||||
)}, status=status.HTTP_200_OK)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
@ -162,7 +206,6 @@ class UserDetailsView(RetrieveUpdateAPIView):
|
|||
"""
|
||||
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()
|
||||
|
|
@ -85,17 +85,17 @@ qthelp:
|
|||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-rest-auth.qhcp"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/dj-rest-auth.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-rest-auth.qhc"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/dj-rest-auth.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/django-rest-auth"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-rest-auth"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/dj-rest-auth"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/dj-rest-auth"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
|
|
|
@ -4,7 +4,7 @@ API endpoints
|
|||
Basic
|
||||
-----
|
||||
|
||||
- /rest-auth/login/ (POST)
|
||||
- /dj-rest-auth/login/ (POST)
|
||||
|
||||
- username
|
||||
- email
|
||||
|
@ -12,24 +12,24 @@ Basic
|
|||
|
||||
Returns Token key
|
||||
|
||||
- /rest-auth/logout/ (POST)
|
||||
- /dj-rest-auth/logout/ (POST)
|
||||
|
||||
.. 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
|
||||
|
||||
- /rest-auth/password/reset/ (POST)
|
||||
- /dj-rest-auth/password/reset/ (POST)
|
||||
|
||||
- email
|
||||
|
||||
- /rest-auth/password/reset/confirm/ (POST)
|
||||
- /dj-rest-auth/password/reset/confirm/ (POST)
|
||||
|
||||
- uid
|
||||
- token
|
||||
- new_password1
|
||||
- new_password2
|
||||
|
||||
.. note:: uid and token are sent in email after calling /rest-auth/password/reset/
|
||||
.. note:: uid and token are sent in email after calling /dj-rest-auth/password/reset/
|
||||
|
||||
- /rest-auth/password/change/ (POST)
|
||||
- /dj-rest-auth/password/change/ (POST)
|
||||
|
||||
- new_password1
|
||||
- new_password2
|
||||
|
@ -38,7 +38,7 @@ Basic
|
|||
.. 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
|
||||
|
||||
- /rest-auth/user/ (GET, PUT, PATCH)
|
||||
- /dj-rest-auth/user/ (GET, PUT, PATCH)
|
||||
|
||||
- username
|
||||
- first_name
|
||||
|
@ -50,31 +50,36 @@ Basic
|
|||
Registration
|
||||
------------
|
||||
|
||||
- /rest-auth/registration/ (POST)
|
||||
- /dj-rest-auth/registration/ (POST)
|
||||
|
||||
- username
|
||||
- password1
|
||||
- password2
|
||||
- email
|
||||
|
||||
- /rest-auth/registration/verify-email/ (POST)
|
||||
- /dj-rest-auth/registration/verify-email/ (POST)
|
||||
|
||||
- key
|
||||
|
||||
.. note:: If you set account email verification as mandatory, you have to add the VerifyEmailView with the used `name`.
|
||||
You need to import the view: ``from dj_rest_auth.registration.views import VerifyEmailView``. Then add the url with the corresponding name:
|
||||
``path('dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent')`` to the urlpatterns list.
|
||||
|
||||
|
||||
|
||||
Social Media Authentication
|
||||
---------------------------
|
||||
|
||||
Basing on example from installation section :doc:`Installation </installation>`
|
||||
|
||||
- /rest-auth/facebook/ (POST)
|
||||
- /dj-rest-auth/facebook/ (POST)
|
||||
|
||||
- access_token
|
||||
- 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
|
||||
.. note:: ``access_token`` OR ``code`` can be used as standalone arguments, see https://github.com/jazzband/dj-rest-auth/blob/master/dj_rest_auth/registration/views.py
|
||||
|
||||
- /rest-auth/twitter/ (POST)
|
||||
- /dj-rest-auth/twitter/ (POST)
|
||||
|
||||
- access_token
|
||||
- token_secret
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
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
|
||||
-----
|
||||
- added support for django-rest-framework-jwt
|
||||
- bugfixes
|
||||
|
||||
0.7.0
|
||||
-----
|
||||
- Wrapped API returned strings in ugettext_lazy
|
||||
- Fixed not using ``get_username`` which caused issues when using custom user model without username field
|
||||
- Django 1.9 support
|
||||
- Added ``TwitterLoginSerializer``
|
||||
|
||||
0.6.0
|
||||
-----
|
||||
- dropped support for Python 2.6
|
||||
- dropped support for Django 1.6
|
||||
- fixed demo code
|
||||
- added better validation support for serializers
|
||||
- added optional logout after password change
|
||||
- compatibility fixes
|
||||
- bugfixes
|
||||
|
||||
0.5.0
|
||||
-----
|
||||
- replaced request.DATA with request.data for compatibility with DRF 3.2
|
||||
- authorization codes for social login
|
||||
- view classes rename (appended "View" to all of them)
|
||||
- bugfixes
|
||||
|
||||
0.4.0
|
||||
-----
|
||||
- Django 1.8 compatiblity fixes
|
||||
|
||||
0.3.4
|
||||
-----
|
||||
- fixed bug in PasswordResetConfirmation serializer (token field wasn't validated)
|
||||
- fixed bug in Register view
|
||||
|
||||
0.3.3
|
||||
-----
|
||||
|
||||
- support django-rest-framework v3.0
|
||||
|
||||
0.3.2
|
||||
-----
|
||||
|
||||
- fixed few minor bugs
|
||||
|
||||
0.3.1
|
||||
-----
|
||||
|
||||
- added old_password field in PasswordChangeSerializer
|
||||
- make all endpoints browsable
|
||||
- removed LoggedInRESTAPIView, LoggedOutRESTAPIView
|
||||
- fixed minor bugs
|
||||
|
||||
0.3.0
|
||||
-----
|
||||
|
||||
- replaced ``django-registration`` with ``django-allauth``
|
||||
- moved registration logic to separated django application (``rest_auth.registration``)
|
||||
- added serializers customization in django settings
|
||||
- added social media authentication view
|
||||
- changed request method from GET to POST in logout endpoint
|
||||
- changed request method from POST to PUT/PATCH for user details edition
|
||||
- changed password reset confim url - uid and token should be sent in POST
|
||||
- increase test coverage
|
||||
- made compatibile with django 1.7
|
||||
- removed user profile support
|
30
docs/conf.py
30
docs/conf.py
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# django-rest-auth documentation build configuration file, created by
|
||||
# dj-rest-auth documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Oct 8 15:59:37 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
|
@ -12,8 +12,12 @@
|
|||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
|
||||
about = {}
|
||||
with open('../dj_rest_auth/__version__.py', 'r', encoding="utf8") as f:
|
||||
exec(f.read(), about)
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
|
@ -43,17 +47,17 @@ source_suffix = '.rst'
|
|||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'django-rest-auth'
|
||||
copyright = u'2018, Tivix Inc.'
|
||||
project = u'dj-rest-auth'
|
||||
copyright = u'2020, @iMerica'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.9.5'
|
||||
version = about['__version__']
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.9.5'
|
||||
release = about['__version__']
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -176,7 +180,7 @@ html_static_path = ['_static']
|
|||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'django-rest-authdoc'
|
||||
htmlhelp_basename = 'dj-rest-authdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
@ -196,8 +200,8 @@ latex_elements = {
|
|||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'django-rest-auth.tex', u'django-rest-auth Documentation',
|
||||
u'Tivix Inc.', 'manual'),
|
||||
('index', 'dj-rest-auth.tex', u'dj-rest-auth Documentation',
|
||||
u'iMerica Inc.', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -226,8 +230,8 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'django-rest-auth', u'django-rest-auth Documentation',
|
||||
[u'Tivix Inc.'], 1)
|
||||
('index', 'dj-rest-auth', u'dj-rest-auth Documentation',
|
||||
[u'@iMerica'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
|
@ -240,8 +244,8 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'django-rest-auth', u'django-rest-auth Documentation',
|
||||
u'Tivix Inc.', 'django-rest-auth', 'One line description of project.',
|
||||
('index', 'dj-rest-auth', u'dj-rest-auth Documentation',
|
||||
u'@iMerica', 'dj-rest-auth', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
|
|
@ -6,19 +6,19 @@ Configuration
|
|||
You can define your custom serializers for each endpoint without overriding urls and views by adding ``REST_AUTH_SERIALIZERS`` dictionary in your django settings.
|
||||
Possible key values:
|
||||
|
||||
- LOGIN_SERIALIZER - serializer class in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.LoginSerializer``
|
||||
- LOGIN_SERIALIZER - serializer class in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.LoginSerializer``
|
||||
|
||||
- TOKEN_SERIALIZER - response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.TokenSerializer``
|
||||
- TOKEN_SERIALIZER - response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.TokenSerializer``
|
||||
|
||||
- JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``rest_auth.views.LoginView``, default value ``rest_auth.serializers.JWTSerializer``
|
||||
- JWT_SERIALIZER - (Using REST_USE_JWT=True) response for successful authentication in ``dj_rest_auth.views.LoginView``, default value ``dj_rest_auth.serializers.JWTSerializer``
|
||||
|
||||
- USER_DETAILS_SERIALIZER - serializer class in ``rest_auth.views.UserDetailsView``, default value ``rest_auth.serializers.UserDetailsSerializer``
|
||||
- USER_DETAILS_SERIALIZER - serializer class in ``dj_rest_auth.views.UserDetailsView``, default value ``dj_rest_auth.serializers.UserDetailsSerializer``
|
||||
|
||||
- PASSWORD_RESET_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetView``, default value ``rest_auth.serializers.PasswordResetSerializer``
|
||||
- PASSWORD_RESET_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetView``, default value ``dj_rest_auth.serializers.PasswordResetSerializer``
|
||||
|
||||
- PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``rest_auth.views.PasswordResetConfirmView``, default value ``rest_auth.serializers.PasswordResetConfirmSerializer``
|
||||
- PASSWORD_RESET_CONFIRM_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordResetConfirmView``, default value ``dj_rest_auth.serializers.PasswordResetConfirmSerializer``
|
||||
|
||||
- PASSWORD_CHANGE_SERIALIZER - serializer class in ``rest_auth.views.PasswordChangeView``, default value ``rest_auth.serializers.PasswordChangeSerializer``
|
||||
- PASSWORD_CHANGE_SERIALIZER - serializer class in ``dj_rest_auth.views.PasswordChangeView``, default value ``dj_rest_auth.serializers.PasswordChangeSerializer``
|
||||
|
||||
|
||||
Example configuration:
|
||||
|
@ -36,18 +36,18 @@ Configuration
|
|||
You can define your custom serializers for registration endpoint.
|
||||
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 ``dj_rest_auth.registration.views.RegisterView``, default value ``dj_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** - path to model class for tokens, default value ``'rest_framework.authtoken.models.Token'``
|
||||
|
||||
- **REST_AUTH_TOKEN_CREATOR** - callable to create tokens, default value ``rest_auth.utils.default_create_token``.
|
||||
- **REST_AUTH_TOKEN_CREATOR** - path to callable or callable for creating tokens, default value ``dj_rest_auth.utils.default_create_token``.
|
||||
|
||||
- **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True)
|
||||
|
||||
- **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of django-rest-framework-jwt http://getblimp.github.io/django-rest-framework-jwt/, which must also be installed. (default: False)
|
||||
|
||||
- **REST_USE_JWT** - Enable JWT Authentication instead of Token/Session based. This is built on top of djangorestframework-simplejwt https://github.com/SimpleJWT/django-rest-framework-simplejwt, which must also be installed. (default: False)
|
||||
- **JWT_AUTH_COOKIE** - The cookie name/key.
|
||||
- **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
|
||||
|
|
|
@ -1,17 +1,28 @@
|
|||
Demo project
|
||||
============
|
||||
|
||||
The idea of creating demo project was to show how you can potentially use
|
||||
django-rest-auth app with jQuery on frontend.
|
||||
Do these steps to make it running (ideally in virtualenv).
|
||||
This demo project shows how you can potentially use
|
||||
dj-rest-auth app with jQuery on frontend.
|
||||
To run this locally follow the steps below.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
cd /tmp
|
||||
git clone https://github.com/Tivix/django-rest-auth.git
|
||||
cd django-rest-auth/demo/
|
||||
git clone https://github.com/jazzband/dj-rest-auth.git
|
||||
cd dj-rest-auth/demo/
|
||||
pip install -r requirements.pip
|
||||
python manage.py migrate --settings=demo.settings --noinput
|
||||
python manage.py runserver --settings=demo.settings
|
||||
|
||||
Now, go to ``http://127.0.0.1:8000/`` in your browser.
|
||||
|
||||
Now, go to ``http://127.0.0.1:8000/`` in your browser. There is also a
|
||||
Single Page Application (SPA) in React within the ``demo/`` directory. To run this do:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
cd react-spa/
|
||||
yarn # or npm install
|
||||
yarn run start
|
||||
|
||||
|
||||
Now, go to ``https://localhost:3000`` in your browser to view it.
|
||||
|
|
15
docs/disclosure.rst
Normal file
15
docs/disclosure.rst
Normal file
|
@ -0,0 +1,15 @@
|
|||
Vulnerability Disclosure Policy
|
||||
===============================
|
||||
|
||||
Please observe the standard best practices of responsible disclosure, especially considering that this is OSS.
|
||||
See OWASP's disclosure `cheat sheet <https://cheatsheetseries.owasp.org/cheatsheets/Vulnerability_Disclosure_Cheat_Sheet.html>`_.
|
||||
|
||||
Some basic rules:
|
||||
|
||||
- Keep it legal.
|
||||
- Respect everyone's privacy.
|
||||
- Contact the core maintainer(s) immediately if you discover a serious security vulnerability (imichael@pm.me for now).
|
||||
|
||||
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ FAQ
|
|||
|
||||
1. Why account_confirm_email url is defined but it is not usable?
|
||||
|
||||
In /rest_auth/registration/urls.py we can find something like this:
|
||||
In /dj_rest_auth/registration/urls.py we can find something like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -36,12 +36,12 @@ FAQ
|
|||
# custom fields for user
|
||||
company_name = models.CharField(max_length=100)
|
||||
|
||||
To allow update user details within one request send to rest_auth.views.UserDetailsView view, create serializer like this:
|
||||
To allow update user details within one request send to dj_rest_auth.views.UserDetailsView view, create serializer like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_auth.serializers import UserDetailsSerializer
|
||||
from dj_rest_auth.serializers import UserDetailsSerializer
|
||||
|
||||
class UserSerializer(UserDetailsSerializer):
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
.. django-rest-auth documentation master file, created by
|
||||
.. dj-rest-auth documentation master file, created by
|
||||
sphinx-quickstart on Wed Oct 8 15:59:37 2014.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to django-rest-auth's documentation!
|
||||
Welcome to dj-rest-auth's documentation!
|
||||
============================================
|
||||
|
||||
.. warning:: Updating django-rest-auth from version **0.3.3** is highly recommended because of a security issue in PasswordResetConfirmation validation method.
|
||||
|
||||
.. note:: django-rest-auth from v0.3.3 supports django-rest-framework v3.0
|
||||
.. note:: dj-rest-auth version 1.0.0 now uses Django Simple JWT.
|
||||
|
||||
|
||||
|build-status| |coverage-status| |requirements-status| |docs|
|
||||
.. image:: https://circleci.com/gh/jazzband/dj-rest-auth.svg?style=svg
|
||||
:target: https://circleci.com/gh/jazzband/dj-rest-auth
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
@ -25,28 +25,4 @@ Contents
|
|||
Configuration <configuration>
|
||||
Demo project <demo>
|
||||
FAQ <faq>
|
||||
Changelog <changelog>
|
||||
|
||||
|
||||
.. |build-status| image:: https://travis-ci.org/Tivix/django-rest-auth.svg?branch=master
|
||||
:alt: build status
|
||||
:scale: 100%
|
||||
:target: https://travis-ci.org/Tivix/django-rest-auth
|
||||
|
||||
|
||||
.. |coverage-status| image:: https://coveralls.io/repos/Tivix/django-rest-auth/badge.png?branch=master
|
||||
:alt: coverage status
|
||||
:scale: 100%
|
||||
:target: https://coveralls.io/r/Tivix/django-rest-auth?branch=master
|
||||
|
||||
|
||||
.. |requirements-status| image:: https://requires.io/github/Tivix/django-rest-auth/requirements.png?branch=master
|
||||
:alt: requirements status
|
||||
:scale: 100%
|
||||
:target: https://requires.io/github/Tivix/django-rest-auth/requirements/?branch=master
|
||||
|
||||
|
||||
.. |docs| image:: https://readthedocs.org/projects/django-rest-auth/badge/?version=latest
|
||||
:scale: 100%
|
||||
:target: https://readthedocs.org/projects/django-rest-auth/?badge=latest
|
||||
:alt: Documentation Status
|
||||
Disclosure Policy <disclosure>
|
||||
|
|
|
@ -5,9 +5,9 @@ Installation
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
pip install django-rest-auth
|
||||
pip install dj-rest-auth
|
||||
|
||||
2. Add ``rest_auth`` app to INSTALLED_APPS in your django settings.py:
|
||||
2. Add ``dj_rest_auth`` app to INSTALLED_APPS in your django settings.py:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -16,19 +16,19 @@ Installation
|
|||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
...,
|
||||
'rest_auth'
|
||||
'dj_rest_auth'
|
||||
)
|
||||
|
||||
|
||||
.. note:: This project depends on ``django-rest-framework`` library, so install it if you haven't done yet. Make sure also you have installed ``rest_framework`` and ``rest_framework.authtoken`` apps
|
||||
|
||||
3. Add rest_auth urls:
|
||||
3. Add dj_rest_auth urls:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
urlpatterns = [
|
||||
...,
|
||||
url(r'^rest-auth/', include('rest_auth.urls'))
|
||||
path('dj-rest-auth/', include('dj_rest_auth.urls'))
|
||||
]
|
||||
|
||||
4. Migrate your database
|
||||
|
@ -44,9 +44,9 @@ You're good to go now!
|
|||
Registration (optional)
|
||||
-----------------------
|
||||
|
||||
1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install django-rest-auth[with_social]``.
|
||||
1. If you want to enable standard registration process you will need to install ``django-allauth`` by using ``pip install 'dj-rest-auth[with_social]'``.
|
||||
|
||||
2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py:
|
||||
2. Add ``django.contrib.sites``, ``allauth``, ``allauth.account`` and ``dj_rest_auth.registration`` apps to INSTALLED_APPS in your django settings.py:
|
||||
|
||||
3. Add ``SITE_ID = 1`` to your django settings.py
|
||||
|
||||
|
@ -57,26 +57,26 @@ Registration (optional)
|
|||
'django.contrib.sites',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'rest_auth.registration',
|
||||
'dj_rest_auth.registration',
|
||||
)
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
3. Add rest_auth.registration urls:
|
||||
3. Add dj_rest_auth.registration urls:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
urlpatterns = [
|
||||
...,
|
||||
url(r'^rest-auth/', include('rest_auth.urls')),
|
||||
url(r'^rest-auth/registration/', include('rest_auth.registration.urls'))
|
||||
path('dj-rest-auth/', include('dj_rest_auth.urls')),
|
||||
path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls'))
|
||||
]
|
||||
|
||||
|
||||
Social Authentication (optional)
|
||||
--------------------------------
|
||||
|
||||
Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creating social media authentication view.
|
||||
Using ``django-allauth``, ``dj-rest-auth`` provides helpful class for creating social media authentication view.
|
||||
|
||||
.. note:: Points 1 and 2 are related to ``django-allauth`` configuration, so if you have already configured social authentication, then please go to step 3. See ``django-allauth`` documentation for more details.
|
||||
|
||||
|
@ -88,12 +88,12 @@ Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creati
|
|||
...,
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
'rest_auth'
|
||||
'dj_rest_auth'
|
||||
...,
|
||||
'django.contrib.sites',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'rest_auth.registration',
|
||||
'dj_rest_auth.registration',
|
||||
...,
|
||||
'allauth.socialaccount',
|
||||
'allauth.socialaccount.providers.facebook',
|
||||
|
@ -106,12 +106,12 @@ Using ``django-allauth``, ``django-rest-auth`` provides helpful class for creati
|
|||
Facebook
|
||||
########
|
||||
|
||||
3. Create new view as a subclass of ``rest_auth.registration.views.SocialLoginView`` with ``FacebookOAuth2Adapter`` adapter as an attribute:
|
||||
3. Create new view as a subclass of ``dj_rest_auth.registration.views.SocialLoginView`` with ``FacebookOAuth2Adapter`` adapter as an attribute:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
|
||||
from rest_auth.registration.views import SocialLoginView
|
||||
from dj_rest_auth.registration.views import SocialLoginView
|
||||
|
||||
class FacebookLogin(SocialLoginView):
|
||||
adapter_class = FacebookOAuth2Adapter
|
||||
|
@ -122,7 +122,7 @@ Facebook
|
|||
|
||||
urlpatterns += [
|
||||
...,
|
||||
url(r'^rest-auth/facebook/$', FacebookLogin.as_view(), name='fb_login')
|
||||
path('dj-rest-auth/facebook/', FacebookLogin.as_view(), name='fb_login')
|
||||
]
|
||||
|
||||
|
||||
|
@ -131,13 +131,13 @@ Twitter
|
|||
|
||||
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 ``dj_rest_auth.registration.views.SocialLoginView`` with ``TwitterOAuthAdapter`` adapter and ``TwitterLoginSerializer`` as an attribute:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
|
||||
from rest_auth.registration.views import SocialLoginView
|
||||
from rest_auth.social_serializers import TwitterLoginSerializer
|
||||
from dj_rest_auth.registration.views import SocialLoginView
|
||||
from dj_rest_auth.social_serializers import TwitterLoginSerializer
|
||||
|
||||
class TwitterLogin(SocialLoginView):
|
||||
serializer_class = TwitterLoginSerializer
|
||||
|
@ -149,7 +149,7 @@ If you are using Twitter for your social authentication, it is a bit different s
|
|||
|
||||
urlpatterns += [
|
||||
...,
|
||||
url(r'^rest-auth/twitter/$', TwitterLogin.as_view(), name='twitter_login')
|
||||
path('dj-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.
|
||||
|
@ -160,13 +160,13 @@ GitHub
|
|||
|
||||
If you are using GitHub for your social authentication, it uses code and not AccessToken directly.
|
||||
|
||||
3. Create new view as a subclass of ``rest_auth.views.SocialLoginView`` with ``GitHubOAuth2Adapter`` adapter, an ``OAuth2Client`` and a callback_url as attributes:
|
||||
3. Create new view as a subclass of ``dj_rest_auth.views.SocialLoginView`` with ``GitHubOAuth2Adapter`` adapter, an ``OAuth2Client`` and a callback_url as attributes:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter
|
||||
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
|
||||
from rest_auth.registration.views import SocialLoginView
|
||||
from dj_rest_auth.registration.views import SocialLoginView
|
||||
|
||||
class GithubLogin(SocialLoginView):
|
||||
adapter_class = GitHubOAuth2Adapter
|
||||
|
@ -179,7 +179,7 @@ If you are using GitHub for your social authentication, it uses code and not Acc
|
|||
|
||||
urlpatterns += [
|
||||
...,
|
||||
url(r'^rest-auth/github/$', GitHubLogin.as_view(), name='github_login')
|
||||
path('dj-rest-auth/github/', GitHubLogin.as_view(), name='github_login')
|
||||
]
|
||||
|
||||
Additional Social Connect Views
|
||||
|
@ -193,8 +193,8 @@ If you want to allow connecting existing accounts in addition to login, you can
|
|||
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
|
||||
from dj_rest_auth.registration.views import SocialConnectView
|
||||
from dj_rest_auth.social_serializers import TwitterConnectSerializer
|
||||
|
||||
class FacebookConnect(SocialConnectView):
|
||||
adapter_class = FacebookOAuth2Adapter
|
||||
|
@ -215,28 +215,28 @@ In urls.py:
|
|||
|
||||
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')
|
||||
path('dj-rest-auth/facebook/connect/', FacebookConnect.as_view(), name='fb_connect')
|
||||
path('dj-rest-auth/twitter/connect/', TwitterConnect.as_view(), name='twitter_connect')
|
||||
path('dj-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 (
|
||||
from dj_rest_auth.registration.views import (
|
||||
SocialAccountListView, SocialAccountDisconnectView
|
||||
)
|
||||
|
||||
urlpatterns += [
|
||||
...,
|
||||
url(
|
||||
r'^socialaccounts/$',
|
||||
path(
|
||||
'socialaccounts/',
|
||||
SocialAccountListView.as_view(),
|
||||
name='social_account_list'
|
||||
),
|
||||
url(
|
||||
r'^socialaccounts/(?P<pk>\d+)/disconnect/$',
|
||||
path(
|
||||
'socialaccounts/<int:pk>/disconnect/',
|
||||
SocialAccountDisconnectView.as_view(),
|
||||
name='social_account_disconnect'
|
||||
)
|
||||
|
@ -246,15 +246,41 @@ You can also use the following views to check all social accounts attached to th
|
|||
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:
|
||||
By default ``dj-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.
|
||||
1. Install `djangorestframework-simplejwt <https://github.com/SimpleJWT/django-rest-framework-simplejwt/>`_
|
||||
- ``djangorestframework-simplejwt`` is currently the only supported JWT library.
|
||||
|
||||
3. Add the following configuration value to your settings file to enable JWT authentication.
|
||||
2. Add a simple_jwt auth configuration to the list of authentication classes.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
...
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
...
|
||||
'dj_rest_auth.utils.JWTCookieAuthentication',
|
||||
)
|
||||
...
|
||||
}
|
||||
|
||||
3. Add the following configuration value to your settings file to enable JWT authentication in dj-rest-auth.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
REST_USE_JWT = True
|
||||
|
||||
4. Declare what you want the cookie key to be called.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
JWT_AUTH_COOKIE = 'my-app-auth'
|
||||
|
||||
|
||||
This example value above will cause dj-rest-auth to return a `Set-Cookie` header that looks like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
Set-Cookie: my-app-auth=xxxxxxxxxxxxx; expires=Sat, 28 Mar 2020 18:59:00 GMT; HttpOnly; Max-Age=300; Path=/
|
||||
|
||||
``JWT_AUTH_COOKIE`` is also used while authenticating each request against protected views.
|
||||
|
|
|
@ -2,7 +2,7 @@ Introduction
|
|||
============
|
||||
|
||||
|
||||
Since the introduction of django-rest-framework, Django apps have been able to serve up app-level REST API endpoints. As a result, we saw a lot of instances where developers implemented their own REST registration API endpoints here and there, snippets, and so on. We aim to solve this demand by providing django-rest-auth, a set of REST API endpoints to handle User Registration and Authentication tasks. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for User Management. Of course, we'll add more API endpoints as we see the demand.
|
||||
Since the introduction of django-rest-framework, Django apps have been able to serve up app-level REST API endpoints. As a result, we saw a lot of instances where developers implemented their own REST registration API endpoints here and there, snippets, and so on. We aim to solve this demand by providing dj-rest-auth, a set of REST API endpoints to handle User Registration and Authentication tasks. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for User Management. Of course, we'll add more API endpoints as we see the demand.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
@ -18,14 +18,14 @@ Features
|
|||
Apps structure
|
||||
--------------
|
||||
|
||||
* ``rest_auth`` has basic auth functionality like login, logout, password reset and password change
|
||||
* ``rest_auth.registration`` has logic related with registration and social media authentication
|
||||
* ``dj_rest_auth`` has basic auth functionality like login, logout, password reset and password change
|
||||
* ``dj_rest_auth.registration`` has logic related with registration and social media authentication
|
||||
|
||||
|
||||
Angular app
|
||||
-----------
|
||||
|
||||
- Tivix has also created angular module which uses API endpoints from this app - `angular-django-registration-auth <https://github.com/Tivix/angular-django-registration-auth>`_
|
||||
- iMerica has also created angular module which uses API endpoints from this app - `angular-django-registration-auth <https://github.com/iMerica/angular-django-registration-auth>`_
|
||||
|
||||
|
||||
Demo project
|
||||
|
|
|
@ -115,9 +115,9 @@ if "%1" == "qthelp" (
|
|||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-rest-auth.qhcp
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\dj-rest-auth.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-rest-auth.ghc
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\dj-rest-auth.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
from django.conf import settings
|
||||
|
||||
from rest_auth.serializers import (
|
||||
TokenSerializer as DefaultTokenSerializer,
|
||||
JWTSerializer as DefaultJWTSerializer,
|
||||
UserDetailsSerializer as DefaultUserDetailsSerializer,
|
||||
LoginSerializer as DefaultLoginSerializer,
|
||||
PasswordResetSerializer as DefaultPasswordResetSerializer,
|
||||
PasswordResetConfirmSerializer as DefaultPasswordResetConfirmSerializer,
|
||||
PasswordChangeSerializer as DefaultPasswordChangeSerializer)
|
||||
from .utils import import_callable, default_create_token
|
||||
|
||||
create_token = import_callable(
|
||||
getattr(settings, 'REST_AUTH_TOKEN_CREATOR', default_create_token))
|
||||
|
||||
serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
|
||||
|
||||
TokenSerializer = import_callable(
|
||||
serializers.get('TOKEN_SERIALIZER', DefaultTokenSerializer))
|
||||
|
||||
JWTSerializer = import_callable(
|
||||
serializers.get('JWT_SERIALIZER', DefaultJWTSerializer))
|
||||
|
||||
UserDetailsSerializer = import_callable(
|
||||
serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer)
|
||||
)
|
||||
|
||||
LoginSerializer = import_callable(
|
||||
serializers.get('LOGIN_SERIALIZER', DefaultLoginSerializer)
|
||||
)
|
||||
|
||||
PasswordResetSerializer = import_callable(
|
||||
serializers.get(
|
||||
'PASSWORD_RESET_SERIALIZER',
|
||||
DefaultPasswordResetSerializer
|
||||
)
|
||||
)
|
||||
|
||||
PasswordResetConfirmSerializer = import_callable(
|
||||
serializers.get(
|
||||
'PASSWORD_RESET_CONFIRM_SERIALIZER',
|
||||
DefaultPasswordResetConfirmSerializer
|
||||
)
|
||||
)
|
||||
|
||||
PasswordChangeSerializer = import_callable(
|
||||
serializers.get(
|
||||
'PASSWORD_CHANGE_SERIALIZER',
|
||||
DefaultPasswordChangeSerializer
|
||||
)
|
||||
)
|
BIN
rest_auth/locale/sv/LC_MESSAGES/django.mo
Normal file
BIN
rest_auth/locale/sv/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
107
rest_auth/locale/sv/LC_MESSAGES/django.po
Normal file
107
rest_auth/locale/sv/LC_MESSAGES/django.po
Normal file
|
@ -0,0 +1,107 @@
|
|||
# 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: 2020-05-10 12:48+0000\n"
|
||||
"PO-Revision-Date: 2020-05-10 15:04+0200\n"
|
||||
"Language: sv\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.4\n"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:67
|
||||
msgid "View is not defined, pass it as a context variable"
|
||||
msgstr "Vyn definieras inte, skicka den som en kontextvariabel"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:72
|
||||
msgid "Define adapter_class in view"
|
||||
msgstr "Definiera “adapter_class” i vyn"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:91
|
||||
msgid "Define callback_url in view"
|
||||
msgstr "Definiera “callback_url” i vyn"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:95
|
||||
msgid "Define client_class in view"
|
||||
msgstr "Definiera “client_class” i vyn"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:116
|
||||
msgid "Incorrect input. access_token or code is required."
|
||||
msgstr "Felaktig inmatning. access_token eller code krävs."
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:125
|
||||
msgid "Incorrect value"
|
||||
msgstr "Felaktigt värde"
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:139
|
||||
msgid "User is already registered with this e-mail address."
|
||||
msgstr "Användaren är redan registrerad med den här e-postadressen."
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:185
|
||||
msgid "A user is already registered with this e-mail address."
|
||||
msgstr "En användare är redan registrerad med den här e-postadressen."
|
||||
|
||||
#: rest_auth/rest_auth/registration/serializers.py:193
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "De två lösenordsfälten matchade inte."
|
||||
|
||||
#: rest_auth/rest_auth/registration/views.py:51
|
||||
msgid "Verification e-mail sent."
|
||||
msgstr "Verifikationsmail har skickats."
|
||||
|
||||
#: rest_auth/rest_auth/registration/views.py:98
|
||||
msgid "ok"
|
||||
msgstr "ok"
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:33
|
||||
msgid "Must include \"email\" and \"password\"."
|
||||
msgstr "Måste inkludera “email” och “password”."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:44
|
||||
msgid "Must include \"username\" and \"password\"."
|
||||
msgstr "Måste innehålla “username” och “password”."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:57
|
||||
msgid "Must include either \"username\" or \"email\" and \"password\"."
|
||||
msgstr "Måste innehålla antingen “username” eller “email” och “password”."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:98
|
||||
msgid "User account is disabled."
|
||||
msgstr "Användarkontot är avstängt."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:101
|
||||
msgid "Unable to log in with provided credentials."
|
||||
msgstr "Det går inte att logga in med de angivna uppgifterna."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:110
|
||||
msgid "E-mail is not verified."
|
||||
msgstr "E-post är inte verifierad."
|
||||
|
||||
#: rest_auth/rest_auth/serializers.py:259
|
||||
msgid "Your old password was entered incorrectly. Please enter it again."
|
||||
msgstr "Ditt gamla lösenord angavs felaktigt. Vänligen ange det igen."
|
||||
|
||||
#: rest_auth/rest_auth/views.py:137
|
||||
msgid "Successfully logged out."
|
||||
msgstr "Utloggad."
|
||||
|
||||
#: rest_auth/rest_auth/views.py:190
|
||||
msgid "Password reset e-mail has been sent."
|
||||
msgstr "E-post för återställning av lösenord har skickats."
|
||||
|
||||
#: rest_auth/rest_auth/views.py:216
|
||||
msgid "Password has been reset with the new password."
|
||||
msgstr "Lösenordet har återställts med det nya lösenordet."
|
||||
|
||||
#: rest_auth/rest_auth/views.py:238
|
||||
msgid "New password has been saved."
|
||||
msgstr "Nytt lösenord har sparats."
|
|
@ -1,10 +0,0 @@
|
|||
from django.conf import settings
|
||||
|
||||
from rest_framework.authtoken.models import Token as DefaultTokenModel
|
||||
|
||||
from .utils import import_callable
|
||||
|
||||
# Register your models here.
|
||||
|
||||
TokenModel = import_callable(
|
||||
getattr(settings, 'REST_AUTH_TOKEN_MODEL', DefaultTokenModel))
|
|
@ -1,30 +0,0 @@
|
|||
# Moved in Django 1.8 from django to tests/auth_tests/urls.py
|
||||
|
||||
from django.conf.urls import url
|
||||
from django.contrib.auth import views
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.urls import urlpatterns
|
||||
|
||||
|
||||
# special urls for auth test cases
|
||||
urlpatterns += [
|
||||
url(r'^logout/custom_query/$', views.logout, dict(redirect_field_name='follow')),
|
||||
url(r'^logout/next_page/$', views.logout, dict(next_page='/somewhere/')),
|
||||
url(r'^logout/next_page/named/$', views.logout, dict(next_page='password_reset')),
|
||||
url(r'^password_reset_from_email/$', views.password_reset, dict(from_email='staffmember@example.com')),
|
||||
url(r'^password_reset/custom_redirect/$', views.password_reset, dict(post_reset_redirect='/custom/')),
|
||||
url(r'^password_reset/custom_redirect/named/$', views.password_reset, dict(post_reset_redirect='password_reset')),
|
||||
url(r'^password_reset/html_email_template/$', views.password_reset,
|
||||
dict(html_email_template_name='registration/html_password_reset_email.html')),
|
||||
url(r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
|
||||
views.password_reset_confirm,
|
||||
dict(post_reset_redirect='/custom/')),
|
||||
url(r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
|
||||
views.password_reset_confirm,
|
||||
dict(post_reset_redirect='password_reset')),
|
||||
url(r'^password_change/custom/$', views.password_change, dict(post_change_redirect='/custom/')),
|
||||
url(r'^password_change/custom/named/$', views.password_change, dict(post_change_redirect='password_reset')),
|
||||
url(r'^admin_password_reset/$', views.password_reset, dict(is_admin_site=True)),
|
||||
url(r'^login_required/$', login_required(views.password_reset)),
|
||||
url(r'^login_required_login_url/$', login_required(views.password_reset, login_url='/somewhere/')),
|
||||
]
|
|
@ -1,5 +0,0 @@
|
|||
django-allauth>=0.25.0
|
||||
responses>=0.3.0
|
||||
flake8==2.4.0
|
||||
djangorestframework-jwt>=1.7.2
|
||||
djangorestframework>=3.6.4
|
|
@ -1,29 +0,0 @@
|
|||
from six import string_types
|
||||
from importlib import import_module
|
||||
|
||||
|
||||
def import_callable(path_or_callable):
|
||||
if hasattr(path_or_callable, '__call__'):
|
||||
return path_or_callable
|
||||
else:
|
||||
assert isinstance(path_or_callable, string_types)
|
||||
package, attr = path_or_callable.rsplit('.', 1)
|
||||
return getattr(import_module(package), attr)
|
||||
|
||||
|
||||
def default_create_token(token_model, user, serializer):
|
||||
token, _ = token_model.objects.get_or_create(user=user)
|
||||
return token
|
||||
|
||||
|
||||
def jwt_encode(user):
|
||||
try:
|
||||
from rest_framework_jwt.settings import api_settings
|
||||
except ImportError:
|
||||
raise ImportError("djangorestframework_jwt needs to be installed")
|
||||
|
||||
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
||||
|
||||
payload = jwt_payload_handler(user)
|
||||
return jwt_encode_handler(payload)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user