Premier commit

This commit is contained in:
Benjamin Dauvergne 2014-10-29 11:38:53 +01:00
commit 9f2ad26f86
30 changed files with 1467 additions and 0 deletions

1
COPYING Normal file
View File

@ -0,0 +1 @@
authentic2-pratic is distributed under the license AGPLv3 or later.

3
MANIFEST.in Normal file
View File

@ -0,0 +1,3 @@
include COPYING
recursive-include src/authentic2_pratic/templates *.html
recursive-include src/authentic2_pratic/static *.js *.css *.png

18
README Normal file
View File

@ -0,0 +1,18 @@
Authentic2 Pr@tic
=================
Remplacement pour les pages de gestion d'Authentic2:
- gestion des collectivités
- gestion des utilisateurs
- gestion des services
- gestion des droits d'accès
URLs
====
/manage/ - liste des collectivités
/manage/<collectivite>/ - menu services, utilisateurs et autorisations
/manage/<collectivite>/services/ - services
/manage/<collectivite>/utilisateurs/ - utilisateurs
/manage/<collectivite>/autorisations/ - autorisations

193
old-doc/cdg59.schema Normal file
View File

@ -0,0 +1,193 @@
# Schéma LDAP
#
objectIdentifier Cdg59Root 1.1
objectIdentifier Cdg59LDAP Cdg59Root:2
objectIdentifier Cdg59LDAPAttribute Cdg59LDAP:1
objectIdentifier Cdg59LDAPObjectClass Cdg59LDAP:2
attributetype ( Cdg59LDAPAttribute:1 NAME 'cdg59siretCode'
DESC 'Collectivity SIRET code'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE)
attributetype ( Cdg59LDAPAttribute:2 NAME 'cdg59direction'
DESC 'Collectivity Direction'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:3 NAME 'cdg59isAdmin'
DESC 'Admin or not'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
attributetype ( Cdg59LDAPAttribute:4 NAME 'cdg59isDisabled'
DESC 'Acccount disabled or not'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
attributetype ( Cdg59LDAPAttribute:5 NAME 'cdg59sid'
DESC 'Service Id'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:6 NAME 'cdg59siid'
DESC 'Service Instance Id'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:7 NAME 'cdg59serviceType'
DESC 'Service Type'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:8 NAME 'cdg59URL'
DESC 'Generic URL'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
attributetype ( Cdg59LDAPAttribute:9 NAME 'cdg59metadataURL'
DESC 'Service Metadata URL'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
attributetype ( Cdg59LDAPAttribute:10 NAME 'cdg59serviceAccesses'
DESC 'Services an agent can access'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:11 NAME 'cdg59collectivitySirhCode'
DESC 'Collectivity SIRH code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
SINGLE-VALUE)
attributetype ( Cdg59LDAPAttribute:12 NAME 'cdg59collectivitySirhLabel'
DESC 'Collectivity SIRH Label'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:13 NAME 'cdg59regionCode'
DESC 'Collectivity "Region" Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:14 NAME 'cdg59departementCode'
DESC 'Collectivity "Departement" Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:15 NAME 'cdg59arrondissementCode'
DESC 'Collectivity "Arrondissement" Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:16 NAME 'cdg59cantonCode'
DESC 'Collectivity "Canton" Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:17 NAME 'cdg59inseeCode'
DESC 'Collectivity INSEE Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:18 NAME 'cdg59streetNumber'
DESC 'Collectivity street number'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})
attributetype ( Cdg59LDAPAttribute:19 NAME 'cdg59distOffice'
DESC 'Collectivity distribution office'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:20 NAME 'cdg59addressCompl'
DESC 'Collectivity complementary address infomation'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:21 NAME 'cdg59addressMention'
DESC 'Collectivity particular mention on address'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:22 NAME 'cdg59agentSirhCode'
DESC 'Collectivity SIRH code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
SINGLE-VALUE)
attributetype ( Cdg59LDAPAttribute:23 NAME 'cdg59isGlobal'
DESC 'Global service, or not'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7)
attributetype ( Cdg59LDAPAttribute:24 NAME 'cdg59ssoRelayState'
DESC 'URL for redirection after a single sign on'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
attributetype ( Cdg59LDAPAttribute:25 NAME 'cdg59lastConnectionTime'
DESC 'Last connection time'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27)
attributetype ( Cdg59LDAPAttribute:26 NAME 'cdg59lastConnectionDuration'
DESC 'Last connection duration'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27)
attributetype ( Cdg59LDAPAttribute:28 NAME 'cdg59collectivityId'
DESC 'Id Code'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
SINGLE-VALUE)
# CDG 59 Collectivity
objectclass ( Cdg59LDAPObjectClass:1
NAME 'cdg59collectivity'
DESC 'CDG 59 Collectivity Objectclass'
STRUCTURAL
SUP organizationalUnit
MAY ( cdg59siretCode $ cdg59collectivitySirhCode $ cdg59collectivitySirhLabel $ cn $ mail $ cdg59URL $ cdg59regionCode $ cdg59departementCode $ cdg59arrondissementCode $ cdg59cantonCode $ cdg59inseeCode $ cdg59streetNumber $ cdg59distOffice $ cdg59addressCompl $ cdg59addressMention $ cdg59collectivityId ))
# CDG 59 Agent
objectclass (Cdg59LDAPObjectClass:2
NAME 'cdg59agent'
DESC 'CDG 59 Agent Objectclass'
STRUCTURAL
SUP inetOrgPerson
MUST ( uid )
MAY ( cdg59isAdmin $ cdg59direction $ cdg59isDisabled $ cdg59serviceAccesses $ cdg59agentSirhCode $ cdg59lastConnectionTime $ cdg59lastConnectionDuration ))
# CDG 59 Service
objectclass ( Cdg59LDAPObjectClass:3
NAME 'cdg59service'
DESC 'CDG 59 Service Objectclass'
STRUCTURAL
MUST ( cdg59sid )
MAY ( cn $ description $ cdg59URL $ cdg59isGlobal $ cdg59metadataURL $ cdg59ssoRelayState ))
# CDG 59 Service Instance
objectclass ( Cdg59LDAPObjectClass:4
NAME 'cdg59serviceInstance'
DESC 'CDG 59 Service Instance Objectclass'
STRUCTURAL
MUST ( cdg59siid )
MAY ( cdg59serviceType $ cdg59URL $ cdg59metadataURL $ cdg59ssoRelayState ))

66
setup.py Executable file
View File

@ -0,0 +1,66 @@
#!/usr/bin/python
from setuptools import setup, find_packages
import os
def get_version():
import glob
import re
import os
version = None
for d in glob.glob('src/*'):
if not os.path.isdir(d):
continue
module_file = os.path.join(d, '__init__.py')
if not os.path.exists(module_file):
continue
for v in re.findall("""__version__ *= *['"](.*)['"]""",
open(module_file).read()):
assert version is None
version = v
if version:
break
assert version is not None
if os.path.exists('.git'):
import subprocess
p = subprocess.Popen(['git','describe','--dirty','--match=v*'],
stdout=subprocess.PIPE)
result = p.communicate()[0]
assert p.returncode == 0, 'git returned non-zero'
new_version = result.split()[0][1:]
assert new_version.split('-')[0] == version, '__version__ must match the last git annotated tag'
version = new_version.replace('-', '.')
return version
README = file(os.path.join(
os.path.dirname(__file__),
'README')).read()
setup(name='authentic2-pratic',
version=get_version(),
license='AGPLv3',
description='Authentic2 Pr@tic',
long_description=README,
author="Entr'ouvert",
author_email="info@entrouvert.com",
packages=find_packages('src'),
package_dir={
'': 'src',
},
package_data={
'authentic2_pratic': [
'templates/authentic2_pratic/*.html',
'static/authentic2_pratic/js/*.js',
'static/authentic2_pratic/css/*.css',
'static/authentic2_pratic/img/*.png',
],
},
install_requires=[
'authentic2',
],
entry_points={
'authentic2.plugin': [
'authentic2-pratic = authentic2_pratic:Plugin',
],
},
)

View File

@ -0,0 +1,15 @@
__version__ = '1.0.0b1'
class Plugin(object):
def get_before_urls(self):
from . import urls
return urls.urlpatterns
def get_apps(self):
return [__name__]
def get_authentication_backends(self):
return ['authentic2_pratic.backends.PraticBackend']
def get_auth_frontends(self):
return ['authentic2_pratic.auth_frontends.PraticFrontend']

View File

View File

@ -0,0 +1,22 @@
class AppSettings(object):
__DEFAULTS = {
}
def __init__(self, prefix):
self.prefix = prefix
def _setting(self, name, dflt):
from django.conf import settings
return getattr(settings, self.prefix+name, dflt)
def __getattr__(self, name):
if name not in self.__DEFAULTS:
raise AttributeError(name)
return self._setting(name, self.__DEFAULTS[name])
# Ugly? Guido recommends this himself ...
# http://mail.python.org/pipermail/python-ideas/2012-May/014969.html
import sys
app_settings = AppSettings('A2_PRATIC_')
app_settings.__name__ = __name__
sys.modules[__name__] = app_settings

View File

@ -0,0 +1,21 @@
from django.utils.translation import gettext_noop
from django import forms
class PraticFrontend(object):
def enabled(self):
True
def name(self):
return gettext_noop('Pr@tic')
def id(self):
return 'pratic'
def form(self):
return forms.Form
def post(self, request, form, nonce, next):
raise NotImplemented
def template(self):
return 'authentic2_pratic/login.html'

View File

@ -0,0 +1,8 @@
import logging
class PraticBackend(object):
def __init__(self):
self.logger = logging.getLogger(__name__)
def authenticate(self, **kwargs):
raise NotImplemented

View File

@ -0,0 +1,11 @@
from django.utils.translation import ugettext_lazy as _
from admin_tools.dashboard import modules
def get_admin_modules():
'''Show models in authentic2 admin'''
model_list = modules.ModelList(_('Pr@tic'),
models=('authentic2_pratic.models.*',))
return (model_list,)

View File

@ -0,0 +1,35 @@
from django import forms
from . import models
class BaseForm(forms.ModelForm):
required_css_class = 'required'
error_css_class = 'error'
class ServiceForm(BaseForm):
class Meta:
model = models.Service
class CollectivityForm(BaseForm):
class Meta:
model = models.Collectivity
class ServiceInstanceForm(BaseForm):
class Meta:
model = models.ServiceInstance
exclude = ('collectivity',)
class AccessForm(BaseForm):
def __init__(self, *args, **kwargs):
collectivity = kwargs.pop('collectivity')
super(AccessForm, self).__init__(*args, **kwargs)
self.fields['user'].queryset = self.fields['user'].queryset.filter(collectivity=collectivity)
self.fields['service_instance'].queryset = self.fields['service_instance'].queryset.filter(collectivity=collectivity)
class Meta:
model = models.Access
class UserForm(BaseForm):
class Meta:
model = models.User
fields = ('uid', 'first_name', 'last_name', 'email')

View File

@ -0,0 +1,296 @@
from django.db.models import (Model, TextField, CharField, EmailField,
URLField, BooleanField, IntegerField, ForeignKey, SlugField)
from django.contrib.auth.models import User as AuthUser
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
class User(AuthUser):
# givenName -> first_name
# sn -> last_name
# userPassword -> password
# mail -> email
# cdg59isDisabled -> ! active
# cdg59lastConnectionTime -> last_login
# cn -> get_full_name()
# ou -> collectivity
# username = uid + '@' + collectivity.slug
uid = CharField(
verbose_name=_('identifier'),
max_length=128)
collectivity = ForeignKey(
'Collectivity',
verbose_name=_('collectivity'))
# cdg59isAdmin
is_admin = BooleanField(
verbose_name=_('is admin'),
default=False,
blank=True)
# cdg59agentSirhCode
sirh_code = CharField(
verbose_name=_('SIRH Code'),
max_length=8,
blank=True)
# cdg59direction
direction = CharField(
verbose_name=_('direction'),
max_length=32,
blank=True)
# cdg59lastConnectionDuration
last_login_duration = IntegerField(
verbose_name=_('last connection duration'),
default=0,
blank=True)
# cdg59serviceAccesses -> convert to ACLs
# employeeType
employee_type = CharField(
verbose_name=_('employee type'),
max_length=64,
blank=True)
# postalAddress
postal_address = TextField(
verbose_name=_('postal address'),
blank=True)
# facsimileTelephoneNumber
fax = CharField(
verbose_name=_('fax'),
max_length=32)
# mobile
mobile = CharField(
verbose_name=_('mobile'),
max_length=16,
blank=True)
# telephoneNumber
phone = CharField(
verbose_name=_('phone'),
max_length=32)
class Meta:
verbose_name = _('agent')
verbose_name_plural = _('agents')
# enforce unicity of login by collectivity
unique_together = (('uid', 'collectivity'),)
def clean(self):
# prevent collisions between users from multiple collectivities
if self.uid and not self.username and self.collectivity:
self.username = u'%s@%s' % (self.uid, self.collectivity.slug)
super(User, self).clean()
# Fields to support
class Collectivity(Model):
# Identifiers
# cn = ou
name = CharField(
verbose_name=_('name'),
max_length=64,
unique=True)
slug = SlugField(
verbose_name=_('identifier'),
max_length=64,
unique=True)
# cdg59collectivityId
collectivity_id = CharField(
verbose_name=_('collectivity id'),
max_length=8,
blank=True)
# cdg59collectivitySirhCode
sirh_code = CharField(
verbose_name=_('SIRH Code'),
max_length=8,
blank=True)
# cdg59collectivitySirhLabel
sirh_label = CharField(
verbose_name=_('SIRH Code'),
max_length=64,
blank=True)
# cdg59inseeCode
insee_code = CharField(
verbose_name=_('INSEE Code'),
max_length=8,
blank=True)
# cdg59siretCode
siret_code = CharField(
verbose_name=_('SIRET Code'),
max_length=8,
blank=True)
# Postal addresse
# postalAddress
postal_address = TextField(
verbose_name=_('postal address'),
blank=True)
# cdg59streetNumber
street_number = CharField(
verbose_name=_('street number'),
max_length=8,
blank=True)
# street
street = CharField(
verbose_name=_('street'),
max_length=128,
blank=True)
# postalCode
postal_code = CharField(
verbose_name=_('postal code'),
max_length=16,
blank=True)
# cdg59addressCompl
address_complementary = CharField(
verbose_name=_('complementary address'),
max_length=64,
blank=True)
# cdg59addressMention
address_mention = CharField(
verbose_name=_('address mention'),
max_length=64,
blank=True)
# cdg59arrondissementCode
arrondissement_code = CharField(
verbose_name=_('arrondissement code'),
max_length=64,
blank=True)
# cdg59cantonCode
canton_code = CharField(
verbose_name=_('canton code'),
max_length=4,
blank=True)
# cdg59departementCode
departement_code = CharField(
verbose_name=_('departement code'),
max_length=2,
blank=True)
# cdg59distOffice
dist_office = CharField(
verbose_name=_('distribution office'),
max_length=64,
blank=True)
# cdg59regionCode
region_code = CharField(
verbose_name=_('distribution office'),
max_length=4,
blank=True)
# Contact
# telephoneNumber
phone = CharField(
verbose_name=_('phone'),
max_length=32,
blank=True)
# facsimileTelephoneNumber
fax = CharField(
verbose_name=_('fax'),
max_length=32,
blank=True)
# mail
email = EmailField(
verbose_name=_('email'),
max_length=64,
blank=True)
# cdg59URL
url = URLField(
verbose_name=_('URL'),
max_length=128,
blank=True)
def __unicode__(self):
return self.name
class Meta:
verbose_name = _('collectivity')
verbose_name_plural = _('collectivities')
ordering = ('name',)
class Service(Model):
# Services without a collectivity are global
# cn
name = CharField(
verbose_name=_('name'),
max_length=32,
unique=True)
# cdg59sid
slug = SlugField(
verbose_name=('identifier'),
unique=True)
is_global = BooleanField(
verbose_name=_('is global'),
default=False,
blank=True)
service_url = URLField(
verbose_name=_('URL'))
metadata_url = URLField(
verbose_name=_('SAML Metadata URL'),
blank=True)
oauth2_url = URLField(
verbose_name=_('OAuth2 URL'),
blank=True)
oauth2_key = CharField(
verbose_name=_('OAuth2 Key'),
max_length=64,
blank=True)
def __unicode__(self):
return self.name
class Meta:
verbose_name = _('service')
verbose_name_plural = _('services')
ordering = ('name',)
class ServiceInstance(Model):
# cdg59sid
slug = SlugField(
verbose_name=('identifier'))
service = ForeignKey(
'Service',
verbose_name=_('service'))
collectivity = ForeignKey(
'Collectivity',
verbose_name=_('collectivity'))
service_url = URLField(
verbose_name=_('URL'),
blank=True)
metadata_url = URLField(
verbose_name=_('SAML Metadata URL'),
blank=True)
oauth2_url = URLField(
verbose_name=_('OAuth2 URL'),
blank=True)
oauth2_key = CharField(
verbose_name=_('OAuth2 Key'),
max_length=64,
blank=True)
def __unicode__(self):
return unicode(self.service)
def clean(self):
if self.collectivity and self.service and self.service.is_global:
qs = ServiceInstance.objects.exclude(id=self.id)
qs = qs.filter(collectivity=self.collectivity,
service=self.service)
if qs.exists():
raise ValidationError(_('There can be only one instance of a global service by collectivity'))
if not self.service.is_global and not self.service_url:
raise ValidationError(_('Service URL field is required'))
class Meta:
verbose_name = _('service instance')
verbose_name = _('service instances')
unique_together = (('slug', 'service', 'collectivity'),)
ordering = ('service__name', 'slug')
class Access(Model):
user = ForeignKey('User',
verbose_name=_('user'))
service_instance = ForeignKey('ServiceInstance',
verbose_name=_('service instance'))
class Meta:
verbose_name = _('access')
verbose_name = _('accesses')
unique_together = (('user', 'service_instance'),)
ordering = ('user__last_name', 'user__first_name', 'service_instance__service__name')

View File

@ -0,0 +1,47 @@
from django.utils.translation import ugettext_lazy as _
from ...models import Attribute, AttributeValue
from ...decorators import to_list
from ...compat import get_user_model
@to_list
def get_instances(ctx):
'''
Retrieve instances from settings
'''
return [None]
@to_list
def get_attribute_names(instance, ctx):
User = get_user_model()
for field in User._meta.fields:
name = 'django_user_' + str(field.name)
description = field.verbose_name + u' (%s)' % name
yield name, description
for attribute in Attribute.objects.all():
name = 'django_user_' + str(attribute.name)
description = attribute.label + u' (%s)' % name
yield name, description
yield 'django_user_groups', User._meta.get_field_by_name('groups')[0].verbose_name + u' (django_user_groups)'
yield 'django_user_group_names', User._meta.get_field_by_name('groups')[0].verbose_name + u' (django_user_group_names)'
yield 'django_user_domain', _('User domain') + u' (django_user_domain)'
yield 'django_user_identifier', _('User identifier') + u' (django_user_identifier)'
def get_dependencies(instance, ctx):
return ('user',)
def get_attributes(instance, ctx):
user = ctx.get('user')
User = get_user_model()
if not user or not isinstance(user, User):
return ctx
for field in User._meta.fields:
ctx['django_user_' + str(field.name)] = getattr(user, field.name)
for av in AttributeValue.objects.with_owner(user):
ctx['django_user_' + str(av.attribute.name)] = av.to_python()
ctx['django_user_groups'] = [group for group in user.groups.all()]
ctx['django_user_group_names'] = [unicode(group) for group in user.groups.all()]
ctx['django_user_domain'] = user.username.rsplit('@', 1)[1] if '@' in user.username else ''
ctx['django_user_identifier'] = user.username.rsplit('@', 1)[0] if '@' in user.username else ''
return ctx

View File

@ -0,0 +1,68 @@
from django.utils.translation import ugettext_lazy as _
import django_tables2 as tables
from . import models
class ServiceTable(tables.Table):
name = tables.TemplateColumn(
'<a rel="popup" href="{% url "a2-pratic-service-edit" pk=record.pk %}">{{ record.name }}</a>',
verbose_name=_('name'))
delete = tables.TemplateColumn(
'{% load i18n %}<a rel="popup" href="{% url "a2-pratic-service-delete" pk=record.pk %}">{% trans "Delete" %}</a>',
verbose_name=_('delete'))
class Meta:
model = models.Service
attrs = {'class': 'main', 'id': 'services-table'}
fields = ('name', 'slug', 'is_global', 'service_url', 'delete')
class CollectivityTable(tables.Table):
name = tables.TemplateColumn(
'<a href="{% url "a2-pratic-collectivity-edit" collectivity_pk=record.pk %}">{{ record.name }}</a>',
verbose_name=_('name'))
delete = tables.TemplateColumn(
'{% load i18n %}<a rel="popup" href="{% url "a2-pratic-collectivity-delete" collectivity_pk=record.pk %}">{% trans "Delete" %}</a>',
verbose_name=_('delete'))
class Meta:
model = models.Collectivity
attrs = {'class': 'main', 'id': 'collectivities-table'}
fields = ('name', 'insee_code', 'postal_code', 'delete')
class UserTable(tables.Table):
uid = tables.TemplateColumn(
'<a rel="popup" href="{% url "a2-pratic-user-edit" collectivity_pk=record.collectivity.pk pk=record.pk %}">{{ record.uid }}</a>',
verbose_name=_('identifier'))
delete = tables.TemplateColumn(
'{% load i18n %}<a rel="popup" href="{% url "a2-pratic-user-delete" collectivity_pk=record.collectivity.pk pk=record.pk %}">{% trans "Delete" %}</a>',
verbose_name=_('delete'))
class Meta:
model = models.User
attrs = {'class': 'main', 'id': 'users-table'}
fields = ('first_name', 'last_name', 'uid', 'is_admin', 'is_active', 'delete')
class ServiceInstanceTable(tables.Table):
slug = tables.TemplateColumn(
'<a rel="popup" href="{% url "a2-pratic-service-instance-edit" collectivity_pk=record.collectivity.pk pk=record.pk %}">{{ record.slug}}</a>',
verbose_name=_('identifier'))
delete = tables.TemplateColumn(
'{% load i18n %}<a rel="popup" href="{% url "a2-pratic-service-instance-delete" collectivity_pk=record.collectivity.pk pk=record.pk %}">{% trans "Delete" %}</a>',
verbose_name=_('delete'))
class Meta:
model = models.User
attrs = {'class': 'main', 'id': 'users-table'}
fields = ('slug', 'service_url')
class AccessTable(tables.Table):
last_name = tables.TemplateColumn('{{ record.user.last_name}}',
verbose_name=_('Last name'))
first_name = tables.TemplateColumn('{{ record.user.first_name }}',
verbose_name=_('First name'))
class Meta:
model = models.Access
attrs = {'class': 'main', 'id': 'accesses-table'}
fields = ('last_name', 'first_name', 'service_instance')

View File

@ -0,0 +1,19 @@
{% extends "authentic2_pratic/collectivity_sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page-title %}{{ block.super }} - {% trans "Accesses management" %}{% endblock %}
{% block page_title %}{{ block.super }} {% trans "Accesses management" %}{% endblock %}
{% block appbar %}
{{ block.super }}
<a rel="popup" href="{% url "a2-pratic-access-add" collectivity_pk=collectivity.pk %}" id="add-user-btn">{% trans "Add access" %}</a>
{% endblock %}
{% block sidebar %}
<p>{% blocktrans count count=object_list.count %}{{ count }} accesses{% plural %}{{ count }} access{% endblocktrans %}</p>
{% endblock %}
{% block main %}
{% render_table table "authentic2_pratic/table.html" %}
{% endblock %}

View File

@ -0,0 +1,35 @@
{% extends "gadjo/base.html" %}
{% load i18n staticfiles %}
{% block page-title %}{% trans "Management" %}{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" media="all" href="{% static "authentic2/manager/css/style.css" %}"/>
{% endblock %}
{% block extrascripts %}
{% if debug %}
<script src="{% static "jquery/js/jquery.form.js" %}"></script>
{% else %}
<script src="{% static "jquery/js/jquery.form.min.js" %}"></script>
{% endif %}
<script type="text/javascript" src="{% static "authentic2/js/purl.js" %}"></script>
<script type="text/javascript" src="{% static "authentic2/manager/js/manager.js" %}"></script>
<script type="text/javascript" src="/static/js/select2.js"></script>
<script type="text/javascript" src="/static/js/heavy_data.js"></script>
<script>
window.csrf_token = '{{ csrf_token }}';
</script>
{% endblock %}
{% block site-url %}/{% endblock %}
{% block site-title %}{% trans "Management" %}{% endblock %}
{% block logout-url %}{% url "auth_logout" %}{% endblock %}
{% block homepage-url %}{% url "a2-pratic-homepage" %}{% endblock %}
{% block appbar %}
<h2>{% block page_title %}{% endblock %}</h2>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page-title %}{{ block.super }} - {% trans "Collectivities management" %}{% endblock %}
{% block page_title %}{% trans "Collectivities management" %}{% endblock %}
{% block appbar %}
{{ block.super }}
<a rel="popup" href="{% url "a2-pratic-collectivity-add" %}" id="add-user-btn">{% trans "Add collectivity" %}</a>
{% endblock %}
{% block sidebar %}
<p>{% blocktrans count count=object_list.count %}{{ count }} collectivities{% plural %}{{ count }} collectivity{% endblocktrans %}</p>
{% endblock %}
{% block main %}
{% render_table table "authentic2_pratic/table.html" %}
{% endblock %}

View File

@ -0,0 +1,54 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n %}
{% block messages %}
{% endblock %}
{% block page_title %}
<a href="{% url "a2-pratic-collectivities" %}">{% trans "Collectivities management" %}</a>
{% endblock %}
{% block sidebar %}
<p><a href="users/">{% trans "Users management" %}</a></p>
<p><a href="services/">{% trans "Service instances management" %}</a></p>
<p><a href="accesses/">{% trans "Accesses management" %}</a></p>
{% endblock %}
{% block main %}
<div class="content">
{% if title %}
<div id="appbar"><h2>{{ title }}</h2></div>
{% endif %}
{% if other_actions %}
<div class="other_actions">
<strong>{% trans "Actions" %}</strong>
<form method="post">
{% for action in other_actions %}
<input type="submit" name="{{ action.name }}" value="{{ action.title }}"
{% if action.confirm %}data-confirm="{{ action.confirm }}"{% endif %}
/>
{% endfor %}
</form>
</div>
{% endif %}
<form method="post">
<div class="form-inner-container">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button>{% if action %}{{ action }}{% else %}{% trans "Save" %}{% endif %}</button>
<a class="cancel" href="..">{% trans "Cancel" %}</a>
</div>
</div>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page_title %}
<a href="{% url "a2-pratic-collectivity-edit" collectivity_pk=collectivity.pk %}">
{{ collectivity }}
</a>
{% endblock %}

View File

@ -0,0 +1,33 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n %}
{% block messages %}
{% endblock %}
{% block main %}
<div class="content">
{% if title %}
<div id="appbar"><h2>{{ title }}</h2></div>
{% endif %}
<form method="post">
<div class="form-inner-container">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
<p>{% blocktrans %}Do you really want to delete « {{ object }} » ?{% endblocktrans %}</p>
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button>{% if action %}{{ action }}{% else %}{% trans "Delete" %}{% endif %}</button>
<a class="cancel" href="..">{% trans "Cancel" %}</a>
</div>
</div>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n %}
{% block messages %}
{% endblock %}
{% block main %}
<div class="content">
{% if title %}
<div id="appbar"><h2>{{ title }}</h2></div>
{% endif %}
{% if other_actions %}
<div class="other_actions">
<strong>{% trans "Actions" %}</strong>
<form method="post">
{% for action in other_actions %}
<input type="submit" name="{{ action.name }}" value="{{ action.title }}"
{% if action.confirm %}data-confirm="{{ action.confirm }}"{% endif %}
/>
{% endfor %}
</form>
</div>
{% endif %}
<form method="post">
<div class="form-inner-container">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button>{% if action %}{{ action }}{% else %}{% trans "Save" %}{% endif %}</button>
<a class="cancel" href="..">{% trans "Cancel" %}</a>
</div>
</div>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% extends "authentic2_pratic/base.html" %}
{% load i18n %}
{% block beforecontent %}
{% endblock %}
{% block appbar %}
<h2>{% trans "Welcome" %}</h2>
{% endblock %}
{% block content %}
<div id="content">
<div id="user-info">
{{ user.get_full_name }}
(<a href="{% url "auth_password_change" %}">{% trans "Password change" %}</a>)
</div>
<ul class="apps">
<li id="collectivities"><a href="{% url "a2-pratic-collectivities" %}">{% trans "Collectivities" %}</a></li>
<li id="services"><a href="{% url "a2-pratic-services" %}">{% trans "Services" %}</a></li>
</ul>
<br style="clear: both;"/>
</div>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "authentic2_pratic/collectivity_sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page-title %}{{ block.super }} - {% trans "Service instances management" %}{% endblock %}
{% block page_title %}{{ block.super }}{% trans "Service instances management" %}{% endblock %}
{% block appbar %}
{{ block.super }}
<a rel="popup" href="{% url "a2-pratic-service-instance-add" collectivity_pk=collectivity.pk %}" id="add-user-btn">{% trans "Add service-instance" %}</a>
{% endblock %}
{% block sidebar %}
<p>{% blocktrans count count=object_list.count %}{{ count }} services instances{% plural %}{{ count }} service instance{% endblocktrans %}</p>
{% endblock %}
{% block main %}
{% render_table table "authentic2_pratic/table.html" %}
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "authentic2_pratic/sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page-title %}{{ block.super }} - {% trans "Services management" %}{% endblock %}
{% block page_title %}{% trans "Services management" %}{% endblock %}
{% block appbar %}
{{ block.super }}
<a rel="popup" href="{% url "a2-pratic-service-add" %}" id="add-user-btn">{% trans "Add service" %}</a>
{% endblock %}
{% block sidebar %}
<p>{% blocktrans count count=object_list.count %}{{ count }} services{% plural %}{{ count }} service{% endblocktrans %}</p>
{% endblock %}
{% block main %}
{% render_table table "authentic2_pratic/table.html" %}
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "authentic2_pratic/base.html" %}
{% block content %}
<div id="sidebar">
{% block sidebar %}
{% endblock %}
</div>
<div class="content">
{% block main %}
{% endblock %}
</div>
{% endblock %}

