Merge pull request #17 from Tivix/develop

Develop
This commit is contained in:
Mateusz Sikora 2014-10-16 13:34:01 +02:00
commit 6e76b2e3ee
28 changed files with 651 additions and 3 deletions

1
.gitignore vendored
View File

@ -53,3 +53,4 @@ coverage.xml
docs/_build/
.DS_Store
db.sqlite3

0
demo/demo/__init__.py Normal file
View File

107
demo/demo/settings.py Normal file
View File

@ -0,0 +1,107 @@
"""
Django settings for demo project.
For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'ma3c@7uu!%e0=tynp+i6+q%$)9v@$t(eulqurym_b=48z82&5n'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
"django.core.context_processors.request",
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount",
)
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
# 'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'allauth',
'allauth.account',
'rest_auth.registration',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'demo.urls'
WSGI_APPLICATION = 'demo.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/static/'
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
REST_SESSION_LOGIN = False
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
SITE_ID = 1
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'

37
demo/demo/urls.py Normal file
View File

@ -0,0 +1,37 @@
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView
urlpatterns = patterns('',
url(r'^$', TemplateView.as_view(template_name="home.html"), name='home'),
url(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
name='signup'),
url(r'^email-verification/$',
TemplateView.as_view(template_name="email_verification.html"),
name='email-verification'),
url(r'^login/$', TemplateView.as_view(template_name="login.html"),
name='login'),
url(r'^password-reset/$',
TemplateView.as_view(template_name="password_reset.html"),
name='password-reset'),
url(r'^password-reset/confirm/$',
TemplateView.as_view(template_name="password_reset_confirm.html"),
name='password-reset-confirm'),
url(r'^user-details/$',
TemplateView.as_view(template_name="user_details.html"),
name='user-details'),
url(r'^password-change/$',
TemplateView.as_view(template_name="password_change.html"),
name='password-change'),
# this url is used to generate email content
url(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
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'^admin/', include(admin.site.urls)),
)

14
demo/demo/wsgi.py Normal file
View File

@ -0,0 +1,14 @@
"""
WSGI config for demo project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
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
application = get_wsgi_application()

10
demo/manage.py Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

3
demo/requirements.pip Normal file
View File

@ -0,0 +1,3 @@
django==1.7
django-rest-auth==0.3.0
django-allauth==0.18.0

96
demo/templates/base.html Normal file
View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<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.">
<title>Starter Template for Bootstrap</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body role="document">
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API endpoints <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<!-- these pages don't require user token -->
<li><a href="{% url 'signup' %}">Signup</a></li>
<li><a href="{% url 'email-verification' %}">E-mail verification</a></li>
<li><a href="{% url 'login' %}">Login</a></li>
<li><a href="{% url 'password-reset' %}">Password Reset</a></li>
<li><a href="{% url 'password-reset-confirm' %}">Password Reset Confirm</a></li>
<li class="divider"></li>
<!-- these pages require user token -->
<li><a href="{% url 'user-details' %}">User details</a></li>
<li><a href="{% url 'password-change' %}">Password change</a></li>
</ul>
</li>
</ul>
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">django-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>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="container theme-showcase" role="main">
{% block content %}{% endblock %}
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
var error_response = function(data){
$('.api-response').html("API Response: " + data.status + ' ' + data.statusText + '<br/>Content: ' + data.responseText);
}
var susccess_response = function(data){
$('.api-response').html("API Response: OK<br/>Content: " + JSON.stringify(data));
}
$().ready(function(){
$('form.ajax-post button[type=submit]').click(function(){
var form = $('form.ajax-post');
$.post(form.attr('action'), form.serialize())
.fail(function(data){error_response(data);})
.done(function(data){susccess_response(data);});
return false;
});
});
</script>
{% block script %}{% endblock %}
</body>
</html>

View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>E-mail verification</h3><hr/>
{% include "fragments/email_verification_form.html" %}
</div>
{% endblock %}

View File

