From 9449481bd493acc906de0987f4d495eeeda98ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Thu, 3 Aug 2017 12:41:30 +0200 Subject: [PATCH] Add example project --- example/app/__init__.py | 1 + example/app/admin.py | 27 ++++++ example/app/apps.py | 73 +++++++++++++++ example/app/fixtures/users.json | 46 ++++++++++ example/app/migrations/0001_initial.py | 46 ++++++++++ example/app/migrations/__init__.py | 0 example/app/models.py | 11 +++ example/app/templates/app/home.html | 88 ++++++++++++++++++ example/app/views.py | 5 + example/db.sqlite3 | Bin 0 -> 67584 bytes example/fixtures/users.json | 38 ++++++++ example/manage.py | 22 +++++ example/requirements.txt | 1 + example/settings.py | 121 +++++++++++++++++++++++++ example/urls.py | 30 ++++++ example/wsgi.py | 16 ++++ 16 files changed, 525 insertions(+) create mode 100644 example/app/__init__.py create mode 100644 example/app/admin.py create mode 100644 example/app/apps.py create mode 100644 example/app/fixtures/users.json create mode 100644 example/app/migrations/0001_initial.py create mode 100644 example/app/migrations/__init__.py create mode 100644 example/app/models.py create mode 100644 example/app/templates/app/home.html create mode 100644 example/app/views.py create mode 100644 example/db.sqlite3 create mode 100644 example/fixtures/users.json create mode 100755 example/manage.py create mode 100644 example/requirements.txt create mode 100644 example/settings.py create mode 100644 example/urls.py create mode 100644 example/wsgi.py diff --git a/example/app/__init__.py b/example/app/__init__.py new file mode 100644 index 0000000..a6ed466 --- /dev/null +++ b/example/app/__init__.py @@ -0,0 +1 @@ +default_app_config = 'app.apps.BasicAppConfig' diff --git a/example/app/admin.py b/example/app/admin.py new file mode 100644 index 0000000..bef3636 --- /dev/null +++ b/example/app/admin.py @@ -0,0 +1,27 @@ +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) diff --git a/example/app/apps.py b/example/app/apps.py new file mode 100644 index 0000000..a76fcc9 --- /dev/null +++ b/example/app/apps.py @@ -0,0 +1,73 @@ +from django.apps import AppConfig +from django.db.models.signals import post_migrate + + +def prepare_site(sender, **kwargs): + from django.contrib.sites.models import Site + Site.objects.filter(id=1).update(name="Demo Site", domain="localhost") + + +def prepare_superuser(sender, **kwargs): + from django.contrib.auth import get_user_model + User = get_user_model() + root, created = User.objects.get_or_create( + username='root', + defaults={ + 'is_staff': True, + 'is_superuser': True, + }, + ) + if created: + root.set_password('root') + root.save() + print('Superuser created - Credantials: root:root') + + +def setup_dummy_social(sender, **kwargs): + from django.contrib.sites.models import Site + from django.utils.module_loading import import_string + + from allauth.socialaccount.models import SocialApp + from allauth.socialaccount.providers import registry + + need_credentials = [ + 'allauth.socialaccount.providers.oauth.provider.OAuthProvider', + 'allauth.socialaccount.providers.oauth2.provider.OAuth2Provider', + ] + + classes = tuple([import_string(cls_path) for cls_path in need_credentials]) + site = Site.objects.get_current() + + dummy_installed = [] + + for provider in registry.get_list(): + if isinstance(provider, classes): + try: + SocialApp.objects.get(provider=provider.id, sites=site) + except SocialApp.DoesNotExist: + app = SocialApp.objects.create( + provider=provider.id, + secret='secret', + client_id='client-id', + name='Dummy %s app' % provider.id, + ) + app.sites.add(site) + dummy_installed.append(provider.id) + + if dummy_installed: + print( + "Dummy application credentials installed for: %s.\n" + "Authentication via these providers will not work until you " + "configure proper credentials via the Django admin (`SocialApp` " + "model)." + % ', '.join(sorted(dummy_installed)) + ) + + +class BasicAppConfig(AppConfig): + name = 'app' + + def ready(self): + post_migrate.connect(prepare_site, sender=self) + post_migrate.connect(prepare_superuser, sender=self) + post_migrate.connect(setup_dummy_social, sender=self) diff --git a/example/app/fixtures/users.json b/example/app/fixtures/users.json new file mode 100644 index 0000000..6590604 --- /dev/null +++ b/example/app/fixtures/users.json @@ -0,0 +1,46 @@ +[ +{ + "model": "testapp.user", + "pk": 1, + "fields": { + "password": "pbkdf2_sha256$36000$RNuQMJ1hqN0P$GFFyxtTONjkh4IUMifNYrsXs4/SnX5uMnGtRNR2WrFo=", + "last_login": null, + "is_superuser": false, + "username": "user", + "first_name": "", + "last_name": "", + "email": "", + "is_staff": false, + "is_active": true, + "date_joined": "2017-07-03T10:10:18.675Z", + "departement": "", + "occupation": "1A", + "phone": "", + "promo": 2016, + "groups": [], + "user_permissions": [] + } +}, +{ + "model": "testapp.user", + "pk": 2, + "fields": { + "password": "pbkdf2_sha256$36000$NFfbdDHHuq0A$auDXrWn6xr+FnsAOW8uq0aa8m2kyUPtgY/QgThMDKF0=", + "last_login": null, + "is_superuser": true, + "username": "root", + "first_name": "", + "last_name": "", + "email": "", + "is_staff": true, + "is_active": true, + "date_joined": "2017-07-03T10:10:36.413Z", + "departement": "", + "occupation": "1A", + "phone": "", + "promo": 2016, + "groups": [], + "user_permissions": [] + } +} +] diff --git a/example/app/migrations/0001_initial.py b/example/app/migrations/0001_initial.py new file mode 100644 index 0000000..0643401 --- /dev/null +++ b/example/app/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# -*- 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()), + ], + ), + ] diff --git a/example/app/migrations/__init__.py b/example/app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/app/models.py b/example/app/models.py new file mode 100644 index 0000000..c48bbda --- /dev/null +++ b/example/app/models.py @@ -0,0 +1,11 @@ +from django.contrib.auth.models import AbstractUser, UserManager + +# from authens.models import ENSUserMixin + +""" +class User(ENSUserMixin, AbstractUser): + objects = UserManager() +""" + +class User(AbstractUser): + objects = UserManager() diff --git a/example/app/templates/app/home.html b/example/app/templates/app/home.html new file mode 100644 index 0000000..910e176 --- /dev/null +++ b/example/app/templates/app/home.html @@ -0,0 +1,88 @@ + + + + + Test app authens + + + + +{% if messages %} + +