View File

@ -0,0 +1,58 @@
{% extends "django_tables2/table.html" %}
{% load django_tables2 %}
{% block table.thead %}
<thead>
<tr>
{% for column in table.columns %}
{% if column.orderable %}
<th {{ column.attrs.th.as_html }}><a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}">{{ column.header }}</a></th>
{% else %}
<th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
{% endif %}
{% endfor %}
{% block table.head.last.column %}
{% endblock %}
</tr>
</thead>
{% endblock table.thead %}
{% block table.tbody.row %}
<tr data-ref="{{ row.record.id }}" class="{{ forloop.counter|divisibleby:2|yesno:"even,odd" }}"> {# avoid cycle for Django 1.2-1.6 compatibility #}
{% for column, cell in row.items %}
<td {{ column.attrs.td.as_html }}>{% if column.localize == None %}{{ cell }}{% else %}{% if column.localize %}{{ cell|localize }}{% else %}{{ cell|unlocalize }}{% endif %}{% endif %}</td>
{% endfor %}
{% block table.tbody.last.column %}
{% endblock %}
</tr>
{% endblock table.tbody.row %}
{% block pagination %}
<p class="paginator">
{% if table.page.number > 1 %}
{% if table.page.previous_page_number != 1 %}
<a href="{% querystring table.prefixed_page_field=1 %}">1</a>
...
{% endif %}
{% endif %}
{% if table.page.has_previous %}
<a href="{% querystring table.prefixed_page_field=table.page.previous_page_number %}">{{ table.page.previous_page_number }}</a>
{% endif %}
<span class="this-page">{{ table.page.number }}</span>
{% if table.page.has_next %}
<a href="{% querystring table.prefixed_page_field=table.page.next_page_number %}">{{ table.page.next_page_number }}</a>
{% endif %}
{% if table.page.number != table.page.paginator.num_pages %}
{% if table.page.paginator.num_pages > 1 %}
{% if table.page.next_page_number != table.page.paginator.num_pages %}
...
<a href="{% querystring table.prefixed_page_field=table.page.paginator.num_pages %}">{{ table.page.paginator.num_pages }}</a>
{% endif %}
{% endif %}
{% endif %}
</p>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "authentic2_pratic/collectivity_sidebar.html" %}
{% load i18n staticfiles django_tables2 %}
{% block page-title %}{{ block.super }} - {% trans "Users management" %}{% endblock %}
{% block page_title %}{{ block.super }}{% trans "Users management" %}{% endblock %}
{% block appbar %}
{{ block.super }}
<a rel="popup" href="{% url "a2-pratic-user-add" collectivity_pk=collectivity.pk %}" id="add-user-btn">{% trans "Add user" %}</a>
{% endblock %}
{% block sidebar %}
<p>{% blocktrans count count=object_list.count %}{{ count }} users{% plural %}{{ count }} user{% endblocktrans %}</p>
{% endblock %}
{% block main %}
{% render_table table "authentic2_pratic/table.html" %}
{% endblock %}

