wip
This commit is contained in:
parent
af98a203e7
commit
bb61f1059e
|
@ -27,7 +27,7 @@ class AppConfig(django.apps.AppConfig):
|
|||
from django_rbac.models import Operation
|
||||
from django_rbac.utils import get_operation
|
||||
|
||||
FC_MANAGE_OP = Operation(name=u'Gérer les fédérations France Connect',
|
||||
FC_MANAGE_OP = Operation(name=u'Gérer France Connect',
|
||||
slug='fc_manage')
|
||||
get_operation(FC_MANAGE_OP)
|
||||
|
||||
|
@ -46,7 +46,7 @@ class AppConfig(django.apps.AppConfig):
|
|||
from .utils import update_roles
|
||||
update_roles()
|
||||
|
||||
def get_a2_manager_actions(self, model=None, **kwargs):
|
||||
def a2_hook_manager_other_actions(self, model=None, **kwargs):
|
||||
'''Retourne des actions utilisateurs pour la gestion France Connect'''
|
||||
from django.contrib.auth import get_user_model
|
||||
from .actions import FranceConnect
|
||||
|
@ -55,14 +55,269 @@ class AppConfig(django.apps.AppConfig):
|
|||
return [FranceConnect]
|
||||
return []
|
||||
|
||||
def get_a2_manager_other_data(self, model=None, **kwargs):
|
||||
def a2_hook_manager_user_data(self, view, user):
|
||||
'''Retourne des objets pour afficher la fédération France Connect'''
|
||||
from django.contrib.auth import get_user_model
|
||||
from .user_datas import FranceConnectUserData
|
||||
from .user_datas import FranceConnectUserData, ValidationUserData
|
||||
|
||||
user_datas = []
|
||||
|
||||
if view.__class__.__name__ == 'UserDetailView':
|
||||
user_datas.append(
|
||||
FranceConnectUserData(user, view.request),
|
||||
)
|
||||
if user.attributes.validated:
|
||||
user_datas.append(
|
||||
ValidationUserData(user)
|
||||
)
|
||||
return user_datas
|
||||
|
||||
def a2_hook_manager_modify_form(self, view, form):
|
||||
from django.forms.widgets import DateTimeInput, HiddenInput
|
||||
from authentic2.passwords import generate_password
|
||||
|
||||
from . import models
|
||||
|
||||
if view.__class__.__name__ == 'UserAddView':
|
||||
# Les usagers CUT n'ont pas d'identifiant
|
||||
ou = getattr(form, 'ou', None)
|
||||
if ou:
|
||||
password = generate_password()
|
||||
form.fields['password1'].initial = password
|
||||
form.fields['password1'].widget = HiddenInput()
|
||||
form.fields['password2'].initial = password
|
||||
form.fields['password2'].widget = HiddenInput()
|
||||
if ou.slug == 'usagers':
|
||||
del form.fields['username']
|
||||
for field_name in ['is_superuser', 'validated',
|
||||
'validation_context', 'validation_date']:
|
||||
if field_name in form.fields:
|
||||
del form.fields[field_name]
|
||||
|
||||
form.fields['generate_password'].initial = False
|
||||
form.fields['generate_password'].widget = HiddenInput()
|
||||
form.fields['reset_password_at_next_login'].initial = False
|
||||
form.fields['reset_password_at_next_login'].widget = HiddenInput()
|
||||
form.fields['send_mail'].initial = False
|
||||
form.fields['send_mail'].widget = HiddenInput()
|
||||
form.fields['send_password_reset'].initial = True
|
||||
form.fields['send_password_reset'].widget = HiddenInput()
|
||||
else:
|
||||
for field_name in form.fields:
|
||||
if field_name not in ['username',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'generate_password']:
|
||||
del form.fields[field_name]
|
||||
form.fields['email'].required = True
|
||||
form.fields['generate_password'].initial = True
|
||||
form.fields['generate_password'].widget.attrs = {'readonly': ''}
|
||||
form.fields['send_password_reset'].initial = True
|
||||
form.fields['send_password_reset'].widget = HiddenInput()
|
||||
old_save = form.save
|
||||
|
||||
def new_save(*args, **kwargs):
|
||||
response = old_save(*args, **kwargs)
|
||||
models.Journal.objects.create(
|
||||
actor=form.request.user,
|
||||
subject=form.instance,
|
||||
message='création du compte')
|
||||
return response
|
||||
form.save = new_save
|
||||
|
||||
if view.__class__.__name__ == 'UserEditView':
|
||||
# Les usagers CUT n'ont pas d'identifiant
|
||||
if form.instance.ou:
|
||||
if form.instance.ou.slug == 'usagers':
|
||||
form.fields['email'].required = True
|
||||
del form.fields['username']
|
||||
for field_name in ['password1', 'password2', 'is_superuser', 'validated',
|
||||
'validation_context', 'validation_date']:
|
||||
if field_name in form.fields:
|
||||
del form.fields[field_name]
|
||||
else:
|
||||
for field_name in form.fields:
|
||||
if field_name not in ['username',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'is_superuser',
|
||||
'generate_password']:
|
||||
del form.fields[field_name]
|
||||
form.fields['email'].required = True
|
||||
old_save = form.save
|
||||
|
||||
def new_save(*args, **kwargs):
|
||||
response = old_save(*args, **kwargs)
|
||||
models.Journal.objects.create(
|
||||
actor=form.request.user,
|
||||
subject=form.instance,
|
||||
message='modification des données')
|
||||
return response
|
||||
form.save = new_save
|
||||
# Si un compte est validé, on interdit la modification des attributs coeurs
|
||||
if form.instance.attributes.validated:
|
||||
for field_name in form.fields:
|
||||
if field_name in ['first_name',
|
||||
'last_name',
|
||||
'birthcountry_insee',
|
||||
'birthplace_insee',
|
||||
'birthcountry',
|
||||
'birthplace',
|
||||
'gender', 'title',
|
||||
'birthdate']:
|
||||
# del form.fields[field_name]
|
||||
field = form.fields[field_name]
|
||||
field.required = False
|
||||
if field_name == 'birthdate':
|
||||
field.widget = DateTimeInput(attrs={'readonly': ''})
|
||||
attrs = field.widget.attrs or {}
|
||||
attrs['disabled'] = ''
|
||||
attrs['title'] = u'Champ validé'
|
||||
field.widget.attrs = attrs
|
||||
|
||||
def new_clean(self, field_name):
|
||||
def clean():
|
||||
self.instance.refresh_from_db()
|
||||
if hasattr(self.instance, field_name):
|
||||
return getattr(self.instance, field_name)
|
||||
else:
|
||||
return getattr(self.instance.attributes, field_name)
|
||||
return clean
|
||||
setattr(form, 'clean_' + field_name, new_clean(form, field_name))
|
||||
if field_name in ['generate_password']:
|
||||
del form.fields[field_name]
|
||||
|
||||
if view.__class__.__name__ == 'UserDetailView':
|
||||
if form.instance.ou:
|
||||
if form.instance.ou.slug == 'usagers':
|
||||
for field_name in ['username', 'is_superuser', 'validated',
|
||||
'validation_context', 'validation_date']:
|
||||
if field_name in form.fields:
|
||||
del form.fields[field_name]
|
||||
else:
|
||||
for field_name in form.fields:
|
||||
if field_name not in ['username', 'first_name', 'last_name', 'email']:
|
||||
del form.fields[field_name]
|
||||
|
||||
if view.__class__.__name__ in ['OrganizationalUnitEditView', 'OrganizationalUnitAddView']:
|
||||
del form.fields['default']
|
||||
del form.fields['email_is_unique']
|
||||
del form.fields['username_is_unique']
|
||||
|
||||
def a2_hook_manager_modify_table(self, view, table):
|
||||
import django_tables2 as tables
|
||||
|
||||
if view.__class__.__name__ == 'UsersView':
|
||||
ou = view.search_form.cleaned_data['ou']
|
||||
sequence = list(table.sequence)
|
||||
if ou and ou.slug == 'usagers':
|
||||
for column_name in ['username', 'link']:
|
||||
if column_name in table.base_columns:
|
||||
del table.base_columns[column_name]
|
||||
if column_name in sequence:
|
||||
sequence.remove(column_name)
|
||||
sequence.remove('email')
|
||||
sequence.insert(2, 'email')
|
||||
table.base_columns['preferred_username'] = tables.Column(
|
||||
accessor='attributes.preferred_username', verbose_name=u'Nom d\'usage')
|
||||
sequence.insert(2, 'preferred_username')
|
||||
table.base_columns['validated'] = tables.BooleanColumn(
|
||||
accessor='attributes.validated', verbose_name=u'Validé')
|
||||
sequence += ['validated']
|
||||
else:
|
||||
del table.base_columns['link']
|
||||
sequence.remove('link')
|
||||
table.columns = tables.columns.BoundColumns(table)
|
||||
table.sequence = sequence
|
||||
return table
|
||||
|
||||
def a2_hook_api_modify_serializer(self, view, original_serializer):
|
||||
from rest_framework import serializers
|
||||
|
||||
if hasattr(original_serializer, 'child'):
|
||||
serializer = original_serializer.child
|
||||
else:
|
||||
serializer = original_serializer
|
||||
|
||||
if view.__class__.__name__ == 'UsersAPI':
|
||||
del serializer.fields['id']
|
||||
del serializer.fields['uuid']
|
||||
del serializer.fields['is_superuser']
|
||||
del serializer.fields['is_staff']
|
||||
del serializer.fields['password']
|
||||
serializer.fields['ou'].write_only = True
|
||||
serializer.fields['ou'].read_only = True
|
||||
del serializer.fields['username']
|
||||
del serializer.fields['last_login']
|
||||
|
||||
def get_gender(obj):
|
||||
title = obj.attributes.title
|
||||
return {'Monsieur': 'male', 'Madame': 'female'}.get(title)
|
||||
serializer.get_gender = get_gender
|
||||
|
||||
serializer.fields['gender'] = serializers.SerializerMethodField()
|
||||
serializer.fields['sub'] = serializers.UUIDField(read_only=True, source='uuid',
|
||||
label='IDCut')
|
||||
serializer.fields['given_name'] = serializers.CharField(read_only=True,
|
||||
source='first_name')
|
||||
serializer.fields['family_name'] = serializers.CharField(read_only=True,
|
||||
source='last_name')
|
||||
serializer.fields['email_verified'].read_only = True
|
||||
|
||||
def a2_hook_modify_context_data(self, view, context):
|
||||
from .custom_settings import CORE_ATTRIBUTES, CROWN_ATTRIBUTES
|
||||
|
||||
if view.__class__.__name__ == 'ProfileView':
|
||||
context['cut_core_filled'] = all(getattr(view.request.user.attributes, a, None) for a in
|
||||
CORE_ATTRIBUTES)
|
||||
context['cut_crown_filled'] = any(getattr(view.request.user.attributes, a, None) for a
|
||||
in CROWN_ATTRIBUTES)
|
||||
|
||||
def a2_hook_manager_modify_other_actions(self, view, other_actions):
|
||||
from authentic2.manager.views import Action
|
||||
|
||||
class CUTValidate(Action):
|
||||
name = 'cut-validate'
|
||||
title = 'Valider le compte'
|
||||
permission = 'custom_user.cut_validate_user'
|
||||
url_name = 'cut-manager-user-edit-core'
|
||||
popup = False
|
||||
|
||||
def display(self, user, request):
|
||||
if user.ou and user.ou.slug != 'usagers':
|
||||
return False
|
||||
if user.attributes.validated and user.attributes.validation_context == 'fc':
|
||||
return False
|
||||
if user.attributes.validated:
|
||||
self.title = u'Modifier les données coeur'
|
||||
self.user = user
|
||||
return super(CUTValidate, self).display(user, request)
|
||||
|
||||
class CUTJournalActions(Action):
|
||||
name = 'cut-journal-actions'
|
||||
title = 'Journal des actions'
|
||||
permission = 'custom_user.view_user'
|
||||
url_name = 'cut-manager-user-actions-journal'
|
||||
popup = False
|
||||
|
||||
def display(self, user, request):
|
||||
if user.ou and user.ou.slug == 'usagers':
|
||||
return False
|
||||
return super(CUTJournalActions, self).display(user, request)
|
||||
|
||||
class CUTJournalModifications(Action):
|
||||
name = 'cut-journal-modifications'
|
||||
title = 'Journal des modifications'
|
||||
permission = 'custom_user.view_user'
|
||||
url_name = 'cut-manager-user-modifications-journal'
|
||||
popup = False
|
||||
|
||||
if view.__class__.__name__ == 'UserDetailView':
|
||||
other_actions.append(CUTValidate())
|
||||
other_actions.append(CUTJournalActions())
|
||||
other_actions.append(CUTJournalModifications())
|
||||
|
||||
if issubclass(model, get_user_model()):
|
||||
return [FranceConnectUserData]
|
||||
return []
|
||||
|
||||
default_app_config = 'authentic2_cut.AppConfig'
|
||||
|
||||
|
|
|
@ -1,12 +1,184 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from authentic2.settings import INSTALLED_APPS, CACHES
|
||||
|
||||
CORE_ATTRIBUTES = [
|
||||
'title',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'birthdate',
|
||||
'birthplace',
|
||||
'birthcountry'
|
||||
]
|
||||
|
||||
CROWN_ATTRIBUTES = [
|
||||
'preferred_username',
|
||||
'preferred_givenname',
|
||||
'address_number',
|
||||
'address_street',
|
||||
'address_complement',
|
||||
'address_zipcode',
|
||||
'address_city',
|
||||
'address_country',
|
||||
'home_mobile_phone',
|
||||
'home_phone',
|
||||
'professional_mobile_phone',
|
||||
'professional_phone',
|
||||
'birthdepartment'
|
||||
]
|
||||
|
||||
# Manager
|
||||
A2_MANAGER_SHOW_INTERNAL_ROLES = True
|
||||
A2_MANAGER_ROLE_MEMBERS_FROM_OU = True
|
||||
A2_MANAGER_USER_SEARCH_MINIMUM_CHARS = 2
|
||||
A2_MANAGER_ROLES_SHOW_PERMISSIONS = True
|
||||
A2_MANAGER_ROLE_MEMBERS_FROM_OU = True
|
||||
|
||||
|
||||
class RemoveFranceConnect(object):
|
||||
name = 'remove-franceconnect'
|
||||
title = 'Supprimer la liaison FranceConnect'
|
||||
confirm = 'Êtes-vous sûr?'
|
||||
|
||||
def do(self, user, request, *args, **kwargs):
|
||||
from authentic2_auth_fc.models import FcAccount
|
||||
|
||||
FcAccount.objects.filter(user=user).delete()
|
||||
|
||||
def display(self, user, request):
|
||||
from authentic2_auth_fc.models import FcAccount
|
||||
|
||||
return FcAccount.objects.filter(user=user).exists()
|
||||
|
||||
A2_MANAGER_USER_ACTIONS = [RemoveFranceConnect()]
|
||||
|
||||
|
||||
class FranceConnectUserData(object):
|
||||
def __init__(self, user, request):
|
||||
self.user = user
|
||||
self.request = request
|
||||
|
||||
def __unicode__(self):
|
||||
from authentic2_auth_fc.models import FcAccount
|
||||
try:
|
||||
FcAccount.objects.get(user=self.user)
|
||||
return u'Utilisateur relié à un compte FranceConnect'
|
||||
except FcAccount.DoesNotExist:
|
||||
return u''
|
||||
|
||||
A2_MANAGER_USER_DATA = [FranceConnectUserData]
|
||||
|
||||
|
||||
def modify_user_info(user, user_info, scope_set):
|
||||
import logging
|
||||
|
||||
user_info.clear()
|
||||
if 'email' in scope_set:
|
||||
logging.info('givin email')
|
||||
user_info['email'] = user.email
|
||||
if 'profile' in scope_set:
|
||||
logging.info('givin profile')
|
||||
user_info['first_name'] = user.first_name
|
||||
user_info['last_name'] = user.last_name
|
||||
user_info['given_name'] = user.first_name
|
||||
user_info['family_name'] = user.last_name
|
||||
user_info['title'] = user.attributes.title
|
||||
user_info['gender'] = {'Monsieur': 'male', 'Madame': 'female'}.get(user.attributes.title)
|
||||
user_info['birthdate'] = user.attributes.birthdate and user.attributes.birthdate.isoformat()
|
||||
user_info['birthplace'] = user.attributes.birthplace
|
||||
user_info['birthcountry'] = user.attributes.birthcountry
|
||||
user_info['birthplace_insee'] = user.attributes.birthplace_insee
|
||||
user_info['birthcountry_insee'] = user.attributes.birthcountry_insee
|
||||
user_info['validated'] = user.attributes.validated
|
||||
user_info['validation_date'] = user.attributes.validation_date and user.attributes.validation_date.isoformat()
|
||||
user_info['validation_context'] = user.attributes.validation_context
|
||||
if 'crown' in scope_set:
|
||||
logging.info('giving crown')
|
||||
user_info['preferred_username'] = user.attributes.preferred_username
|
||||
user_info['preferred_givenname'] = user.attributes.preferred_givenname
|
||||
user_info['address_number'] = user.attributes.address_number
|
||||
user_info['address_street'] = user.attributes.address_street
|
||||
user_info['address_complement'] = user.attributes.address_complement
|
||||
user_info['address_zipcode'] = user.attributes.address_zipcode
|
||||
user_info['address_city'] = user.attributes.address_city
|
||||
user_info['address_country'] = user.attributes.address_country
|
||||
user_info['home_mobile_phone'] = user.attributes.home_mobile_phone
|
||||
user_info['home_phone'] = user.attributes.home_phone
|
||||
user_info['professional_mobile_phone'] = user.attributes.professional_mobile_phone
|
||||
user_info['professional_phone'] = user.attributes.professional_phone
|
||||
user_info['birthdepartment'] = user.attributes.birthdepartment
|
||||
|
||||
A2_IDP_OIDC_MODIFY_USER_INFO = modify_user_info
|
||||
|
||||
|
||||
def modify_profile_form(form):
|
||||
if form.instance and form.instance.attributes.validated:
|
||||
for field in ('first_name', 'last_name', 'birthdate', 'title',
|
||||
'birthplace', 'birthcountry'):
|
||||
form.fields.pop(field, None)
|
||||
return form
|
||||
|
||||
A2_MODIFY_PROFILE_FORM = modify_profile_form
|
||||
|
||||
|
||||
A2_PROFILE_FIELDS = [
|
||||
u'email',
|
||||
u'title',
|
||||
u'last_name',
|
||||
u'first_name',
|
||||
u'birthdate',
|
||||
u'birthplace',
|
||||
u'birthcountry',
|
||||
u'preferred_username',
|
||||
u'preferred_givenname',
|
||||
u'address_number',
|
||||
u'address_street',
|
||||
u'address_complement',
|
||||
u'address_zipcode',
|
||||
u'address_city',
|
||||
u'address_country',
|
||||
u'home_mobile_phone',
|
||||
u'home_phone',
|
||||
u'professional_mobile_phone',
|
||||
u'professional_phone',
|
||||
u'birthdepartment',
|
||||
u'comment',
|
||||
u'validated',
|
||||
u'validation_date',
|
||||
u'validation_context',
|
||||
]
|
||||
A2_REGISTRATION_FIELDS = [
|
||||
u'title',
|
||||
u'last_name',
|
||||
u'first_name',
|
||||
u'birthdate',
|
||||
u'birthplace',
|
||||
u'birthcountry',
|
||||
u'preferred_username',
|
||||
u'preferred_givenname',
|
||||
u'address_number',
|
||||
u'address_street',
|
||||
u'address_complement',
|
||||
u'address_zipcode',
|
||||
u'address_city',
|
||||
u'address_country',
|
||||
u'home_mobile_phone',
|
||||
u'home_phone',
|
||||
u'professional_mobile_phone',
|
||||
u'professional_phone',
|
||||
u'birthdepartment'
|
||||
]
|
||||
A2_REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
|
||||
A2_PRE_REGISTRATION_FIELDS = ['first_name', 'last_name']
|
||||
|
||||
A2_RBAC_MANAGED_CONTENT_TYPES = ()
|
||||
A2_CUT_PARTNERS = [
|
||||
{
|
||||
'domains': ['.lyon.fr'],
|
||||
'name': u'Ville de Lyon',
|
||||
},
|
||||
{
|
||||
'domains': ['.entrouvert.org'],
|
||||
'name': u'Ville de Lyon',
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -22,5 +194,40 @@ if ('Memcached' in CACHES['default']['BACKEND'] or 'Memcached' in
|
|||
print 'canot load django-cachalot', e
|
||||
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
|
||||
# 48h pour les mails de reset de mot de passe
|
||||
PASSWORD_RESET_TIMEOUT_DAYS = 2
|
||||
A2_EMAIL_CHANGE_TOKEN_LIFETIME = 3600 * 24 * 2
|
||||
ACCOUNT_ACTIVATION_DAYS = 2
|
||||
|
||||
|
||||
# CACHALOT_UNCACHABLE_TABLES = ('custom_user_user', 'django_migrations')
|
||||
TEMPLATE_VARS = {
|
||||
'theme': 'grandlyon-cut',
|
||||
'css_variant': 'grandlyon-cut',
|
||||
'theme_base': 'theme.html',
|
||||
'theme_base_filename': 'theme.html',
|
||||
}
|
||||
|
||||
# OIDC
|
||||
A2_IDP_OIDC_SCOPES = ['openid', 'email', 'profile', 'crown']
|
||||
|
||||
A2_FC_USER_INFO_MAPPINGS = {
|
||||
'first_name': 'given_name',
|
||||
'last_name': 'family_name',
|
||||
'birthdate': {'ref': 'birthdate', 'translation': 'isodate'},
|
||||
'birthplace': {'ref': 'birthplace', 'translation': 'insee-communes'},
|
||||
'birthcountry': {'ref': 'birthcountry', 'translation': 'insee-countries'},
|
||||
'birthplace_insee': 'birthplace',
|
||||
'birthcountry_insee': 'birthcountry',
|
||||
'title': {
|
||||
'ref': 'gender',
|
||||
'translation': 'simple',
|
||||
'translation_simple': {
|
||||
'male': 'Monsieur',
|
||||
'female': 'Madame',
|
||||
}
|
||||
},
|
||||
'validated': {'value': True},
|
||||
'validation_date': {'compute': 'today'},
|
||||
'validation_context': {'value': 'France Connect'},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,444 @@
|
|||
[
|
||||
{
|
||||
"fields" : {
|
||||
"disabled" : false,
|
||||
"name" : "first_name",
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Prénoms de naissance",
|
||||
"asked_on_registration" : true,
|
||||
"description" : "",
|
||||
"required" : true,
|
||||
"searchable" : false,
|
||||
"multiple" : false,
|
||||
"user_editable" : true
|
||||
},
|
||||
"pk" : 1,
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"pk" : 2,
|
||||
"fields" : {
|
||||
"user_editable" : true,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : true,
|
||||
"multiple" : false,
|
||||
"user_visible" : true,
|
||||
"label" : "Nom de naissance",
|
||||
"kind" : "string",
|
||||
"asked_on_registration" : true,
|
||||
"disabled" : false,
|
||||
"name" : "last_name"
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"description" : "",
|
||||
"multiple" : false,
|
||||
"user_editable" : true,
|
||||
"name" : "title",
|
||||
"disabled" : false,
|
||||
"kind" : "title",
|
||||
"label" : "Civilité",
|
||||
"user_visible" : true,
|
||||
"asked_on_registration" : true
|
||||
},
|
||||
"pk" : 3
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"user_editable" : true,
|
||||
"multiple" : false,
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"description" : "",
|
||||
"asked_on_registration" : true,
|
||||
"label" : "Complément d'adresse",
|
||||
"kind" : "string",
|
||||
"user_visible" : true,
|
||||
"name" : "address_complement",
|
||||
"disabled" : false
|
||||
},
|
||||
"pk" : 4
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 5,
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"description" : "",
|
||||
"user_editable" : true,
|
||||
"name" : "address_zipcode",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Code postal",
|
||||
"user_visible" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 6,
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"user_editable" : true,
|
||||
"disabled" : false,
|
||||
"name" : "address_city",
|
||||
"asked_on_registration" : true,
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Nom de la commune"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk" : 7,
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"user_editable" : true,
|
||||
"disabled" : false,
|
||||
"name" : "address_country",
|
||||
"asked_on_registration" : true,
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Pays"
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"fields" : {
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"multiple" : false,
|
||||
"user_editable" : true,
|
||||
"disabled" : false,
|
||||
"name" : "birthdate",
|
||||
"user_visible" : true,
|
||||
"label" : "Date de naissance",
|
||||
"kind" : "date",
|
||||
"asked_on_registration" : true
|
||||
},
|
||||
"pk" : 8,
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 9,
|
||||
"fields" : {
|
||||
"name" : "home_phone",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : true,
|
||||
"label" : "Téléphone fixe personnel",
|
||||
"kind" : "string",
|
||||
"user_visible" : true,
|
||||
"multiple" : false,
|
||||
"searchable" : true,
|
||||
"required" : false,
|
||||
"description" : "",
|
||||
"user_editable" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"name" : "home_mobile_phone",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Téléphone mobile personnel",
|
||||
"user_visible" : true,
|
||||
"multiple" : false,
|
||||
"required" : false,
|
||||
"searchable" : true,
|
||||
"description" : "",
|
||||
"user_editable" : true
|
||||
},
|
||||
"pk" : 10
|
||||
},
|
||||
{
|
||||
"fields" : {
|
||||
"user_editable" : false,
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"asked_on_registration" : false,
|
||||
"user_visible" : false,
|
||||
"kind" : "boolean",
|
||||
"label" : "Validé",
|
||||
"disabled" : false,
|
||||
"name" : "validated"
|
||||
},
|
||||
"pk" : 11,
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"pk" : 12,
|
||||
"fields" : {
|
||||
"disabled" : false,
|
||||
"name" : "birthplace",
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Lieu de naissance",
|
||||
"asked_on_registration" : true,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"multiple" : false,
|
||||
"user_editable" : true
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"user_editable" : true,
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"asked_on_registration" : true,
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Pays de naissance",
|
||||
"disabled" : false,
|
||||
"name" : "birthcountry"
|
||||
},
|
||||
"pk" : 13
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 14,
|
||||
"fields" : {
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Prénoms d'usage",
|
||||
"asked_on_registration" : true,
|
||||
"disabled" : false,
|
||||
"name" : "preferred_givenname",
|
||||
"user_editable" : true,
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : true,
|
||||
"multiple" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : true,
|
||||
"user_editable" : true,
|
||||
"disabled" : false,
|
||||
"name" : "preferred_username",
|
||||
"asked_on_registration" : true,
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Nom d'usage"
|
||||
},
|
||||
"pk" : 15,
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 16,
|
||||
"fields" : {
|
||||
"name" : "birthdepartment",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : true,
|
||||
"label" : "Département de naissance",
|
||||
"kind" : "string",
|
||||
"user_visible" : true,
|
||||
"multiple" : false,
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"description" : "",
|
||||
"user_editable" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 17,
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"description" : "",
|
||||
"user_editable" : true,
|
||||
"name" : "address_street",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Nom de la voie",
|
||||
"user_visible" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk" : 18,
|
||||
"fields" : {
|
||||
"name" : "address_number",
|
||||
"disabled" : false,
|
||||
"kind" : "string",
|
||||
"label" : "Numéro sur la voie",
|
||||
"user_visible" : true,
|
||||
"asked_on_registration" : true,
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"description" : "",
|
||||
"multiple" : false,
|
||||
"user_editable" : true
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 19,
|
||||
"fields" : {
|
||||
"disabled" : false,
|
||||
"name" : "professional_mobile_phone",
|
||||
"user_visible" : true,
|
||||
"kind" : "string",
|
||||
"label" : "Téléphone mobile professionnel",
|
||||
"asked_on_registration" : true,
|
||||
"description" : "",
|
||||
"searchable" : true,
|
||||
"required" : false,
|
||||
"multiple" : false,
|
||||
"user_editable" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"user_editable" : true,
|
||||
"searchable" : true,
|
||||
"required" : false,
|
||||
"description" : "",
|
||||
"multiple" : false,
|
||||
"label" : "Téléphone fixe professionnel",
|
||||
"kind" : "string",
|
||||
"user_visible" : true,
|
||||
"asked_on_registration" : true,
|
||||
"name" : "professional_phone",
|
||||
"disabled" : false
|
||||
},
|
||||
"pk" : 20
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"user_editable" : false,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"multiple" : false,
|
||||
"user_visible" : false,
|
||||
"kind" : "string",
|
||||
"label" : "Commentaire",
|
||||
"asked_on_registration" : false,
|
||||
"disabled" : false,
|
||||
"name" : "comment"
|
||||
},
|
||||
"pk" : 21
|
||||
},
|
||||
{
|
||||
"fields" : {
|
||||
"kind" : "string",
|
||||
"label" : "Contexte de validation",
|
||||
"user_visible" : false,
|
||||
"asked_on_registration" : false,
|
||||
"name" : "validation_context",
|
||||
"disabled" : false,
|
||||
"user_editable" : false,
|
||||
"required" : false,
|
||||
"searchable" : false,
|
||||
"description" : "FranceConnect, Online request, Office qui seront traduits en FranceConnect, Demande en ligne, En guichet.",
|
||||
"multiple" : false
|
||||
},
|
||||
"pk" : 24,
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"pk" : 25,
|
||||
"fields" : {
|
||||
"multiple" : false,
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"description" : "",
|
||||
"user_editable" : false,
|
||||
"name" : "validation_date",
|
||||
"disabled" : false,
|
||||
"asked_on_registration" : false,
|
||||
"kind" : "date",
|
||||
"label" : "Date de validation",
|
||||
"user_visible" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk" : 26,
|
||||
"fields" : {
|
||||
"asked_on_registration" : false,
|
||||
"kind" : "string",
|
||||
"label" : "Lieu de naissance (code INSEE)",
|
||||
"user_visible" : false,
|
||||
"name" : "birthplace_insee",
|
||||
"disabled" : false,
|
||||
"user_editable" : false,
|
||||
"multiple" : false,
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"description" : ""
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
},
|
||||
{
|
||||
"model" : "authentic2.attribute",
|
||||
"fields" : {
|
||||
"user_visible" : false,
|
||||
"label" : "Pays de naissance (code INSEE)",
|
||||
"kind" : "string",
|
||||
"asked_on_registration" : false,
|
||||
"disabled" : false,
|
||||
"name" : "birthcountry_insee",
|
||||
"user_editable" : false,
|
||||
"description" : "",
|
||||
"searchable" : false,
|
||||
"required" : false,
|
||||
"multiple" : false
|
||||
},
|
||||
"pk" : 27
|
||||
},
|
||||
{
|
||||
"pk" : 28,
|
||||
"fields" : {
|
||||
"asked_on_registration" : false,
|
||||
"user_visible" : false,
|
||||
"kind" : "string",
|
||||
"label" : "Genre",
|
||||
"disabled" : false,
|
||||
"name" : "gender",
|
||||
"user_editable" : false,
|
||||
"multiple" : false,
|
||||
"description" : "",
|
||||
"required" : false,
|
||||
"searchable" : false
|
||||
},
|
||||
"model" : "authentic2.attribute"
|
||||
}
|
||||
]
|
|
@ -1,5 +1,6 @@
|
|||
from django.conf import settings
|
||||
import urlparse
|
||||
import logging
|
||||
|
||||
|
||||
class CUTMiddleware(object):
|
||||
|
@ -32,7 +33,13 @@ class CUTMiddleware(object):
|
|||
netloc = urlparse.urlparse(url).netloc
|
||||
if netloc:
|
||||
domain = netloc.split(':')[-1]
|
||||
if domain:
|
||||
|
||||
if not domain:
|
||||
domain = request.session.get('cut_domain')
|
||||
|
||||
if not domain:
|
||||
request.partner = None
|
||||
else:
|
||||
if domain not in self.MATCHES:
|
||||
for partner_def in getattr(settings, 'A2_CUT_PARTNERS', []):
|
||||
patterns = partner_def.get('domains', [])
|
||||
|
@ -52,11 +59,11 @@ class CUTMiddleware(object):
|
|||
# sometimes
|
||||
self.MATCHES[domain] = None
|
||||
request.session['cut_domain'] = None
|
||||
else:
|
||||
domain = request.session.get('cut_domain')
|
||||
|
||||
if domain and domain in self.MATCHES:
|
||||
request.partner = self.MATCHES[domain]
|
||||
else:
|
||||
request.partner = None
|
||||
return None
|
||||
if domain and domain in self.MATCHES:
|
||||
request.partner = self.MATCHES[domain]
|
||||
if request.session.get('cut_domain') != domain:
|
||||
request.session['cut_domain'] = domain
|
||||
else:
|
||||
request.partner = None
|
||||
return None
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Journal',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('timestamp', models.DateTimeField(auto_now_add=True, verbose_name='Horodatage', db_index=True)),
|
||||
('message', models.TextField(verbose_name=b'Message')),
|
||||
('actor', models.ForeignKey(related_name='actor_journal', verbose_name='Auteur', to=settings.AUTH_USER_MODEL)),
|
||||
('subject', models.ForeignKey(related_name='subject_journal', verbose_name=b'Sujet', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-timestamp', '-id'),
|
||||
'verbose_name': 'historique',
|
||||
'verbose_name_plural': 'historiques',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,24 @@
|
|||
from django.db import models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Journal(models.Model):
|
||||
timestamp = models.DateTimeField(
|
||||
verbose_name=u'Horodatage',
|
||||
db_index=True,
|
||||
auto_now_add=True)
|
||||
actor = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
verbose_name=u'Auteur',
|
||||
related_name='actor_journal')
|
||||
subject = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
verbose_name='Sujet',
|
||||
related_name='subject_journal')
|
||||
message = models.TextField(
|
||||
verbose_name='Message')
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'historique'
|
||||
verbose_name_plural = 'historiques'
|
||||
ordering = ('-timestamp', '-id')
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# authentic2_cut - Authentic2 plugin for CUT
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import django_tables2 as tables
|
||||
|
||||
from .models import Journal
|
||||
|
||||
|
||||
class UserActionsTable(tables.Table):
|
||||
class Meta:
|
||||
attrs = {'class': 'main'}
|
||||
model = Journal
|
||||
exclude = ['id', 'actor']
|
||||
empty_text = _('None')
|
||||
|
||||
|
||||
class UserModificationsTable(tables.Table):
|
||||
class Meta:
|
||||
attrs = {'class': 'main'}
|
||||
model = Journal
|
||||
exclude = ['id', 'subject']
|
||||
empty_text = _('None')
|
|
@ -0,0 +1 @@
|
|||
{% extends "authentic2/accounts_edit.html %}
|
|
@ -0,0 +1 @@
|
|||
{% extends "authentic2/accounts_edit.html %}
|
|
@ -0,0 +1,18 @@
|
|||
{% extends "authentic2/manager/base.html" %}
|
||||
{% load i18n staticfiles django_tables2 %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'a2-manager-users' %}{% if object.ou %}?search-ou={{ object.ou.pk }}{% endif %}">{% trans 'Users' %}{% if object.ou %} : {{ object.ou }}{% endif %}</a>
|
||||
<a href="{% url 'a2-manager-user-detail' pk=object.pk %}">{{ object.get_full_name }}</a>
|
||||
<a href="#">Journal des actions</a>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block page_title %}
|
||||
{% trans 'User' %} - {{ object }}x
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% render_table table "authentic2/manager/table.html" %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "authentic2/manager/user_edit.html" %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{{ title }}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<ul class="messages">
|
||||
<li class="info">
|
||||
<p>Vous devez demander à l'usager de présenter une pièce d'identité pour valider son compte ou
|
||||
modifier des données coeur déjà validées.</p>
|
||||
<p>Si l'usager est mineur vous devez demander une attestation d'un tuteur légal.</p>
|
||||
</li>
|
||||
</ul>
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{% extends "authentic2/manager/base.html" %}
|
||||
{% load i18n staticfiles django_tables2 %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'a2-manager-users' %}{% if object.ou %}?search-ou={{ object.ou.pk }}{% endif %}">{% trans 'Users' %}{% if object.ou %} : {{ object.ou }}{% endif %}</a>
|
||||
<a href="{% url 'a2-manager-user-detail' pk=object.pk %}">{{ object.get_full_name }}</a>
|
||||
<a href="#">Journal des modifications</a>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block page_title %}
|
||||
{% trans 'User' %} - {{ object }}x
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% render_table table "authentic2/manager/table.html" %}
|
||||
{% endblock %}
|
|
@ -1,5 +1,5 @@
|
|||
# authentic2_cut - Authentic2 plugin for CUT
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
|
@ -14,9 +14,18 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import patterns, url, include
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
# from . import views
|
||||
from . import views
|
||||
|
||||
urlpatterns = patterns('',
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url('^accounts/edit-core/$', views.edit_core, name='cut-edit-core'),
|
||||
url('^accounts/edit-crown/$', views.edit_crown, name='cut-edit-crown'),
|
||||
url('^manage/users/(?P<pk>\d+)/edit-core/$', views.manager_user_edit_core,
|
||||
name='cut-manager-user-edit-core'),
|
||||
url('^manage/users/(?P<pk>\d+)/actions-journal/$', views.user_actions_journal,
|
||||
name='cut-manager-user-actions-journal'),
|
||||
url('^manage/users/(?P<pk>\d+)/modifications-journal/$', views.user_modifications_journal,
|
||||
name='cut-manager-user-modifications-journal'),
|
||||
)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# authentic2_cut - Authentic2 plugin for CUT
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
|
@ -27,3 +28,21 @@ class FranceConnectUserData(object):
|
|||
return u'Utilisateur relié à un compte FranceConnect'
|
||||
except FcAccount.DoesNotExist:
|
||||
return u''
|
||||
|
||||
|
||||
class ValidationUserData(object):
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
|
||||
def __unicode__(self):
|
||||
context_map = {
|
||||
'FC': 'par FranceConnect',
|
||||
'office': 'au guichet',
|
||||
'online': 'en ligne',
|
||||
}
|
||||
validation_context = self.user.attributes.validation_context
|
||||
validation_date = self.user.attributes.validation_date
|
||||
return u'Compte validé {0} le {1}'.format(
|
||||
context_map.get(validation_context, validation_context),
|
||||
validation_date.strftime('%d/%m/%Y'),
|
||||
)
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_rbac.utils import get_ou_model, get_role_model, get_operation, get_permission_model
|
||||
from django_rbac.models import CHANGE_OP, SEARCH_OP, ADD_OP, VIEW_OP, DELETE_OP, ADMIN_OP
|
||||
from authentic2.a2_rbac.models import CHANGE_PASSWORD_OP, RESET_PASSWORD_OP, ACTIVATE_OP
|
||||
from django_rbac.models import CHANGE_OP, SEARCH_OP, ADD_OP, VIEW_OP, DELETE_OP, ADMIN_OP, Operation
|
||||
from authentic2.a2_rbac.models import RESET_PASSWORD_OP, ACTIVATE_OP
|
||||
|
||||
OU = get_ou_model()
|
||||
Role = get_role_model()
|
||||
Permission = get_permission_model()
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
CUT_VALIDATE_OP = Operation(name='Valider', slug='cut_validate')
|
||||
|
||||
ROLE_TEMPLATES = [
|
||||
{
|
||||
'name': u'Administrateur CUT - création',
|
||||
|
@ -64,7 +67,7 @@ ROLE_TEMPLATES = [
|
|||
{
|
||||
'name': u'Administrateur CUT - validation',
|
||||
'slug': '_a2-cut-validate',
|
||||
'operations': [],
|
||||
'operations': [CUT_VALIDATE_OP],
|
||||
'target': 'user_ct',
|
||||
'scope': 'ou_usagers',
|
||||
},
|
||||
|
@ -120,7 +123,10 @@ ROLE_TEMPLATES = [
|
|||
'role_parents': [
|
||||
'_a2-cut-admin-users',
|
||||
'_a2-cut-admin-roles'
|
||||
]
|
||||
],
|
||||
'operations': [ADMIN_OP],
|
||||
'target': 'ou_ct',
|
||||
'scope': 'no_scope',
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -153,10 +159,13 @@ def update_roles():
|
|||
ct_ct = ContentType.objects.get_for_model(ContentType)
|
||||
user_ct = ContentType.objects.get_for_model(User)
|
||||
role_ct = ContentType.objects.get_for_model(Role)
|
||||
ou_ct = ContentType.objects.get_for_model(OU)
|
||||
|
||||
roles = {}
|
||||
|
||||
def handle_ou(ou, ou_usagers, ou_territoire, user_ct, role_ct, **kwargs):
|
||||
def handle_ou(ou, ou_usagers, ou_territoire, user_ct, role_ct, ou_ct, **kwargs):
|
||||
ou_ct = ContentType.objects.get_for_model(OU)
|
||||
no_scope = None
|
||||
if ou.slug == 'usagers':
|
||||
return
|
||||
for tpl in ROLE_TEMPLATES:
|
||||
|
@ -194,6 +203,13 @@ def update_roles():
|
|||
if 'role_parents' in tpl:
|
||||
for role_parent in tpl['role_parents']:
|
||||
role.add_parent(roles[(ou, role_parent)])
|
||||
if tpl['name'] == 'Administrateur':
|
||||
op = get_operation(ADMIN_OP)
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
operation=op,
|
||||
target_ct=ct_ct,
|
||||
target_id=ou_ct.pk)
|
||||
role.permissions.add(permission)
|
||||
slugs = [tpl['slug'] for tpl in ROLE_TEMPLATES]
|
||||
Role.objects.filter(slug__startswith='_a2-cut').exclude(slug__in=slugs).delete()
|
||||
handle_ou(ou_territoire, **vars())
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# authentic2_cut - Authentic2 plugin for CUT
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.utils.timezone import now
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from authentic2.views import EditProfile
|
||||
from authentic2.manager.views import SimpleSubTableView
|
||||
from authentic2.manager.user_views import UserEditView
|
||||
|
||||
from .custom_settings import CORE_ATTRIBUTES
|
||||
from . import tables, models
|
||||
|
||||
|
||||
class EditCoreView(EditProfile):
|
||||
template_names = ['authentic2/cut-edit-core.html']
|
||||
fields = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'title',
|
||||
'birthdate',
|
||||
'birthplace',
|
||||
'birthcountry',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_fields(cls):
|
||||
fields, labels = super(EditCoreView, cls).get_fields()
|
||||
return [field for field in fields if field in cls.fields], labels
|
||||
|
||||
edit_core = EditCoreView.as_view()
|
||||
|
||||
|
||||
class EditCrownView(EditProfile):
|
||||
template_names = ['authentic2/cut-edit-crown.html']
|
||||
fields = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'title',
|
||||
'birthdate',
|
||||
'birthplace',
|
||||
'birthcountry',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_fields(cls):
|
||||
fields, labels = super(EditCrownView, cls).get_fields()
|
||||
return [field for field in fields if field not in cls.fields], labels
|
||||
|
||||
edit_crown = EditCrownView.as_view()
|
||||
|
||||
|
||||
class UserEditCoreView(UserEditView):
|
||||
template_name = 'authentic2/cut_manager_user_edit_core.html'
|
||||
permissions = ['custom_user.cut_validate_user']
|
||||
|
||||
def get_title(self):
|
||||
if self.object.attributes.validated:
|
||||
return u'Modifier les attributs cœurs'
|
||||
return u'Valider les attributs cœurs'
|
||||
|
||||
def get_fields(self):
|
||||
fields = super(UserEditCoreView, self).get_fields()
|
||||
return [field for field in CORE_ATTRIBUTES if field in fields]
|
||||
|
||||
def get_form(self, *args, **kwargs):
|
||||
form = super(UserEditCoreView, self).get_form(*args, **kwargs)
|
||||
for field in form.fields.values():
|
||||
field.required = True
|
||||
if 'birthdate' in form.fields:
|
||||
form.fields['birthdate'].widget.options['endDate'] = '+0d'
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
response = super(UserEditCoreView, self).form_valid(form)
|
||||
if not form.instance.attributes.validated:
|
||||
models.Journal.objects.create(
|
||||
author=self.request.user,
|
||||
subject=self.object,
|
||||
message='validation du compte')
|
||||
form.instance.attributes.validated = True
|
||||
form.instance.attributes.validation_context = 'office'
|
||||
form.instance.attributes.validation_date = now().date()
|
||||
messages.info(self.request, u'Le compte a été validé.')
|
||||
else:
|
||||
models.Journal.objects.create(
|
||||
author=self.request.user,
|
||||
subject=self.object,
|
||||
message='modification des données cœur')
|
||||
messages.info(self.request, u'Les données cœur ont été modifié.')
|
||||
return response
|
||||
|
||||
manager_user_edit_core = UserEditCoreView.as_view()
|
||||
|
||||
|
||||
class UserActionsJournal(SimpleSubTableView):
|
||||
model = get_user_model()
|
||||
table_class = tables.UserActionsTable
|
||||
template_name = 'authentic2/cut_manager_user_actions_journal.html'
|
||||
|
||||
def get_table_queryset(self):
|
||||
return self.object.actor_journal.all()
|
||||
|
||||
user_actions_journal = UserActionsJournal.as_view()
|
||||
|
||||
|
||||
class UserModificationsJournal(SimpleSubTableView):
|
||||
model = get_user_model()
|
||||
table_class = tables.UserModificationsTable
|
||||
template_name = 'authentic2/cut_manager_user_modifications_journal.html'
|
||||
|
||||
def get_table_queryset(self):
|
||||
return self.object.subject_journal.all()
|
||||
|
||||
user_modifications_journal = UserModificationsJournal.as_view()
|
Loading…
Reference in New Issue