Messages

+ + + +{% endif %} + + +

Utilisateur connecté

+ +{% if user.is_authenticated %} +Connecté avec {{ user }} (superuser: {{ user.is_superuser|yesno:"oui,non" }}) +{% else %} +Non connecté +{% endif %} + +

Pages comptes

+ + + +

Les pages suivantes nécessitent d'être connecté pour y accéder.

+ + + + +

Navigation

+ + +

Accéder à une page

+ + + +

Connexion (/accounts/login/(?next=<redirect>)?)

+ + + +

Déconnexion (/accounts/logout/(?next=<redirect>)?)

+ + diff --git a/example/app/views.py b/example/app/views.py new file mode 100644 index 0000000..c7e2886 --- /dev/null +++ b/example/app/views.py @@ -0,0 +1,5 @@ +from django.views.generic import TemplateView + + +class HomeView(TemplateView): + template_name = 'app/home.html' diff --git a/example/db.sqlite3 b/example/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..21cac4bf81e38867768cbfbf8c25c46c3444381a GIT binary patch literal 67584 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 literal 0 HcmV?d00001 diff --git a/example/fixtures/users.json b/example/fixtures/users.json new file mode 100644 index 0000000..f87008f --- /dev/null +++ b/example/fixtures/users.json @@ -0,0 +1,38 @@ +[ +{ + "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": [] + } +} +] diff --git a/example/manage.py b/example/manage.py new file mode 100755 index 0000000..7646e46 --- /dev/null +++ b/example/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/example/requirements.txt b/example/requirements.txt new file mode 100644 index 0000000..c642fd0 --- /dev/null +++ b/example/requirements.txt @@ -0,0 +1 @@ +-e ../ diff --git a/example/settings.py b/example/settings.py new file mode 100644 index 0000000..5c04e80 --- /dev/null +++ b/example/settings.py @@ -0,0 +1,121 @@ +import os + +import django + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + + +SECRET_KEY = 'iamaplop' + +DEBUG = True + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +SITE_ID = 1 + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.sites', + 'django.contrib.staticfiles', + + 'widget_tweaks', + + # This one must be before 'allauth' to replace its templates. + 'allauth_ens', + + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + + 'allauth_cas', + + 'allauth.socialaccount.providers.facebook', + 'allauth.socialaccount.providers.google', + + 'allauth_ens.providers.clipper', + + 'app', +] + +_MIDDLEWARES = [ + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.sites.middleware.CurrentSiteMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +] + +if django.VERSION >= (1, 10): + MIDDLEWARE = _MIDDLEWARES +else: + MIDDLEWARE_CLASSES = _MIDDLEWARES + +ROOT_URLCONF = 'urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'Europe/Paris' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +STATIC_URL = '/static/' + +AUTH_USER_MODEL = 'app.User' + +LOGIN_URL = '/account/login/' +LOGIN_REDIRECT_URL = '/account/settings/' + +SOCIALACCOUNT_QUERY_EMAIL = True + +# allauth settings + +ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = False diff --git a/example/urls.py b/example/urls.py new file mode 100644 index 0000000..98df25d --- /dev/null +++ b/example/urls.py @@ -0,0 +1,30 @@ +from django.conf.urls import url, include +from django.contrib import admin +from django.contrib.auth.decorators import login_required, permission_required +from django.views.generic import RedirectView + +from app import views + +urlpatterns = [ + # Catch admin login/logout views. + # url(r'^admin/login/', authens_views.CaptureLogin.as_view()), + # url(r'^admin/logout/', authens_views.CaptureLogout.as_view()), + + # Admin urls include comes after. + url(r'^admin/', admin.site.urls), + + # Base views with different required permissions. + url(r'^view/', views.HomeView.as_view(), + name='view'), + url(r'^user/', login_required()(views.HomeView.as_view()), + name='user-view'), + url(r'^root/', permission_required('foo.perm')(views.HomeView.as_view()), + name='root-view'), + + # Authens urls (handle login/logout views). + url(r'^account/', include('allauth_ens.urls')), + + + # (Redirect from /) + url(r'^$', RedirectView.as_view(url='/view/')), +] diff --git a/example/wsgi.py b/example/wsgi.py new file mode 100644 index 0000000..d9986f9 --- /dev/null +++ b/example/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for plop3 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.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plop3.settings") + +application = get_wsgi_application()