Eww, hard to sum up…
- Update django-allauth-cas to the last version. - Add docs (README, example/README). - Add tests for Clipper provider. - Add tests to check templates do not contain syntax error. - Add the last missing templates to override all allauth's displayable templates. - Improve stylesheets.
This commit is contained in:
parent
4cdbb049df
commit
fe21f9c6af
58 changed files with 1304 additions and 4566 deletions
5
CHANGELOG.rst
Normal file
5
CHANGELOG.rst
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
******************
|
||||||
|
1.0.0 (unreleased)
|
||||||
|
******************
|
||||||
|
|
||||||
|
- First official release.
|
1
Gemfile
1
Gemfile
|
@ -2,4 +2,3 @@
|
||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'compass'
|
gem 'compass'
|
||||||
gem 'font-awesome-sass', :git => "https://github.com/TruePath/font-awesome-sass.git", :branch => "patch-1"
|
|
||||||
|
|
13
Gemfile.lock
13
Gemfile.lock
|
@ -1,11 +1,3 @@
|
||||||
GIT
|
|
||||||
remote: https://github.com/TruePath/font-awesome-sass.git
|
|
||||||
revision: b3974fe0632d09a7744c4a3b42f4ccf8dc9f919e
|
|
||||||
branch: patch-1
|
|
||||||
specs:
|
|
||||||
font-awesome-sass (4.7.0)
|
|
||||||
sass (>= 3.2)
|
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
@ -23,7 +15,7 @@ GEM
|
||||||
compass-import-once (1.0.5)
|
compass-import-once (1.0.5)
|
||||||
sass (>= 3.2, < 3.5)
|
sass (>= 3.2, < 3.5)
|
||||||
ffi (1.9.18)
|
ffi (1.9.18)
|
||||||
multi_json (1.12.1)
|
multi_json (1.12.2)
|
||||||
rb-fsevent (0.10.2)
|
rb-fsevent (0.10.2)
|
||||||
rb-inotify (0.9.10)
|
rb-inotify (0.9.10)
|
||||||
ffi (>= 0.5.0, < 2)
|
ffi (>= 0.5.0, < 2)
|
||||||
|
@ -34,7 +26,6 @@ PLATFORMS
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
compass
|
compass
|
||||||
font-awesome-sass!
|
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.15.3
|
1.16.1
|
||||||
|
|
259
README.rst
259
README.rst
|
@ -1,8 +1,259 @@
|
||||||
==================
|
##################
|
||||||
django-allauth-ens
|
django-allauth-ens
|
||||||
==================
|
##################
|
||||||
|
|
||||||
Providers for django-allauth_ allowing using the ENS' auth-systems.
|
This package is meant to ease the management of authentication of django-apps
|
||||||
|
at the ENS.
|
||||||
|
|
||||||
|
On top of django-allauth_, which provides easy ways to configure the
|
||||||
|
authentication of django-apps, this package provides:
|
||||||
|
|
||||||
|
* social authentication using Clipper (*cas.eleves*);
|
||||||
|
|
||||||
|
* ready-to-use templates in replacement of allauth' ones;
|
||||||
|
|
||||||
|
* helpers to use *allauth*'s login and logout views instead of those
|
||||||
|
provided by third-parties (Django admin, wagtail, *etc*).
|
||||||
|
|
||||||
|
|
||||||
.. _django-allauth: https://www.intenct.nl/projects/django-allauth/
|
**Contents**
|
||||||
|
|
||||||
|
.. contents:: :local:
|
||||||
|
|
||||||
|
|
||||||
|
************
|
||||||
|
Installation
|
||||||
|
************
|
||||||
|
|
||||||
|
First, `install django-allauth`_.
|
||||||
|
|
||||||
|
Then, install *django-allauth-ens*:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ pip install django-allauth-ens
|
||||||
|
|
||||||
|
And edit your settings file:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
# …
|
||||||
|
|
||||||
|
# Above allauth to replace its templates.
|
||||||
|
'allauth_ens',
|
||||||
|
|
||||||
|
# Added when you installed allauth.
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
|
||||||
|
# Required to use CAS-based providers (e.g. Clipper).
|
||||||
|
'allauth_cas',
|
||||||
|
|
||||||
|
# …
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
*************
|
||||||
|
Configuration
|
||||||
|
*************
|
||||||
|
|
||||||
|
See also the `allauth configuration`_ and `advanced usage`_ docs pages.
|
||||||
|
|
||||||
|
``ACCOUNT_HOME_URL``
|
||||||
|
*Optional* — A view name or an url path.
|
||||||
|
|
||||||
|
Used as a link from the templates of ``allauth_ens`` to return to your
|
||||||
|
application.
|
||||||
|
|
||||||
|
**Examples:** ``'home'``, ``'/home/'``
|
||||||
|
|
||||||
|
``ACCOUNT_DETAILS_URL``
|
||||||
|
*Optional* — A view name or an url path.
|
||||||
|
|
||||||
|
Used as a link from the templates of ``allauth_ens`` for a logged in user to
|
||||||
|
access their profile in your app.
|
||||||
|
|
||||||
|
**Examples:** ``'my-account'``, ``'/my-account/'``
|
||||||
|
|
||||||
|
*****
|
||||||
|
Views
|
||||||
|
*****
|
||||||
|
|
||||||
|
Capture other login and logout views
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can use the ``capture_login`` and ``capture_logout`` views to replace the
|
||||||
|
login and logout views of other applications. They redirect to their similar
|
||||||
|
*allauth*'s view and forward the query string, so that if a GET parameter
|
||||||
|
``next`` is given along the initial request, user is redirected to this url on
|
||||||
|
successful login and logout.
|
||||||
|
|
||||||
|
This requires to add urls before the include of the app' urls.
|
||||||
|
|
||||||
|
For example, to replace the Django admin login and logout views with allauth's
|
||||||
|
ones:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from allauth_ens.views import capture_login, capture_logout
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# …
|
||||||
|
|
||||||
|
# Add it before include of admin urls.
|
||||||
|
url(r'^admin/login/$', capture_login),
|
||||||
|
url(r'^admin/logout/$', capture_logout),
|
||||||
|
|
||||||
|
url(r'^admin/$', include(admin.site.urls)),
|
||||||
|
|
||||||
|
# …
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
Templates
|
||||||
|
*********
|
||||||
|
|
||||||
|
The templates provided by *allauth* only contains the bare minimum. Hopefully,
|
||||||
|
this package includes ready-to-use templates. They are automatically used if
|
||||||
|
you put ``'allauth_ens'`` before ``'allauth'`` in your ``INSTALLED_APPS``,
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
Providers
|
||||||
|
*********
|
||||||
|
|
||||||
|
*Google, Facebook¸ but also Clipper…*
|
||||||
|
|
||||||
|
To interact with an external authentication service, you must add the
|
||||||
|
corresponding provider application to your ``INSTALLED_APPS``.
|
||||||
|
|
||||||
|
*allauth* already includes `several providers`_ (see also `their python path`_).
|
||||||
|
In addition to that, this package adds the following providers:
|
||||||
|
|
||||||
|
Clipper
|
||||||
|
=======
|
||||||
|
|
||||||
|
It uses the CAS server `<https://cas.eleves.ens.fr/>`_.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
Add ``'allauth_ens.providers.clipper'`` to the ``INSTALLED_APPS``.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
Available settings and their default value:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
|
# …
|
||||||
|
|
||||||
|
'clipper': {
|
||||||
|
|
||||||
|
# These settings control whether a message containing a link to
|
||||||
|
# disconnect from the CAS server is added when users log out.
|
||||||
|
'MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT': True,
|
||||||
|
'MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT_LEVEL': messages.INFO,
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Auto-signup
|
||||||
|
Poulated data
|
||||||
|
- username: ``<clipper>``
|
||||||
|
- email (primary and verified): ``<clipper>@clipper.ens.fr``
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
Demo Site
|
||||||
|
*********
|
||||||
|
|
||||||
|
See ``example/README``.
|
||||||
|
|
||||||
|
|
||||||
|
***********
|
||||||
|
Development
|
||||||
|
***********
|
||||||
|
|
||||||
|
First, you need to clone the repository.
|
||||||
|
|
||||||
|
Stylesheets
|
||||||
|
===========
|
||||||
|
|
||||||
|
This project uses `compass`_ to compile SCSS files to CSS.
|
||||||
|
|
||||||
|
Using bundler
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
* Ensure Ruby is installed (``$ ruby -v``) or `install Ruby`_
|
||||||
|
* Ensure bundler is installed (``$ bundle -v``) or install bundler
|
||||||
|
(``$ gem install bundler``)
|
||||||
|
* Install dependencies: ``$ bundle install``
|
||||||
|
|
||||||
|
Compile
|
||||||
|
* Watch changes and recompile: ``$ bundle exec compass watch``
|
||||||
|
|
||||||
|
Tests
|
||||||
|
=====
|
||||||
|
|
||||||
|
Local environment
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
``$ ./runtests.py``
|
||||||
|
|
||||||
|
All
|
||||||
|
---
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
* tox, install with ``$ pip install tox``
|
||||||
|
* ``python{2.7,3.4,3.5,3.6}`` must be available on your system path
|
||||||
|
|
||||||
|
Run
|
||||||
|
* all (django/python with combined coverage + flake8 + isort): ``$ tox``
|
||||||
|
|
||||||
|
|
||||||
|
******
|
||||||
|
Howtos
|
||||||
|
******
|
||||||
|
|
||||||
|
Assuming you use the following settings (when needed):
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ACCOUNT_ADAPTER = 'shared.allauth_adapter.AccountAdapter'
|
||||||
|
SOCIALACCOUNT_ADAPTER = 'shared.allauth_adapter.SocialAccountAdapter'
|
||||||
|
|
||||||
|
Signup disabled, except for clipper provider (auto-signup)
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
In ``shared/allauth_adapter.py``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class AccountAdapter(DefaultAccountAdapter):
|
||||||
|
def is_open_for_signup(self, request):
|
||||||
|
return False
|
||||||
|
|
||||||
|
class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
|
def is_open_for_signup(self, request, sociallogin):
|
||||||
|
# sociallogin.account is a SocialAccount instance.
|
||||||
|
# See https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py
|
||||||
|
|
||||||
|
if sociallogin.account.provider == 'clipper':
|
||||||
|
return True
|
||||||
|
|
||||||
|
# It returns AccountAdapter.is_open_for_signup().
|
||||||
|
# See https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/adapter.py
|
||||||
|
return super().is_open_for_signup(request, sociallogin)
|
||||||
|
|
||||||
|
|
||||||
|
.. _django-allauth: https://django-allauth.readthedocs.io/en/latest/overview.html
|
||||||
|
.. _install django-allauth: https://django-allauth.readthedocs.io/en/latest/installation.html
|
||||||
|
.. _several providers: https://django-allauth.readthedocs.io/en/latest/providers.html
|
||||||
|
.. _allauth configuration: https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
.. _advanced usage: https://django-allauth.readthedocs.io/en/latest/advanced.html
|
||||||
|
.. _their python path: https://django-allauth.readthedocs.io/en/latest/installation.html
|
||||||
|
.. _compass: https://compass-style.org/
|
||||||
|
.. _install Ruby: https://www.ruby-lang.org/en/documentation/installation/
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
__version__ = '0.0.1.dev1'
|
__version__ = '0.0.1.dev1'
|
||||||
|
|
||||||
default_app_config = 'allauth_ens.apps.ENSAllauthAppConfig'
|
default_app_config = 'allauth_ens.apps.ENSAllauthConfig'
|
||||||
|
|
|
@ -2,6 +2,6 @@ from django.apps import AppConfig
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class ENSAllauthAppConfig(AppConfig):
|
class ENSAllauthConfig(AppConfig):
|
||||||
name = 'allauth_ens'
|
name = 'allauth_ens'
|
||||||
verbose_name = _("ENS Authentication")
|
verbose_name = _("ENS Authentication")
|
||||||
|
|
|
@ -15,8 +15,8 @@ class ClipperProvider(CASProvider):
|
||||||
account_class = ClipperAccount
|
account_class = ClipperAccount
|
||||||
|
|
||||||
def extract_email(self, data):
|
def extract_email(self, data):
|
||||||
username, _, _ = data
|
uid, extra = data
|
||||||
return '{}@clipper.ens.fr'.format(username)
|
return '{}@clipper.ens.fr'.format(uid.strip().lower())
|
||||||
|
|
||||||
def extract_common_fields(self, data):
|
def extract_common_fields(self, data):
|
||||||
common = super(ClipperProvider, self).extract_common_fields(data)
|
common = super(ClipperProvider, self).extract_common_fields(data)
|
||||||
|
@ -24,20 +24,23 @@ class ClipperProvider(CASProvider):
|
||||||
return common
|
return common
|
||||||
|
|
||||||
def extract_email_addresses(self, data):
|
def extract_email_addresses(self, data):
|
||||||
email = self.extract_email(data)
|
|
||||||
return [
|
return [
|
||||||
EmailAddress(
|
EmailAddress(
|
||||||
email=email,
|
email=self.extract_email(data),
|
||||||
verified=True,
|
verified=True, primary=True,
|
||||||
primary=True,
|
),
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def extract_extra_data(self, data):
|
def extract_extra_data(self, data):
|
||||||
extra = super(ClipperProvider, self).extract_extra_data(data)
|
extra_data = super(ClipperProvider, self).extract_extra_data(data)
|
||||||
extra['username'] = data[0]
|
extra_data['email'] = self.extract_email(data)
|
||||||
extra['email'] = self.extract_email(data)
|
return extra_data
|
||||||
return extra
|
|
||||||
|
def message_suggest_caslogout_on_logout(self, request):
|
||||||
|
return (
|
||||||
|
self.get_settings()
|
||||||
|
.get('MESSAGE_SUGGEST_CASLOGOUT_ON_LOGOUT', True)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
provider_classes = [ClipperProvider]
|
provider_classes = [ClipperProvider]
|
||||||
|
|
|
@ -1,4 +1,21 @@
|
||||||
from allauth_cas.test.testcases import CASViewTestCase
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
from allauth_cas.test.testcases import CASTestCase, CASViewTestCase
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class ClipperProviderTests(CASTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.u = User.objects.create_user('user', 'user@mail.net', 'user')
|
||||||
|
|
||||||
|
def test_auto_signup(self):
|
||||||
|
self.client_cas_login(
|
||||||
|
self.client, provider_id='clipper', username='clipper_uid')
|
||||||
|
|
||||||
|
u = User.objects.get(username='clipper_uid')
|
||||||
|
self.assertEqual(u.email, 'clipper_uid@clipper.ens.fr')
|
||||||
|
|
||||||
|
|
||||||
class ClipperViewsTests(CASViewTestCase):
|
class ClipperViewsTests(CASViewTestCase):
|
||||||
|
@ -15,6 +32,10 @@ class ClipperViewsTests(CASViewTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_callback_view(self):
|
def test_callback_view(self):
|
||||||
|
# Required to initialize a SocialLogin.
|
||||||
|
r = self.client.get('/accounts/clipper/login/')
|
||||||
|
|
||||||
|
# Tests.
|
||||||
self.patch_cas_response(valid_ticket='__all__')
|
self.patch_cas_response(valid_ticket='__all__')
|
||||||
r = self.client.get('/accounts/clipper/login/callback/', {
|
r = self.client.get('/accounts/clipper/login/callback/', {
|
||||||
'ticket': '123456',
|
'ticket': '123456',
|
||||||
|
|
|
@ -27,16 +27,14 @@ b {
|
||||||
* Layout structure *
|
* Layout structure *
|
||||||
********************/
|
********************/
|
||||||
|
|
||||||
$main-max-width: 700px;
|
$main-max-width: 500px;
|
||||||
|
|
||||||
$divider-size: 2px;
|
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
max-width: $main-max-width;
|
max-width: $main-max-width;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
background: $white;
|
background: $white;
|
||||||
box-shadow: 0 0 10px $gray-lighter;
|
box-shadow: 0 0 5px rgba(0,0,0,.1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,49 +63,24 @@ $divider-size: 2px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 500px) {
|
||||||
& > section {
|
& > section {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 350px - $divider-size / 2;
|
width: 250px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Divider */
|
@media (min-width: 120px) {
|
||||||
|
& > section {
|
||||||
& > .divider {
|
flex: 1 1 auto;
|
||||||
display: none;
|
width: 350px;
|
||||||
|
|
||||||
&::before {
|
|
||||||
display: block;
|
|
||||||
content: " ";
|
|
||||||
background: $gray-lighter;
|
|
||||||
|
|
||||||
height: $divider-size;
|
|
||||||
width: $divider-size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 575px) {
|
|
||||||
& {
|
|
||||||
flex: 100%;
|
|
||||||
padding: 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before { width: 100%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
|
||||||
& {
|
|
||||||
align-self: stretch;
|
|
||||||
padding: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before { height: 100%; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > section + .divider {
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#providers {
|
||||||
|
width:150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,23 +105,6 @@ header {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
.history-back {
|
|
||||||
@include transition;
|
|
||||||
|
|
||||||
width: 55px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
color: $white;
|
|
||||||
font-size: $header-history-icon-size;
|
|
||||||
|
|
||||||
@include hover-focus {
|
|
||||||
background: lighten($header-bg, 5%);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $white !important;
|
color: $white !important;
|
||||||
|
|
||||||
|
@ -159,42 +115,41 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
border-left: 1px solid lighten($header-bg, 15%);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
|
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-left: 1px solid lighten($header-bg, 15%);
|
||||||
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
line-height: 28px;
|
|
||||||
|
& > * {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > * > * {
|
#connect-status {
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& #connect-status {
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
.fa {
|
.fa {
|
||||||
margin-right: 10px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
flex: 1 0 auto;
|
flex: 1 1 auto;
|
||||||
|
|
||||||
padding: 15px 35px;
|
padding: 15px 25px;
|
||||||
line-height: 25px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -252,128 +207,92 @@ section {
|
||||||
|
|
||||||
/* Methods list */
|
/* Methods list */
|
||||||
|
|
||||||
$space-between: 15px;
|
|
||||||
|
|
||||||
.method-list {
|
.method-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: - $space-between / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-wrapper {
|
& > .method-wrapper {
|
||||||
flex: 1 50%;
|
flex: 1 100%;
|
||||||
padding: $space-between / 2;
|
padding: 2px 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@include btn;
|
@include btn;
|
||||||
@include btn-primary-hov;
|
|
||||||
display: block;
|
border-radius: 0;
|
||||||
|
border-left: 5px solid $brand-primary;
|
||||||
|
|
||||||
|
background: $gray-lighter;
|
||||||
|
color: $black;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
@include hover-focus {
|
||||||
|
background: lighten($brand-primary, 50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connected accounts list */
|
/* Connected accounts list */
|
||||||
|
|
||||||
.provider-list {
|
.connections-providers-list {
|
||||||
|
|
||||||
& > li {
|
& > * {
|
||||||
|
|
||||||
&:not(:first-child) {
|
& + * {
|
||||||
margin-top: 5px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .heading {
|
& > .heading {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
|
|
||||||
height: 45px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
background-color: $gray-lighter;
|
border-left: 5px solid $brand-primary;
|
||||||
|
background: $gray-lighter;
|
||||||
|
|
||||||
|
.connect {
|
||||||
|
@include btn;
|
||||||
|
@include btn-primary;
|
||||||
|
@include btn-sm;
|
||||||
|
|
||||||
|
float: right;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.connections-list {
|
||||||
|
border-left: 5px solid $gray-lightest;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
float: left;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .connect, & > .brand-icon {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .connect a {
|
|
||||||
@include transition;
|
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
background-color: $brand-success;
|
|
||||||
color: $white;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
line-height: 100%;
|
|
||||||
width: 45px;
|
|
||||||
|
|
||||||
padding: 12px;
|
|
||||||
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
@include hover-focus {
|
|
||||||
background-color: darken($brand-success, 5%);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .brand-icon {
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 45px;
|
font-size: 14px;
|
||||||
color: $brand-primary;
|
|
||||||
|
& + * {
|
||||||
|
border-top: 1px dotted $gray-lighter;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .name {
|
& > .fa {
|
||||||
padding: 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .connected-list {
|
|
||||||
|
|
||||||
padding: 0 15px;
|
|
||||||
|
|
||||||
& > li {
|
|
||||||
@include clearfix;
|
|
||||||
|
|
||||||
height: 30px;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
float: left;
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .connected-delete [type=submit] {
|
|
||||||
background-color: $red;
|
|
||||||
color: $white;
|
|
||||||
min-height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
|
|
||||||
@include hover-focus {
|
|
||||||
background-color: darken($red, 5%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .connected-label {
|
|
||||||
padding: 7px 15px;
|
|
||||||
width: calc(100% - 30px);
|
|
||||||
border-bottom: 1px solid $red;
|
|
||||||
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
float: right;
|
||||||
|
margin-top: -2px;
|
||||||
|
|
||||||
|
& [type=submit] {
|
||||||
|
@include btn;
|
||||||
|
@include btn-danger;
|
||||||
|
@include btn-sm;
|
||||||
|
opacity: .8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
form {
|
form {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +331,7 @@ $space-between: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .primary {
|
& > .primary {
|
||||||
color: darken($brand-primary, 15%);
|
color: $brand-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .verified {
|
& > .verified {
|
||||||
|
@ -424,19 +343,6 @@ $space-between: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
|
||||||
@include clearfix;
|
|
||||||
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
float: right;
|
|
||||||
margin-right: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -557,9 +463,9 @@ $label-top: $label-height + $input-wrapper-padding + $input-padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include input-special('has-value', $green);
|
@include input-special('has-value', $brand-success);
|
||||||
@include input-special('error', $red);
|
@include input-special('error', $brand-danger);
|
||||||
@include input-special('focused', $blue);
|
@include input-special('focused', $brand-primary);
|
||||||
|
|
||||||
.infos-spacer {
|
.infos-spacer {
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -577,16 +483,47 @@ $label-top: $label-height + $input-wrapper-padding + $input-padding;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.widget-checkbox {
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
& > input[type="checkbox"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button {
|
||||||
|
@include transition;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: white;
|
||||||
|
color: $gray-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button.choice-yes {
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button.choice-no {
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button.focus {
|
||||||
|
background: $brand-primary;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[type=submit]:not(.link) {
|
[type=submit]:not(.link) {
|
||||||
@include btn;
|
@include btn;
|
||||||
@include btn-success-hov;
|
@include btn-success;
|
||||||
float: right;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type=submit].link {
|
[type=submit].link {
|
||||||
@include link;
|
@include link;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
@include hover-focus {
|
@include hover-focus {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -595,13 +532,15 @@ $label-top: $label-height + $input-wrapper-padding + $input-padding;
|
||||||
|
|
||||||
.form-inline {
|
.form-inline {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.input-list {
|
& > .input-wrapper {
|
||||||
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type=submit] {
|
[type=submit] {
|
||||||
|
margin-top: -5px;
|
||||||
|
margin-left: 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,6 +550,5 @@ $label-top: $label-height + $input-wrapper-padding + $input-padding;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary-hov {
|
.btn-primary { @include btn-primary; }
|
||||||
@include btn-primary-hov;
|
.btn-success { @include btn-success; }
|
||||||
}
|
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin transition($time: .3s) {
|
@mixin transition($time: .15s) {
|
||||||
transition: background $time, color $time;
|
transition: background $time, color $time, border-color $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin link {
|
@mixin link {
|
||||||
|
@ -50,13 +50,15 @@
|
||||||
@mixin btn {
|
@mixin btn {
|
||||||
@include transition;
|
@include transition;
|
||||||
|
|
||||||
//width: 100%;
|
display: block;
|
||||||
|
width: 100%;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
|
line-height: initial;
|
||||||
|
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 10px 15px;
|
border-radius: 3px;
|
||||||
|
padding: 7px 15px;
|
||||||
|
|
||||||
font-family: "Roboto Slab";
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -67,23 +69,38 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin btn-primary-hov {
|
@mixin btn-primary {
|
||||||
color: $black;
|
background: $brand-primary;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
@include hover-focus {
|
@include hover-focus {
|
||||||
background: darken($brand-primary, 15%);
|
background: darken($brand-primary, 5%);
|
||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin btn-success-hov {
|
@mixin btn-success {
|
||||||
background-color: $brand-success;
|
background: $brand-success;
|
||||||
color: $white;
|
color: $white;
|
||||||
//background: $gray-lighter;
|
|
||||||
//color: $black;
|
|
||||||
|
|
||||||
@include hover-focus {
|
@include hover-focus {
|
||||||
background: darken($brand-success, 15%);
|
background: darken($brand-success, 15%);
|
||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin btn-danger {
|
||||||
|
background: $brand-danger;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
@include hover-focus {
|
||||||
|
background: darken($brand-danger, 15%);
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin btn-sm {
|
||||||
|
min-height: auto;
|
||||||
|
padding: 4px 7px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ a, input, button {
|
||||||
}
|
}
|
||||||
|
|
||||||
input, button {
|
input, button {
|
||||||
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
|
@ -17,10 +17,10 @@ $gray-light: #636c72 !default;
|
||||||
$gray-lighter: #eceeef !default;
|
$gray-lighter: #eceeef !default;
|
||||||
$gray-lightest: #f7f7f9 !default;
|
$gray-lightest: #f7f7f9 !default;
|
||||||
|
|
||||||
$brand-primary: $blue !default;
|
$brand-primary: darken($blue, 10%) !default;
|
||||||
$brand-success: $green !default;
|
$brand-success: darken($green, 10%) !default;
|
||||||
$brand-info: $teal !default;
|
$brand-info: $teal !default;
|
||||||
$brand-warning: $orange !default;
|
$brand-warning: darken($orange, 10%) !default;
|
||||||
$brand-danger: $red !default;
|
$brand-danger: $red !default;
|
||||||
$brand-inverse: $gray-dark !default;
|
$brand-inverse: $gray-dark !default;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,6 @@
|
||||||
/* Welcome to Compass.
|
|
||||||
* In this file you should write your main styles. (or centralize your imports)
|
|
||||||
* Import this file using the following HTML or equivalent:
|
|
||||||
* <link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" /> */
|
|
||||||
|
|
||||||
// @import "vendor/normalize";
|
|
||||||
// @import "reset";
|
|
||||||
@import "compass/reset";
|
@import "compass/reset";
|
||||||
@import "reset";
|
@import "reset";
|
||||||
|
|
||||||
@import "font-awesome-compass";
|
|
||||||
@import "font-awesome";
|
|
||||||
|
|
||||||
@import "variables";
|
@import "variables";
|
||||||
@import "mixins";
|
@import "mixins";
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,15 @@ Input.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(Input.prototype, {
|
$.extend(Input.prototype, {
|
||||||
update_focus: toggleWrapperClass('input-focused', Input.prototype.has_focus),
|
update_focus: toggleWrapperClass('input-focused', Input.prototype.has_focus),
|
||||||
update_error: toggleWrapperClass('input-error', Input.prototype.has_error),
|
update_error: function () {
|
||||||
|
let has_error = this.has_error();
|
||||||
|
toggleWrapperClass('input-error').bind(this)(has_error);
|
||||||
|
if (!has_error) {
|
||||||
|
this.wrapper.find('.messages .error-desc').hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
update_has_value: toggleWrapperClass('input-has-value', Input.prototype.has_value),
|
update_has_value: toggleWrapperClass('input-has-value', Input.prototype.has_value),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,6 +58,23 @@ $( function() {
|
||||||
fields.map( function() { return new Input(this); });
|
fields.map( function() { return new Input(this); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
let choice_yes = $('.choice-yes');
|
||||||
|
let choice_no = $('.choice-no');
|
||||||
|
|
||||||
|
choice_yes.click(function () {
|
||||||
|
$(this).siblings('input').prop('checked', true);
|
||||||
|
$(this).addClass('focus');
|
||||||
|
$(this).siblings('.choice-no').removeClass('focus');
|
||||||
|
});
|
||||||
|
|
||||||
|
choice_no.click(function () {
|
||||||
|
$(this).siblings('input').prop('checked', true);
|
||||||
|
$(this).addClass('focus');
|
||||||
|
$(this).siblings('.choice-yes').removeClass('focus');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keyboard shortcuts
|
* Keyboard shortcuts
|
||||||
|
|
File diff suppressed because it is too large
Load diff
18
allauth_ens/templates/account/account_inactive.html
Normal file
18
allauth_ens/templates/account/account_inactive.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "allauth_ens/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block header-title %}{% trans "Account Inactive" %}{% endblock %}
|
||||||
|
{% block title %}{% trans "Account Inactive" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
{% blocktrans %}
|
||||||
|
This account is inactive.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,29 +0,0 @@
|
||||||
{% load widget_tweaks %}
|
|
||||||
|
|
||||||
{% csrf_token %}
|
|
||||||
<ul class="input-list">
|
|
||||||
{% for field in form %}
|
|
||||||
{% with field|field_type as type %}
|
|
||||||
<li class="input-wrapper {% if type == "booleanfield" %}input-skip{% endif %}">
|
|
||||||
{% if type == "booleanfield" %}
|
|
||||||
<label for="{{ field.id_for_label }}">
|
|
||||||
{{ field.label }}
|
|
||||||
{% render_field field class+="field" %}
|
|
||||||
</label>
|
|
||||||
{% else %}
|
|
||||||
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
|
||||||
{% render_field field class+="field" autocomplete="off" autocapitalize="none" placeholder="" %}
|
|
||||||
{% endif %}
|
|
||||||
<div class="infos-spacer"></div>
|
|
||||||
<ul class="messages">
|
|
||||||
{% if field.help_text %}
|
|
||||||
<li>{{ field.help_text|safe }}</li>
|
|
||||||
{% endif %}
|
|
||||||
{% for error in field.errors %}
|
|
||||||
<li>{{ error }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% endwith %}
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "E-mail Addresses" %}{% endblock %}
|
{% block title %}{% trans "E-mail Addresses" %}{% endblock %}
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<form action="{% url "account_email" %}" method="post" class="form-inline">
|
<form action="{% url "account_email" %}" method="post" class="form-inline">
|
||||||
{% include "account/block-form.html" with form=form %}
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
<button type="submit" class="link" name="action_add">{% trans "Add E-mail" %}</button>
|
<button type="submit" class="link" name="action_add">{% trans "Add E-mail" %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load account %}
|
{% load account %}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load account socialaccount allauth_ens %}
|
{% load account socialaccount allauth_ens %}
|
||||||
|
|
||||||
|
@ -18,9 +18,10 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li class="message warning">
|
<li class="message warning">
|
||||||
|
{% user_display user as user_str %}
|
||||||
{% blocktrans %}
|
{% blocktrans %}
|
||||||
You are unauthorized to view this page. Please sign in with an account
|
Your are authenticated as {{ user_str }}, but are not authorized to access
|
||||||
with the required permissions.
|
this page. Would you like to login to a different account ?
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -34,31 +35,32 @@
|
||||||
{% get_providers as socialaccount_providers %}
|
{% get_providers as socialaccount_providers %}
|
||||||
|
|
||||||
{% if socialaccount_providers %}
|
{% if socialaccount_providers %}
|
||||||
<section>
|
<section id="providers">
|
||||||
<p>
|
|
||||||
{% blocktrans %}
|
|
||||||
Please sign in with one of your existing third party accounts, or with the
|
|
||||||
form opposite.
|
|
||||||
{% endblocktrans %}
|
|
||||||
</p>
|
|
||||||
<ul class="method-list">
|
<ul class="method-list">
|
||||||
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
|
||||||
|
|
||||||
{% include "socialaccount/snippets/login_extra.html" %}
|
{% include "socialaccount/snippets/login_extra.html" %}
|
||||||
|
</section>
|
||||||
|
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<section>
|
<section id="main">
|
||||||
|
<p>
|
||||||
|
{% blocktrans %}
|
||||||
|
Please sign in with one of your existing third party accounts, or with the form below.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
<ul class="actions">
|
<ul class="actions">
|
||||||
<li><a href="{{ signup_url }}">{% trans "Sign Up" %}</a></li>
|
|
||||||
<li><a href="{% url "account_reset_password" %}">{% trans "Forgot Password?" %}</a>
|
<li><a href="{% url "account_reset_password" %}">{% trans "Forgot Password?" %}</a>
|
||||||
|
{% is_open_for_signup as open_signup %}
|
||||||
|
{% if open_signup %}
|
||||||
|
<li><a href="{{ signup_url }}">{% trans "Sign Up" %}</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
<form action="{% url "account_login" %}" method="post">
|
<form action="{% url "account_login" %}" method="post">
|
||||||
{% include "account/block-form.html" with form=form %}
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
<input type="submit" value="{% trans "Sign In" %}">
|
<input type="submit" value="{% trans "Sign In" %}">
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Sign Out" %}{% endblock %}
|
{% block title %}{% trans "Sign Out" %}{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Change Password" %}{% endblock %}
|
{% block title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
{% block messages-extra %}
|
{% block messages-extra %}
|
||||||
|
|
||||||
{% include "account/block-messages-form-errors.html" with form_errors=form.non_field_errors %}
|
{% include "allauth_ens/block-messages-form-errors.html" with form_errors=form.non_field_errors %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<form action="{% url "account_change_password" %}" method="post">
|
<form action="{% url "account_change_password" %}" method="post">
|
||||||
{% include "account/block-form.html" with form=form submit_value=submit_value %}
|
{% include "allauth_ens/block-form.html" with form=form submit_value=submit_value %}
|
||||||
<input type="submit" value="{% trans "Change Password" %}">
|
<input type="submit" value="{% trans "Change Password" %}">
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Password Reset" %}{% endblock %}
|
{% block title %}{% trans "Password Reset" %}{% endblock %}
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
<form action="{% url "account_reset_password" %}" method="post">
|
<form action="{% url "account_reset_password" %}" method="post">
|
||||||
{% include "account/block-form.html" with form=form %}
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
<input type="submit" value="{% trans "Reset Password" %}">
|
<input type="submit" value="{% trans "Reset Password" %}">
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Password Reset" %}{% endblock %}
|
{% block title %}{% trans "Password Reset" %}{% endblock %}
|
||||||
|
|
28
allauth_ens/templates/account/password_reset_from_key.html
Normal file
28
allauth_ens/templates/account/password_reset_from_key.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{% extends "allauth_ens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
{% block header-title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
{% if token_fail %}
|
||||||
|
<p>
|
||||||
|
{% url 'account_reset_password' as passwd_reset_url %}
|
||||||
|
{% blocktrans %}
|
||||||
|
The password reset link was invalid, possibly because it has already been used.
|
||||||
|
Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
{% elif form %}
|
||||||
|
<form action="" method="post">
|
||||||
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
|
<input type="submit" value="{% trans "Reset Password" %}">
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<p>{% trans "Your password is now changed." %}</p>
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Change Password" %}{% endblock %}
|
{% block title %}{% trans "Change Password" %}{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Set Password" %}{% endblock %}
|
{% block title %}{% trans "Set Password" %}{% endblock %}
|
||||||
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
{% block messages-extra %}
|
{% block messages-extra %}
|
||||||
|
|
||||||
{% include "account/block-messages-form-errors.html" with form_errors=form.non_field_errors %}
|
{% include "allauth_ens/block-messages-form-errors.html" with form_errors=form.non_field_errors %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -19,9 +19,8 @@
|
||||||
third parties.
|
third parties.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
<hr>
|
|
||||||
<form action="{% url "account_set_password" %}" method="post">
|
<form action="{% url "account_set_password" %}" method="post">
|
||||||
{% include "account/block-form.html" with form=form %}
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
<input type="submit" value="{% trans "Set Password" %}">
|
<input type="submit" value="{% trans "Set Password" %}">
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Signup" %}{% endblock %}
|
{% block title %}{% trans "Signup" %}{% endblock %}
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<form action="{% url "account_signup" %}" method="post">
|
<form action="{% url "account_signup" %}" method="post">
|
||||||
{% include "account/block-form.html" with form=form %}
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
<input type="submit" value="{% trans "Sign Up" %}">
|
<input type="submit" value="{% trans "Sign Up" %}">
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Sign Up Closed" %}{% endblock %}
|
{% block title %}{% trans "Sign Up Closed" %}{% endblock %}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
|
||||||
<title>{% block title %}{% endblock %}{% if request.site.name %} - {{ request.site.name }}{% endif %}</title>
|
<title>{% block title %}{% endblock %}{% if request.site.name %} · {{ request.site.name }}{% endif %}</title>
|
||||||
|
|
||||||
{# Responsive UI #}
|
{# Responsive UI #}
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
@ -17,6 +17,10 @@
|
||||||
{# CSS #}
|
{# CSS #}
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://fonts.googleapis.com/css?family=Roboto:400,700|Roboto+Slab:400">
|
href="https://fonts.googleapis.com/css?family=Roboto:400,700|Roboto+Slab:400">
|
||||||
|
<link rel="stylesheet"
|
||||||
|
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||||
|
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
|
||||||
|
crossorigin="anonymous">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="{% static "allauth_ens/screen.css" %}">
|
href="{% static "allauth_ens/screen.css" %}">
|
||||||
|
|
||||||
|
@ -44,10 +48,10 @@
|
||||||
{% get_home_url as home_url %}
|
{% get_home_url as home_url %}
|
||||||
{% if home_url %}
|
{% if home_url %}
|
||||||
<a href="{{ home_url }}">
|
<a href="{{ home_url }}">
|
||||||
{{ request.site.name|default:"Voir le site" }}
|
{{ request.site.name|default:"View site" }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span>{{ request.site.name }}</span>
|
<span>{{ request.site.name|default:"View site" }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -66,16 +70,16 @@
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<span>
|
<a href="{% url "account_login" %}">
|
||||||
<i class="fa fa-user"></i>
|
<i class="fa fa-sign-in"></i>
|
||||||
{% trans "Not Connected" %}
|
{% trans "Not Connected" %}
|
||||||
</span>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{% include "account/block-messages.html" %}
|
{% include "allauth_ens/block-messages.html" %}
|
||||||
|
|
||||||
{% block messages-extra %}{% endblock %}
|
{% block messages-extra %}{% endblock %}
|
||||||
|
|
33
allauth_ens/templates/allauth_ens/block-form.html
Normal file
33
allauth_ens/templates/allauth_ens/block-form.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{% load widget_tweaks %}
|
||||||
|
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% for field in form %}
|
||||||
|
{% with widget=field|widget_type %}
|
||||||
|
{% if widget == "checkboxinput" %}
|
||||||
|
<div li class="input-wrapper input-skip {% if field.errors %}input-error{% endif %}">
|
||||||
|
<label for="{{ field.id_for_label }}">
|
||||||
|
{{ field.label }}
|
||||||
|
<div class="widget-checkbox">
|
||||||
|
{% render_field field class+="field" %}
|
||||||
|
<button type="button" class="choice-yes">Oui</button>
|
||||||
|
<button type="button" class="choice-no focus">Non</button>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
{% else %}
|
||||||
|
<div class="input-wrapper{% if field.errors %} input-error{% endif %}">
|
||||||
|
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||||
|
{% render_field field class+="field" size="" autocomplete="off" autocapitalize="none" placeholder="" %}
|
||||||
|
{% endif %}
|
||||||
|
<div class="infos-spacer"></div>
|
||||||
|
<ul class="messages">
|
||||||
|
{% if field.help_text %}
|
||||||
|
<li>{{ field.help_text|safe }}</li>
|
||||||
|
{% endif %}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li class="error-desc">{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/block-messages-base.html" %}
|
{% extends "allauth_ens/block-messages-base.html" %}
|
||||||
|
|
||||||
{% block messages-container %}
|
{% block messages-container %}
|
||||||
{% if form_errors %}{{ block.super }}{% endif %}
|
{% if form_errors %}{{ block.super }}{% endif %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/block-messages-base.html" %}
|
{% extends "allauth_ens/block-messages-base.html" %}
|
||||||
|
|
||||||
{% block messages-container %}
|
{% block messages-container %}
|
||||||
{% if messages %}{{ block.super }}{% endif %}
|
{% if messages %}{{ block.super }}{% endif %}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends "allauth_ens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Login Failure" %}{% endblock %}
|
||||||
|
{% block header-title %}{% trans "Login Failure" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
{% blocktrans %}
|
||||||
|
An error occured while attempting to login via your social network account.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "account/base.html" %}
|
{% extends "allauth_ens/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load socialaccount allauth_ens_social %}
|
{% load socialaccount allauth_ens_social %}
|
||||||
|
|
||||||
|
@ -19,48 +19,45 @@
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
<ul class="provider-list">
|
<ul class="connections-providers-list">
|
||||||
{% get_accounts_by_providers user as accounts_by_providers %}
|
{% get_accounts_by_providers user as accounts_by_providers %}
|
||||||
|
|
||||||
{% for provider, accounts in accounts_by_providers.items %}
|
{% for provider, accounts in accounts_by_providers.items %}
|
||||||
|
|
||||||
<li class="provider">
|
<li>
|
||||||
<ul class="heading">
|
<div class="heading">
|
||||||
<li class="connect">
|
<a class="connect" href="{% provider_login_url provider.id process="connect" scope=scope auth_params=auth_params %}">
|
||||||
<a href="{% provider_login_url provider.id process="connect" scope=scope auth_params=auth_params %}">
|
|
||||||
<i class="fa fa-plus"></i>
|
<i class="fa fa-plus"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
|
||||||
<li class="name">
|
|
||||||
{{ provider.name }}
|
{{ provider.name }}
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
|
||||||
|
|
||||||
{% if accounts %}
|
{% if accounts %}
|
||||||
|
|
||||||
<ul class="connected-list">
|
<ul class="connections-list">
|
||||||
{% for account in accounts %}
|
{% for account in accounts %}
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<span class="connected-delete">
|
<div class="delete">
|
||||||
<form action="{% url "socialaccount_connections" %}" method="post">
|
<form action="{% url "socialaccount_connections" %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="account" value="{{ account.id }}">
|
<input type="hidden" name="account" value="{{ account.id }}">
|
||||||
<button type="submit" class="link"><i class="fa fa-remove"></i></button>
|
<button type="submit" class="link">
|
||||||
|
<i class="fa fa-remove"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</span>
|
</div>
|
||||||
<span class="connected-label">
|
|
||||||
<i class="fa fa-user"></i>
|
<i class="fa fa-user"></i>
|
||||||
{% with account.get_profile_url as profile_url %}
|
{% with profile_urlaccount.get_profile_url as profile_url %}
|
||||||
{% trans "Connected Account - No ID" as fallback_label %}
|
{% firstof account.extra_data.name account.extra_data.username account.uid as account_label %}
|
||||||
{% firstof account.extra_data.name account.extra_data.username fallback_label as account_label %}
|
|
||||||
{% if profile_url %}
|
{% if profile_url %}
|
||||||
<a href="{{ profile_url }}" target="blank">{{ account_label }}</a>
|
<a href="{{ get_profile_url }}" target="blank">
|
||||||
|
{{ account_label }}
|
||||||
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ account_label }}
|
{{ account_label }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
19
allauth_ens/templates/socialaccount/login_cancelled.html
Normal file
19
allauth_ens/templates/socialaccount/login_cancelled.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% extends "allauth_ens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Login Cancelled" %}{% endblock %}
|
||||||
|
{% block header-title %}{% trans "Login Cancelled" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
{% url "account_login" as login_url %}
|
||||||
|
|
||||||
|
{% blocktrans %}
|
||||||
|
You decided to cancel logging into our site using one of your existing accounts. If this was a mistake, please proceed to <a href="{{login_url}}">sign in</a>.{% endblocktrans %}
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
26
allauth_ens/templates/socialaccount/signup.html
Normal file
26
allauth_ens/templates/socialaccount/signup.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends "allauth_ens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Signup" %}{% endblock %}
|
||||||
|
{% block header-title %}{% trans "Signup" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
{% blocktrans with provider_name=account.get_provider.name %}
|
||||||
|
You are about to use your {{ provider_name }} account to login.
|
||||||
|
As a final step, please complete the following form:
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form action="{% url "socialaccount_signup" %}" method="post">
|
||||||
|
{% include "allauth_ens/block-form.html" with form=form %}
|
||||||
|
<input type="submit" value="{% trans "Sign Up" %}">
|
||||||
|
{% if redirect_field_value %}
|
||||||
|
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -3,6 +3,7 @@ from django import template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
|
|
||||||
|
from allauth.account.adapter import get_adapter
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
@ -26,3 +27,9 @@ def get_profile_url():
|
||||||
if profile_url is None:
|
if profile_url is None:
|
||||||
return None
|
return None
|
||||||
return resolve_url(profile_url)
|
return resolve_url(profile_url)
|
||||||
|
|
||||||
|
|
||||||
|
@simple_tag(takes_context=True)
|
||||||
|
def is_open_for_signup(context):
|
||||||
|
request = context['request']
|
||||||
|
return get_adapter(request).is_open_for_signup(request)
|
||||||
|
|
|
@ -6,7 +6,6 @@ from django import template
|
||||||
from allauth import app_settings as allauth_settings
|
from allauth import app_settings as allauth_settings
|
||||||
from allauth.socialaccount.templatetags import socialaccount as tt_social
|
from allauth.socialaccount.templatetags import socialaccount as tt_social
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
if django.VERSION >= (1, 9):
|
if django.VERSION >= (1, 9):
|
||||||
|
|
137
allauth_ens/tests.py
Normal file
137
allauth_ens/tests.py
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
import django
|
||||||
|
from django.contrib.auth import HASH_SESSION_KEY, get_user_model
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
from django.core import mail
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
if django.VERSION >= (1, 10):
|
||||||
|
from django.urls import reverse
|
||||||
|
else:
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
def prevent_logout_pwd_change(client, user):
|
||||||
|
"""
|
||||||
|
Updating a user's password logs out all sessions for the user.
|
||||||
|
By calling this function this behavior will be prevented.
|
||||||
|
|
||||||
|
See this link, and the source code of `update_session_auth_hash`:
|
||||||
|
https://docs.djangoproject.com/en/dev/topics/auth/default/#session-invalidation-on-password-change
|
||||||
|
"""
|
||||||
|
if hasattr(user, 'get_session_auth_hash'):
|
||||||
|
session = client.session
|
||||||
|
session[HASH_SESSION_KEY] = user.get_session_auth_hash()
|
||||||
|
session.save()
|
||||||
|
|
||||||
|
|
||||||
|
class ViewsTests(TestCase):
|
||||||
|
"""
|
||||||
|
Checks (barely) that templates do not contain errors.
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
self.u = User.objects.create_user('user', 'user@mail.net', 'user')
|
||||||
|
|
||||||
|
Site.objects.filter(pk=1).update(domain='testserver')
|
||||||
|
|
||||||
|
def _login(self, client=None):
|
||||||
|
if client is None:
|
||||||
|
client = self.client
|
||||||
|
client.login(username='user', password='user')
|
||||||
|
|
||||||
|
def _get_confirm_email_link(self, email_msg):
|
||||||
|
m = re.search(
|
||||||
|
r'http://testserver(/accounts/confirm-email/.*/)',
|
||||||
|
email_msg.body,
|
||||||
|
)
|
||||||
|
return m.group(1)
|
||||||
|
|
||||||
|
def _get_reset_password_link(self, email_msg):
|
||||||
|
m = re.search(
|
||||||
|
r'http://testserver(/accounts/password/reset/key/.*/)',
|
||||||
|
email_msg.body,
|
||||||
|
)
|
||||||
|
return m.group(1)
|
||||||
|
|
||||||
|
def test_account_signup(self):
|
||||||
|
r = self.client.get(reverse('account_signup'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
ACCOUNT_ADAPTER='tests.adapter.ClosedSignupAccountAdapter',
|
||||||
|
)
|
||||||
|
def test_account_closed_signup(self):
|
||||||
|
r = self.client.get(reverse('account_signup'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_login(self):
|
||||||
|
r = self.client.get(reverse('account_login'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_logout(self):
|
||||||
|
self._login()
|
||||||
|
r = self.client.get(reverse('account_logout'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_change_password(self):
|
||||||
|
self._login()
|
||||||
|
r = self.client.get(reverse('account_change_password'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_set_password(self):
|
||||||
|
self._login()
|
||||||
|
self.u.set_unusable_password()
|
||||||
|
self.u.save()
|
||||||
|
prevent_logout_pwd_change(self.client, self.u)
|
||||||
|
|
||||||
|
r = self.client.get(reverse('account_set_password'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_inactive(self):
|
||||||
|
r = self.client.get(reverse('account_inactive'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_email(self):
|
||||||
|
self._login()
|
||||||
|
r = self.client.get(reverse('account_email'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_email_verification_sent(self):
|
||||||
|
self._login()
|
||||||
|
r = self.client.get(reverse('account_email_verification_sent'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_confirm_email(self):
|
||||||
|
self._login()
|
||||||
|
self.client.post(reverse('account_email'), {
|
||||||
|
'action_add': '',
|
||||||
|
'email': 'test@mail.net',
|
||||||
|
})
|
||||||
|
confirm_url = self._get_confirm_email_link(mail.outbox[0])
|
||||||
|
|
||||||
|
r = self.client.get(confirm_url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_reset_password(self):
|
||||||
|
r = self.client.get(reverse('account_reset_password'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_reset_password_done(self):
|
||||||
|
r = self.client.get(reverse('account_reset_password_done'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_reset_password_from_key(self):
|
||||||
|
self.client.post(reverse('account_reset_password'), {
|
||||||
|
'email': 'user@mail.net',
|
||||||
|
})
|
||||||
|
reset_url = self._get_reset_password_link(mail.outbox[0])
|
||||||
|
|
||||||
|
r = self.client.get(reset_url, follow=True)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_account_reset_password_from_key_done(self):
|
||||||
|
r = self.client.get(reverse('account_reset_password_from_key_done'))
|
||||||
|
self.assertEqual(r.status_code, 200)
|
|
@ -1,10 +1,16 @@
|
||||||
from django.core.urlresolvers import reverse_lazy
|
import django
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
|
if django.VERSION >= (1, 10):
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
else:
|
||||||
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
|
||||||
|
|
||||||
class CaptureLogin(RedirectView):
|
class CaptureLogin(RedirectView):
|
||||||
url = reverse_lazy('account_login')
|
url = reverse_lazy('account_login')
|
||||||
query_string = True
|
query_string = True
|
||||||
|
permanent = False
|
||||||
|
|
||||||
|
|
||||||
capture_login = CaptureLogin.as_view()
|
capture_login = CaptureLogin.as_view()
|
||||||
|
@ -13,6 +19,7 @@ capture_login = CaptureLogin.as_view()
|
||||||
class CaptureLogout(RedirectView):
|
class CaptureLogout(RedirectView):
|
||||||
url = reverse_lazy('account_logout')
|
url = reverse_lazy('account_logout')
|
||||||
query_string = True
|
query_string = True
|
||||||
|
permanent = False
|
||||||
|
|
||||||
|
|
||||||
capture_logout = CaptureLogout.as_view()
|
capture_logout = CaptureLogout.as_view()
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
require 'compass/import-once/activate'
|
require 'compass/import-once/activate'
|
||||||
# Require any additional compass plugins here.
|
|
||||||
require 'font-awesome-sass'
|
|
||||||
|
|
||||||
# Set this to the root of your project when deployed:
|
# Set this to the root of your project when deployed:
|
||||||
http_path = '/'
|
http_path = '/'
|
||||||
|
|
54
example/README.rst
Normal file
54
example/README.rst
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
*****
|
||||||
|
Setup
|
||||||
|
*****
|
||||||
|
|
||||||
|
Clone the repository and go to the directory containing this file.
|
||||||
|
|
||||||
|
If it is the first time you start the example website, run these commands::
|
||||||
|
|
||||||
|
# Create a virtual env.
|
||||||
|
$ virtualenv -p python3 venv
|
||||||
|
$ . venv/bin/activate
|
||||||
|
|
||||||
|
# Install dependencies (django-allauth-ens is installed from local copy).
|
||||||
|
$ pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Initialize the database (sqlite).
|
||||||
|
$ ./manage.py migrate
|
||||||
|
|
||||||
|
Start the server with::
|
||||||
|
|
||||||
|
$ ./manage.py runserver
|
||||||
|
|
||||||
|
Then, open your browser at `<http://localhost:8000/>`_.
|
||||||
|
|
||||||
|
|
||||||
|
*****
|
||||||
|
Usage
|
||||||
|
*****
|
||||||
|
|
||||||
|
Pre-existing users
|
||||||
|
==================
|
||||||
|
|
||||||
|
You can try to login using one of the existing users:
|
||||||
|
|
||||||
|
* a "normal" user (username: 'user', password: 'user')
|
||||||
|
|
||||||
|
* a superuser (username: 'root', password: 'root')
|
||||||
|
|
||||||
|
Auth Providers
|
||||||
|
==============
|
||||||
|
|
||||||
|
Facebook and Google are activated but they won't work unless you provide valid
|
||||||
|
API credentials in the Django Admin at
|
||||||
|
`<http://localhost:8060/admin/socialaccount/socialapp/>`_.
|
||||||
|
|
||||||
|
Clipper is available (which requires valid credentials). For auto-signup, the
|
||||||
|
new user is populated with the clipper identifier as username (plus a suffix if
|
||||||
|
not available) and ``<clipper id>@clipper.ens.fr`` as email.
|
||||||
|
|
||||||
|
Adapters
|
||||||
|
========
|
||||||
|
|
||||||
|
``ACCOUNT_ADAPTER`` and ``SOCIALACCOUNT_ADAPTER`` can be customized in
|
||||||
|
``adapter.py``.
|
11
example/adapter.py
Normal file
11
example/adapter.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
|
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||||
|
|
||||||
|
|
||||||
|
class AccountAdapter(DefaultAccountAdapter):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
|
pass
|
|
@ -1,27 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
from django.contrib.auth.admin import UserAdmin
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from .models import User
|
|
||||||
|
|
||||||
|
|
||||||
class ExtendedUserAdmin(UserAdmin):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
base_fields = [field.name for field in AbstractUser._meta.fields]
|
|
||||||
all_fields = [field.name for field in self.model._meta.fields]
|
|
||||||
|
|
||||||
extra_fields = [
|
|
||||||
f for f in all_fields
|
|
||||||
if f not in base_fields and f != self.model._meta.pk.name
|
|
||||||
]
|
|
||||||
|
|
||||||
self.fieldsets += (
|
|
||||||
(_('Champs additionnels'), {'fields': extra_fields}),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(User, ExtendedUserAdmin)
|
|
|
@ -1,34 +1,42 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
from allauth.socialaccount.providers import registry
|
||||||
|
|
||||||
|
|
||||||
def prepare_site(sender, **kwargs):
|
def setup_site(sender, **kwargs):
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
Site.objects.filter(id=1).update(name="Demo Site", domain="localhost")
|
Site.objects.filter(id=1).update(name="Demo Site", domain="localhost")
|
||||||
|
|
||||||
|
|
||||||
def prepare_superuser(sender, **kwargs):
|
def setup_users(sender, **kwargs):
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
root, created = User.objects.get_or_create(
|
|
||||||
username='root',
|
root, r_created = User.objects.get_or_create(username='root', defaults={
|
||||||
defaults={
|
'email': 'root@mail.net',
|
||||||
'is_staff': True,
|
'is_staff': True,
|
||||||
'is_superuser': True,
|
'is_superuser': True,
|
||||||
},
|
})
|
||||||
)
|
if r_created:
|
||||||
if created:
|
|
||||||
root.set_password('root')
|
root.set_password('root')
|
||||||
root.save()
|
root.save()
|
||||||
print('Superuser created - Credentials: root:root')
|
print('Superuser created - Credentials: root:root')
|
||||||
|
|
||||||
|
user, u_created = User.objects.get_or_create(username='user', defaults={
|
||||||
|
'email': 'user@mail.net',
|
||||||
|
})
|
||||||
|
if u_created:
|
||||||
|
user.set_password('user')
|
||||||
|
user.save()
|
||||||
|
print('User created - Credentials: user:user')
|
||||||
|
|
||||||
|
|
||||||
def setup_dummy_social(sender, **kwargs):
|
def setup_dummy_social(sender, **kwargs):
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.utils.module_loading import import_string
|
|
||||||
|
|
||||||
from allauth.socialaccount.models import SocialApp
|
from allauth.socialaccount.models import SocialApp
|
||||||
from allauth.socialaccount.providers import registry
|
|
||||||
|
|
||||||
need_credentials = [
|
need_credentials = [
|
||||||
'allauth.socialaccount.providers.oauth.provider.OAuthProvider',
|
'allauth.socialaccount.providers.oauth.provider.OAuthProvider',
|
||||||
|
@ -68,6 +76,6 @@ class BasicAppConfig(AppConfig):
|
||||||
name = 'app'
|
name = 'app'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
post_migrate.connect(prepare_site, sender=self)
|
post_migrate.connect(setup_site, sender=self)
|
||||||
post_migrate.connect(prepare_superuser, sender=self)
|
|
||||||
post_migrate.connect(setup_dummy_social, sender=self)
|
post_migrate.connect(setup_dummy_social, sender=self)
|
||||||
|
post_migrate.connect(setup_users, sender=self)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"model": "testapp.user",
|
"model": "auth.user",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"fields": {
|
"fields": {
|
||||||
"password": "pbkdf2_sha256$36000$RNuQMJ1hqN0P$GFFyxtTONjkh4IUMifNYrsXs4/SnX5uMnGtRNR2WrFo=",
|
"password": "pbkdf2_sha256$100000$WDs2nLZ0eIl1$oNqrYphOf0AVRQ8aPIA3g7xM2gI8/c8NJkp2geVT7mc=",
|
||||||
"last_login": null,
|
"last_login": null,
|
||||||
"is_superuser": false,
|
"is_superuser": false,
|
||||||
"username": "user",
|
"username": "user",
|
||||||
|
@ -13,19 +13,15 @@
|
||||||
"is_staff": false,
|
"is_staff": false,
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"date_joined": "2017-07-03T10:10:18.675Z",
|
"date_joined": "2017-07-03T10:10:18.675Z",
|
||||||
"departement": "",
|
|
||||||
"occupation": "1A",
|
|
||||||
"phone": "",
|
|
||||||
"promo": 2016,
|
|
||||||
"groups": [],
|
"groups": [],
|
||||||
"user_permissions": []
|
"user_permissions": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"model": "testapp.user",
|
"model": "auth.user",
|
||||||
"pk": 2,
|
"pk": 2,
|
||||||
"fields": {
|
"fields": {
|
||||||
"password": "pbkdf2_sha256$36000$NFfbdDHHuq0A$auDXrWn6xr+FnsAOW8uq0aa8m2kyUPtgY/QgThMDKF0=",
|
"password": "pbkdf2_sha256$100000$EjBzWe7Ce5Bc$abqTFywweKuMaRux2MMUwcLchcwxmXGduN320oYaV28=",
|
||||||
"last_login": null,
|
"last_login": null,
|
||||||
"is_superuser": true,
|
"is_superuser": true,
|
||||||
"username": "root",
|
"username": "root",
|
||||||
|
@ -35,12 +31,16 @@
|
||||||
"is_staff": true,
|
"is_staff": true,
|
||||||
"is_active": true,
|
"is_active": true,
|
||||||
"date_joined": "2017-07-03T10:10:36.413Z",
|
"date_joined": "2017-07-03T10:10:36.413Z",
|
||||||
"departement": "",
|
|
||||||
"occupation": "1A",
|
|
||||||
"phone": "",
|
|
||||||
"promo": 2016,
|
|
||||||
"groups": [],
|
"groups": [],
|
||||||
"user_permissions": []
|
"user_permissions": []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "sites.Site",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"name": "Example Site",
|
||||||
|
"domain": "localhost"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,46 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.3 on 2017-07-27 15:06
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import django.contrib.auth.models
|
|
||||||
import django.contrib.auth.validators
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.utils.timezone
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('auth', '0008_alter_user_username_max_length'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='User',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
|
||||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
|
||||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
|
||||||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
|
||||||
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
|
|
||||||
('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
|
|
||||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
|
||||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
|
||||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
|
||||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
|
||||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
|
||||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name_plural': 'users',
|
|
||||||
'verbose_name': 'user',
|
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
managers=[
|
|
||||||
('objects', django.contrib.auth.models.UserManager()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,11 +0,0 @@
|
||||||
from django.contrib.auth.models import AbstractUser, UserManager
|
|
||||||
|
|
||||||
# from authens.models import ENSUserMixin
|
|
||||||
|
|
||||||
"""
|
|
||||||
class User(ENSUserMixin, AbstractUser):
|
|
||||||
objects = UserManager()
|
|
||||||
"""
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
|
||||||
objects = UserManager()
|
|
|
@ -1,38 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"model": "auth.user",
|
|
||||||
"pk": 1,
|
|
||||||
"fields": {
|
|
||||||
"password": "pbkdf2_sha256$36000$xjRTvXipQpaq$z0kj/h2b4yZp8DNOjhu2TUxSOWHWYX+S+0rvsaWx7TU=",
|
|
||||||
"last_login": null,
|
|
||||||
"is_superuser": false,
|
|
||||||
"username": "user",
|
|
||||||
"first_name": "",
|
|
||||||
"last_name": "",
|
|
||||||
"email": "",
|
|
||||||
"is_staff": false,
|
|
||||||
"is_active": true,
|
|
||||||
"date_joined": "2017-07-01T07:11:08.549Z",
|
|
||||||
"groups": [],
|
|
||||||
"user_permissions": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "auth.user",
|
|
||||||
"pk": 3,
|
|
||||||
"fields": {
|
|
||||||
"password": "pbkdf2_sha256$36000$7IcQUVbp8OM1$7mKhCjAPFLkcEUfu9djXxn/scOw2uvlWLFrMtGfhd0U=",
|
|
||||||
"last_login": null,
|
|
||||||
"is_superuser": true,
|
|
||||||
"username": "root",
|
|
||||||
"first_name": "",
|
|
||||||
"last_name": "",
|
|
||||||
"email": "",
|
|
||||||
"is_staff": true,
|
|
||||||
"is_active": true,
|
|
||||||
"date_joined": "2017-07-01T07:11:20.745Z",
|
|
||||||
"groups": [],
|
|
||||||
"user_permissions": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -9,34 +9,26 @@ SECRET_KEY = 'iamaplop'
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
|
||||||
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
|
'django.contrib.sessions',
|
||||||
'django.contrib.sites',
|
'django.contrib.sites',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
|
||||||
'debug_toolbar',
|
'debug_toolbar',
|
||||||
'widget_tweaks',
|
'widget_tweaks',
|
||||||
|
|
||||||
# This one must be before 'allauth' to replace its templates.
|
|
||||||
'allauth_ens',
|
'allauth_ens',
|
||||||
|
|
||||||
'allauth',
|
'allauth',
|
||||||
'allauth.account',
|
'allauth.account',
|
||||||
'allauth.socialaccount',
|
'allauth.socialaccount',
|
||||||
|
|
||||||
'allauth_cas',
|
'allauth_cas',
|
||||||
|
|
||||||
'allauth.socialaccount.providers.facebook',
|
'allauth.socialaccount.providers.facebook',
|
||||||
'allauth.socialaccount.providers.google',
|
'allauth.socialaccount.providers.google',
|
||||||
|
|
||||||
'allauth_ens.providers.clipper',
|
'allauth_ens.providers.clipper',
|
||||||
|
|
||||||
'app',
|
'app',
|
||||||
|
@ -59,6 +51,12 @@ else:
|
||||||
|
|
||||||
ROOT_URLCONF = 'urls'
|
ROOT_URLCONF = 'urls'
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'wsgi.application'
|
||||||
|
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
@ -75,8 +73,6 @@ TEMPLATES = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'wsgi.application'
|
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
@ -86,16 +82,28 @@ DATABASES = {
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
'NAME': (
|
||||||
|
'django.contrib.auth.password_validation'
|
||||||
|
'.UserAttributeSimilarityValidator',
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
'NAME': (
|
||||||
|
'django.contrib.auth.password_validation'
|
||||||
|
'.MinimumLengthValidator'
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
'NAME': (
|
||||||
|
'django.contrib.auth.password_validation'
|
||||||
|
'.CommonPasswordValidator'
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
'NAME': (
|
||||||
|
'django.contrib.auth.password_validation'
|
||||||
|
'.NumericPasswordValidator'
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -115,7 +123,10 @@ DEBUG_TOOLBAR_CONFIG = {
|
||||||
'SHOW_TOOLBAR_CALLBACK': lambda r: True,
|
'SHOW_TOOLBAR_CALLBACK': lambda r: True,
|
||||||
}
|
}
|
||||||
|
|
||||||
AUTH_USER_MODEL = 'app.User'
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
'allauth.account.auth_backends.AuthenticationBackend',
|
||||||
|
]
|
||||||
|
|
||||||
LOGIN_URL = '/account/login/'
|
LOGIN_URL = '/account/login/'
|
||||||
LOGIN_REDIRECT_URL = 'user-view'
|
LOGIN_REDIRECT_URL = 'user-view'
|
||||||
|
@ -125,4 +136,13 @@ SOCIALACCOUNT_QUERY_EMAIL = True
|
||||||
|
|
||||||
# allauth settings
|
# allauth settings
|
||||||
|
|
||||||
|
ACCOUNT_ADAPTER = 'adapter.AccountAdapter'
|
||||||
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = False
|
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = False
|
||||||
|
ACCOUNT_AUTHENTICATION_METHOD = 'username_email'
|
||||||
|
|
||||||
|
SOCIALACCOUNT_ADAPTER = 'adapter.SocialAccountAdapter'
|
||||||
|
|
||||||
|
# allauth_ens settings
|
||||||
|
|
||||||
|
ACCOUNT_HOME_URL = 'home'
|
||||||
|
ACCOUNT_DETAILS_URL = '/my-account/'
|
||||||
|
|
|
@ -4,13 +4,14 @@ from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
import debug_toolbar
|
import debug_toolbar
|
||||||
|
from allauth_ens.views import capture_login, capture_logout
|
||||||
|
|
||||||
from app import views
|
from app import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Catch admin login/logout views.
|
# Catch admin login/logout views.
|
||||||
# url(r'^admin/login/', authens_views.CaptureLogin.as_view()),
|
url(r'^admin/login/', capture_login),
|
||||||
# url(r'^admin/logout/', authens_views.CaptureLogout.as_view()),
|
url(r'^admin/logout/', capture_logout),
|
||||||
|
|
||||||
# Admin urls include comes after.
|
# Admin urls include comes after.
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
|
@ -28,7 +29,8 @@ urlpatterns = [
|
||||||
|
|
||||||
|
|
||||||
# (Redirect from /)
|
# (Redirect from /)
|
||||||
url(r'^$', RedirectView.as_view(url='/view/')),
|
url(r'^$', RedirectView.as_view(url='/view/'),
|
||||||
|
name='home'),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls))]
|
urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls))]
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -45,7 +45,7 @@ setup(
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'django-allauth',
|
'django-allauth',
|
||||||
'django-allauth-cas',
|
'django-allauth-cas>=1.0.0b2,<1.1',
|
||||||
'django-widget-tweaks',
|
'django-widget-tweaks',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
6
tests/adapter.py
Normal file
6
tests/adapter.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
|
|
||||||
|
|
||||||
|
class ClosedSignupAccountAdapter(DefaultAccountAdapter):
|
||||||
|
def is_open_for_signup(self, request):
|
||||||
|
return False
|
|
@ -12,10 +12,12 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sites',
|
'django.contrib.sites',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
|
||||||
|
'widget_tweaks',
|
||||||
|
|
||||||
|
'allauth_ens',
|
||||||
'allauth',
|
'allauth',
|
||||||
'allauth.account',
|
'allauth.account',
|
||||||
'allauth.socialaccount',
|
'allauth.socialaccount',
|
||||||
|
|
||||||
'allauth_cas',
|
'allauth_cas',
|
||||||
|
|
||||||
'allauth_ens.providers.clipper',
|
'allauth_ens.providers.clipper',
|
||||||
|
@ -36,6 +38,7 @@ _MIDDLEWARES = [
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.sites.middleware.CurrentSiteMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -61,3 +64,7 @@ TEMPLATES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'tests.urls'
|
ROOT_URLCONF = 'tests.urls'
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
||||||
|
|
6
tox.ini
6
tox.ini
|
@ -1,7 +1,8 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
py{27,34,35}-django{18,19,110}
|
django{18,19,110}-py{27,34,35},
|
||||||
py{27,34,35,36}-django111,
|
django111-py{27,34,35,36},
|
||||||
|
django20-py{34,35,36},
|
||||||
cov_combine,
|
cov_combine,
|
||||||
flake8,
|
flake8,
|
||||||
isort
|
isort
|
||||||
|
@ -12,6 +13,7 @@ deps =
|
||||||
django19: django>=1.9,<1.10
|
django19: django>=1.9,<1.10
|
||||||
django110: django>=1.10,<1.11
|
django110: django>=1.10,<1.11
|
||||||
django111: django>=1.11,<2.0
|
django111: django>=1.11,<2.0
|
||||||
|
django20: django>=2.0,<2.1
|
||||||
coverage
|
coverage
|
||||||
mock ; python_version < "3.0"
|
mock ; python_version < "3.0"
|
||||||
usedevelop= True
|
usedevelop= True
|
||||||
|
|
Loading…
Reference in a new issue