View File

@ -0,0 +1,61 @@
from django.conf.urls import patterns, url, include
from . import views
access_urlpatterns = patterns('',
url('^$',
views.access_edit,
name='a2-pratic-access-edit'),
url('^delete/$',
views.access_delete,
name='a2-pratic-access-delete'))
service_instance_urlpatterns = patterns('',
url('^$',
views.service_instance_edit,
name='a2-pratic-service-instance-edit'),
url('^delete/$',
views.service_instance_delete,
name='a2-pratic-service-instance-delete'))
user_urlpatterns = patterns('',
url('^$', views.user_edit, name='a2-pratic-user-edit'),
url('^delete/$', views.user_delete, name='a2-pratic-user-delete'))
collectivity_urlpatterns = patterns('',
url('^$', views.collectivity_edit, name='a2-pratic-collectivity-edit'),
url('^delete/$', views.collectivity_delete, name='a2-pratic-collectivity-delete'),
url('^users/$', views.collectivity_users, name='a2-pratic-users'),
url('^users/add/$',
views.user_add,
name='a2-pratic-user-add'),
url('^users/(?P<pk>\d+)/',
include(user_urlpatterns)),
url('^services/$',
views.collectivity_service_instances,
name='a2-pratic-service-instances'),
url('^services/add/$',
views.service_instance_add,
name='a2-pratic-service-instance-add'),
url('^services/(?P<pk>\d+)/',
include(service_instance_urlpatterns)),
url('^accesses/$',
views.collectivity_accesses,
name='a2-pratic-accesses'),
url('^accesses/add/$',
views.access_add,
name='a2-pratic-access-add'),
url('^accesses/(?P<pk>\d+)/$',
include(access_urlpatterns)),
)
urlpatterns = patterns('',
url('^manage/$', views.homepage, name='a2-pratic-homepage'),
url('^manage/services/$', views.services, name='a2-pratic-services'),
url('^manage/services/add/$', views.service_add, name='a2-pratic-service-add'),
url('^manage/services/(?P<pk>\d+)/delete/$', views.service_delete, name='a2-pratic-service-delete'),
url('^manage/services/(?P<pk>\d+)/$', views.service_edit, name='a2-pratic-service-edit'),
url('^manage/collectivities/$', views.collectivities, name='a2-pratic-collectivities'),
url('^manage/collectivities/add/$', views.collectivity_add, name='a2-pratic-collectivity-add'),
url('^manage/collectivities/(?P<collectivity_pk>\d+)/', include(collectivity_urlpatterns)),
)