@ -0,0 +1,18 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" role="form" action="{% url 'verify_email' %}">
<div class="form-group">
<label for="key" class="col-sm-2 control-label">Key</label>
<div class="col-sm-10">
<input name="key" type="text" class="form-control" id="key" placeholder="Key">
<p class="help-block">Put here a key which was sent in verification email</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Verify</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,24 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" role="form" action="{% url 'rest_login' %}">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input name="username" type="text" class="form-control" id="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input name="password" type="password" class="form-control" id="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Login</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,25 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" role="form" action="{% url 'rest_password_change' %}">
<div class="form-group">
<label for="new_password1" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input name="new_password1" type="password" class="form-control" id="new_password1" placeholder="Password">
</div>
</div>
<div class="form-group">
<label for="new_password2" class="col-sm-2 control-label">Repeat password</label>
<div class="col-sm-10">
<input name="new_password2" type="password" class="form-control" id="new_password2" placeholder="Repeat password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Set new password</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,40 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" role="form" action="{% url 'rest_password_reset_confirm' %}">
<div class="form-group">
<label for="uid" class="col-sm-2 control-label">Uid</label>
<div class="col-sm-10">
<input name="uid" type="text" class="form-control" id="uid" placeholder="Uid">
<p class="help-block">Uid value sent in email</p>
</div>
</div>
<div class="form-group">
<label for="token" class="col-sm-2 control-label">Token</label>
<div class="col-sm-10">
<input name="token" type="text" class="form-control" id="token" placeholder="Token">
<p class="help-block">Token value sent in email</p>
</div>
</div>
<div class="form-group">
<label for="new_password1" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input name="new_password1" type="password" class="form-control" id="new_password1" placeholder="Password">
</div>
</div>
<div class="form-group">
<label for="new_password2" class="col-sm-2 control-label">Repeat password</label>
<div class="col-sm-10">
<input name="new_password2" type="password" class="form-control" id="new_password2" placeholder="Repeat password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Set new password</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,16 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" role="form" action="{% url 'rest_password_reset' %}">
<div class="form-group">
<label for="email" class="col-sm-2 control-label">E-mail</label>
<div class="col-sm-10">
<input name="email" type="text" class="form-control" id="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Reset</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,38 @@
<!-- Signup form -->
<form class="form-horizontal ajax-post" id="signup" role="form" action="{% url 'rest_register' %}">
<div class="form-group">
<label for="email" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input name="email" type="text" class="form-control" id="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input name="username" type="text" class="form-control" id="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="password1" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input name="password1" type="password" class="form-control" id="password1" placeholder="Password">
</div>
</div>
<div class="form-group">
<label for="password2" class="col-sm-2 control-label">Repeat password</label>
<div class="col-sm-10">
<input name="password2" type="password" class="form-control" id="password2" placeholder="Repeat password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign up</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

View File

@ -0,0 +1,39 @@
<!-- Signup form -->
<form class="form-horizontal" id="signup" role="form" action="{% url 'rest_user_details' %}">
<div class="form-group">
<label for="email" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input name="email" type="text" class="form-control" id="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input name="username" type="text" class="form-control" id="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="first_name" class="col-sm-2 control-label">First name</label>
<div class="col-sm-10">
<input name="first_name" type="text" class="form-control" id="first_name" placeholder="First name">
</div>
</div>
<div class="form-group">
<label for="last_name" class="col-sm-2 control-label">Last name</label>
<div class="col-sm-10">
<input name="last_name" type="text" class="form-control" id="last_name" placeholder="Last name">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Save</button>
</div>
</div>
<div class="form-group api-response"></div>
</form>

9
demo/templates/home.html Normal file
View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% 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>
</div>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>Login</h3><hr/>
{% include "fragments/login_form.html" %}
</div>
{% endblock %}

View File