View File

@ -0,0 +1,239 @@
import logging
from django.contrib.auth.decorators import login_required, user_passes_test
from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.contrib import messages
from django.views.generic import (TemplateView, FormView, UpdateView,
CreateView, DeleteView, View, ListView)
from django_tables2 import SingleTableView
from authentic2.manager.views import (AjaxFormViewMixin,
ActionMixin, OtherActionsMixin, TitleMixin, Action, UserEditView)
from . import models, tables, forms
def is_pratic_admin(user):
if user.is_superuser:
return True
return getattr(user, 'is_admin', False)
pratic_admin = user_passes_test(is_pratic_admin)
class DeleteActionMixin(object):
def get_other_actions(self):
yield Action('delete',
_('Delete'),
_(u'Do you really want to delete "%s" ?') % self.object)
def action_delete(self, request, *args, **kwargs):
self.object.delete()
return HttpResponseRedirect('.')
class HomepageView(TemplateView):
template_name = 'authentic2_pratic/homepage.html'
# Services
class ServicesView(SingleTableView):
template_name = 'authentic2_pratic/services.html'
model = models.Service
table_class = tables.ServiceTable
class ServiceAddView(TitleMixin, ActionMixin, AjaxFormViewMixin, CreateView):
model = models.Service
form_class = forms.ServiceForm
title = _('Add service')
template_name = 'authentic2_pratic/form.html'
action = _('Add')
class ServiceView(DeleteActionMixin, TitleMixin, OtherActionsMixin,
AjaxFormViewMixin, UpdateView):
model = models.Service
title = _('Edit service')
template_name = 'authentic2_pratic/form.html'
form_class = forms.ServiceForm
class ServiceDeleteView(TitleMixin, AjaxFormViewMixin, DeleteView):
model = models.Service
template_name = 'authentic2_pratic/delete.html'
title = _('Delete service')
success_url = 'a2-pratic-services'
# Collectivities
class CollectivitiesView(SingleTableView):
template_name = 'authentic2_pratic/collectivities.html'
model = models.Collectivity
table_class = tables.CollectivityTable
class CollectivityAddView(TitleMixin, ActionMixin, AjaxFormViewMixin, CreateView):
model = models.Collectivity
title = _('Add collectivity')
template_name = 'authentic2_pratic/form.html'
action = _('Add')
class CollectivityView(DeleteActionMixin, TitleMixin, OtherActionsMixin,
AjaxFormViewMixin, UpdateView):
model = models.Collectivity
title = _('Edit collectivity')
template_name = 'authentic2_pratic/collectivity_edit.html'
form_class = forms.CollectivityForm
pk_url_kwarg = 'collectivity_pk'
class CollectivityDeleteView(TitleMixin, AjaxFormViewMixin, DeleteView):
model = models.Service
template_name = 'authentic2_pratic/delete.html'
title = _('Delete collectivity')
success_url = 'a2-pratic-collectivities'
pk_url_kwarg = 'collectivity_pk'
class CollectivityMixin(object):
def dispatch(self, request, *args, **kwargs):
self.collectivity = get_object_or_404(models.Collectivity,
pk=kwargs['collectivity_pk'])
return super(CollectivityMixin, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super(CollectivityMixin, self).get_context_data(**kwargs)
ctx['collectivity'] = self.collectivity
return ctx
class CollectivityChildMixin(CollectivityMixin):
def get_queryset(self):
qs = super(CollectivityMixin, self).get_queryset()
return qs.filter(collectivity=self.collectivity)
def get_form_kwargs(self):
kwargs = super(CollectivityMixin, self).get_form_kwargs()
if not kwargs.get('instance'):
kwargs['instance'] = self.model(collectivity=self.collectivity)
return kwargs
# users
class UsersView(CollectivityChildMixin, SingleTableView):
template_name = 'authentic2_pratic/users.html'
model = models.User
table_class = tables.UserTable
class UserAddView(CollectivityChildMixin, TitleMixin, ActionMixin,
AjaxFormViewMixin, CreateView):
model = models.User
title = _('Add user')
template_name = 'authentic2_pratic/form.html'
action = _('Add')
form_class = forms.UserForm
class UserView(CollectivityChildMixin, UserEditView):
model = models.User
title = _('Edit user')
template_name = 'authentic2_pratic/form.html'
form_class = forms.UserForm
class UserDeleteView(CollectivityChildMixin, TitleMixin, AjaxFormViewMixin,
DeleteView):
model = models.Service
template_name = 'authentic2_pratic/delete.html'
title = _('Delete user')
success_url = 'a2-pratic-users'
# service instances
class ServiceInstancesView(CollectivityChildMixin, SingleTableView):
template_name = 'authentic2_pratic/service_instances.html'
model = models.ServiceInstance
table_class = tables.ServiceInstanceTable
class ServiceInstanceAddView(CollectivityChildMixin, TitleMixin, ActionMixin,
AjaxFormViewMixin, CreateView):
model = models.ServiceInstance
title = _('Add service instance')
template_name = 'authentic2_pratic/form.html'
action = _('Add')
form_class = forms.ServiceInstanceForm
class ServiceInstanceView(CollectivityChildMixin, DeleteActionMixin, TitleMixin,
OtherActionsMixin, AjaxFormViewMixin, UpdateView):
model = models.ServiceInstance
title = _('Edit service instance')
template_name = 'authentic2_pratic/form.html'
form_class = forms.ServiceInstanceForm
class ServiceInstanceDeleteView(CollectivityChildMixin, TitleMixin,
AjaxFormViewMixin, DeleteView):
model = models.ServiceInstance
template_name = 'authentic2_pratic/delete.html'
title = _('Delete service instance')
success_url = 'a2-pratic-users'
# accesses
class AccessMixin(object):
def get_queryset(self):
qs = self.model.objects.all()
return qs.filter(user__collectivity=self.collectivity,
service_instance__collectivity=self.collectivity)
def get_form_kwargs(self):
kwargs = super(CollectivityMixin, self).get_form_kwargs()
kwargs['collectivity'] = self.collectivity
return kwargs
class AccessesView(AccessMixin, CollectivityMixin, SingleTableView):
template_name = 'authentic2_pratic/accesses.html'
model = models.Access
table_class = tables.AccessTable
class AccessAddView(AccessMixin, CollectivityMixin, TitleMixin, ActionMixin,
AjaxFormViewMixin, CreateView):
model = models.Access
title = _('Add service instance')
template_name = 'authentic2_pratic/form.html'
action = _('Add')
form_class = forms.AccessForm
class AccessView(AccessMixin, CollectivityMixin, DeleteActionMixin, TitleMixin,
OtherActionsMixin, AjaxFormViewMixin, UpdateView):
model = models.Access
title = _('Edit service instance')
template_name = 'authentic2_pratic/form.html'
form_class = forms.AccessForm
class AccessDeleteView(AccessMixin, CollectivityMixin, TitleMixin,
AjaxFormViewMixin, DeleteView):
model = models.Access
template_name = 'authentic2_pratic/delete.html'
title = _('Delete service instance')
success_url = 'a2-pratic-users'
# general views
homepage = pratic_admin(HomepageView.as_view())
# services
services = pratic_admin(ServicesView.as_view())
service_edit = pratic_admin(ServiceView.as_view())
service_add = pratic_admin(ServiceAddView.as_view())
service_delete = pratic_admin(ServiceDeleteView.as_view())
# collectivities
collectivities = pratic_admin(CollectivitiesView.as_view())
collectivity_edit = pratic_admin(CollectivityView.as_view())
collectivity_add = pratic_admin(CollectivityAddView.as_view())
collectivity_delete = pratic_admin(CollectivityDeleteView.as_view())
# collectivity users
collectivity_users = pratic_admin(UsersView.as_view())
user_add = pratic_admin(UserAddView.as_view())
user_edit = pratic_admin(UserView.as_view())
user_delete = pratic_admin(UserDeleteView.as_view())
# service instances
collectivity_service_instances = pratic_admin(ServiceInstancesView.as_view())
service_instance_add = pratic_admin(ServiceInstanceAddView.as_view())
service_instance_edit = pratic_admin(ServiceInstanceView.as_view())
service_instance_delete = pratic_admin(ServiceInstanceDeleteView.as_view())
# accesses
collectivity_accesses = pratic_admin(AccessesView.as_view())
access_add = pratic_admin(AccessAddView.as_view())
access_edit = pratic_admin(AccessView.as_view())
access_delete = pratic_admin(AccessDeleteView.as_view())