@ -0,0 +1,39 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="form-group">
<label for="token" class="col-sm-2 control-label">User Token</label>
<div class="col-sm-4">
<input name="token" type="text" class="form-control" id="token" placeholder="Token">
<p class="help-block">Token received after login</p>
</div>
</div>
</div>
<div class="row">
<h3>Update User Details</h3><hr/>
{% include "fragments/password_change_form.html" %}
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
$().ready(function(){
$('form button[type=submit]').click(function(){
var token = $('input[name=token]').val();
var form = $('form');
$.ajax({
url: form.attr('action'),
data: $('form').serialize(),
type: "POST",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);}
}).fail(function(data){error_response(data);})
.done(function(data){susccess_response(data);});
return false;
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>Password reset</h3><hr/>
{% include "fragments/password_reset_form.html" %}
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>Password reset confirmation</h3><hr/>
{% include "fragments/password_reset_confirm_form.html" %}
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
var url_elements = window.location.pathname.split('/');
if (url_elements.length == 6){
var uid = url_elements[url_elements.length - 3];
if (uid !== undefined){
$('input[name=uid]').val(uid);
}
var token = url_elements[url_elements.length - 2];
if (token !== undefined){
$('input[name=token]').val(token);
}
}
</script>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>Signup</h3><hr/>
{% include "fragments/signup_form.html" %}
</div>
{% endblock %}

View File

@ -0,0 +1,58 @@
{% extends "base.html" %}
{% block content %}
<div class="row">
<h3>Retrieve User Details</h3><hr/>
<div class="form-group">
<label for="token" class="col-sm-2 control-label">User Token</label>
<div class="col-sm-4">
<input name="token" type="text" class="form-control" id="token" placeholder="Token">
<p class="help-block">Token received after login</p>
</div>
<button id="get-user-details" class="btn btn-primary">GET user details</button>
</div>
</div>
<div class="row">
<h3>Update User Details</h3><hr/>
{% include "fragments/user_details_form.html" %}
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
$().ready(function(){
$('#get-user-details').click(function(){
var token = $('input[name=token]').val();
$.ajax({
url: "{% url 'rest_user_details' %}",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);},
type: "GET",
success: function(data) {
$('input[name=username]').val(data.username);
$('input[name=email]').val(data.email);
$('input[name=first_name]').val(data.first_name);
$('input[name=last_name]').val(data.last_name);
}
});
return false;
});
$('form button[type=submit]').click(function(){
var token = $('input[name=token]').val();
var form = $('form');
$.ajax({
url: form.attr('action'),
data: $('form').serialize(),
type: "PUT",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);}
}).fail(function(data){error_response(data);})
.done(function(data){susccess_response(data);});
return false;
});
});
</script>
{% endblock %}

View File

@ -60,7 +60,7 @@ Registration
See allauth documentation for more details.
- /rest-auth/registration/ (POST)
- /rest-auth/registration/verify-email/ (POST)
- key

15
docs/demo.rst Normal file
View File

@ -0,0 +1,15 @@
Demo project
============
To run demo project (ideally in virtualenv):
.. code-block:: python
cd /tmp
git clone git@github.com:Tivix/django-rest-auth.git
cd django-rest-auth/demo/
pip install -r requirements.pip
python manage.py syncdb --settings=demo.settings --noinput
python manage.py runserver --settings=demo.settings
Now, go to ``http://127.0.0.1:8000/`` in your browser.

View File

@ -21,6 +21,7 @@ Contents
Installation <installation>
API endpoints <api_endpoints>
Configuration <configuration>
Demo project <demo>
Changelog <changelog>

View File

@ -5,7 +5,7 @@ from .views import Register, VerifyEmail
urlpatterns = patterns('',
url(r'^$', Register.as_view(), name='rest_register'),
url(r'^verify-email/$', VerifyEmail.as_view(), name='verify_email'),
url(r'^verify-email/$', VerifyEmail.as_view(), name='rest_verify_email'),
# These two views are used in django-allauth and empty TemplateView were
# defined just to allow reverse() call inside app, for example when email

View File

@ -154,7 +154,7 @@ class APITestCase1(TestCase, BaseAPITestCase):
self.register_url = reverse('rest_register')
self.password_reset_url = reverse('rest_password_reset')
self.user_url = reverse('rest_user_details')
self.veirfy_email_url = reverse('verify_email')
self.veirfy_email_url = reverse('rest_verify_email')
def _login(self):
payload = {