Move auth-related from 'kfet' app to 'kfet.auth'.

This commit is contained in:
Aurélien Delobelle 2017-09-13 01:57:31 +02:00
parent 7d16001ee5
commit bf61e41b50
19 changed files with 213 additions and 134 deletions

View file

@ -90,6 +90,7 @@ INSTALLED_APPS = [
'wagtailmenus', 'wagtailmenus',
'modelcluster', 'modelcluster',
'taggit', 'taggit',
'kfet.auth',
'kfet.cms', 'kfet.cms',
] ]
@ -99,7 +100,7 @@ MIDDLEWARE_CLASSES = [
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'kfet.middleware.KFetAuthenticationMiddleware', 'kfet.auth.middleware.KFetAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
@ -127,7 +128,7 @@ TEMPLATES = [
'wagtailmenus.context_processors.wagtailmenus', 'wagtailmenus.context_processors.wagtailmenus',
'djconfig.context_processors.config', 'djconfig.context_processors.config',
'gestioncof.shared.context_processor', 'gestioncof.shared.context_processor',
'kfet.context_processors.auth', 'kfet.auth.context_processors.auth',
'kfet.context_processors.config', 'kfet.context_processors.config',
], ],
}, },
@ -190,7 +191,7 @@ CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', 'django.contrib.auth.backends.ModelBackend',
'gestioncof.shared.COFCASBackend', 'gestioncof.shared.COFCASBackend',
'kfet.backends.GenericTeamBackend', 'kfet.auth.backends.GenericTeamBackend',
) )
RECAPTCHA_USE_SSL = True RECAPTCHA_USE_SSL = True

1
kfet/auth/__init__.py Normal file
View file

@ -0,0 +1 @@
default_app_config = 'kfet.auth.apps.KFetAuthConfig'

8
kfet/auth/apps.py Normal file
View file

@ -0,0 +1,8 @@
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
class KFetAuthConfig(AppConfig):
name = 'kfet.auth'
label = 'kfetauth'
verbose_name = _("K-Fêt - Authentification et Autorisation")

View file

@ -0,0 +1,10 @@
from django.contrib.auth.context_processors import PermWrapper
def auth(request):
if hasattr(request, 'real_user'):
return {
'user': request.real_user,
'perms': PermWrapper(request.real_user),
}
return {}

20
kfet/auth/fields.py Normal file
View file

@ -0,0 +1,20 @@
from django import forms
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.forms import widgets
class KFetPermissionsField(forms.ModelMultipleChoiceField):
def __init__(self, *args, **kwargs):
queryset = Permission.objects.filter(
content_type__in=ContentType.objects.filter(app_label="kfet"),
)
super().__init__(
queryset=queryset,
widget=widgets.CheckboxSelectMultiple,
*args, **kwargs
)
def label_from_instance(self, obj):
return obj.name

44
kfet/auth/forms.py Normal file
View file

@ -0,0 +1,44 @@
from django import forms
from django.contrib.auth.models import Group, User
from .fields import KFetPermissionsField
class GroupForm(forms.ModelForm):
permissions = KFetPermissionsField()
def clean_name(self):
name = self.cleaned_data['name']
return 'K-Fêt %s' % name
def clean_permissions(self):
kfet_perms = self.cleaned_data['permissions']
# TODO: With Django >=1.11, the QuerySet method 'difference' can be
# used.
# other_groups = self.instance.permissions.difference(
# self.fields['permissions'].queryset
# )
other_perms = self.instance.permissions.exclude(
pk__in=[p.pk for p in self.fields['permissions'].queryset],
)
return list(kfet_perms) + list(other_perms)
class Meta:
model = Group
fields = ['name', 'permissions']
class UserGroupForm(forms.ModelForm):
groups = forms.ModelMultipleChoiceField(
Group.objects.filter(name__icontains='K-Fêt'),
label='Statut équipe',
required=False)
def clean_groups(self):
kfet_groups = self.cleaned_data.get('groups')
other_groups = self.instance.groups.exclude(name__icontains='K-Fêt')
return list(kfet_groups) + list(other_groups)
class Meta:
model = User
fields = ['groups']

View file

@ -2,7 +2,7 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from kfet.backends import KFetBackend from .backends import KFetBackend
class KFetAuthenticationMiddleware(object): class KFetAuthenticationMiddleware(object):

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('auth', '0006_require_contenttypes_0002'),
]
operations = [
migrations.CreateModel(
name='GenericTeamToken',
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)),
('token', models.CharField(unique=True, max_length=50)),
],
),
]

View file

5
kfet/auth/models.py Normal file
View file

@ -0,0 +1,5 @@
from django.db import models
class GenericTeamToken(models.Model):
token = models.CharField(max_length=50, unique=True)

69
kfet/auth/views.py Normal file
View file

@ -0,0 +1,69 @@
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import Group, User
from django.core.urlresolvers import reverse_lazy
from django.db.models import Prefetch
from django.shortcuts import render
from django.utils.crypto import get_random_string
from django.views.generic.edit import CreateView, UpdateView
from django_cas_ng.views import logout as cas_logout_view
from kfet.decorators import teamkfet_required
from .forms import GroupForm
from .models import GenericTeamToken
@teamkfet_required
def login_genericteam(request):
# Check si besoin de déconnecter l'utilisateur de CAS
cas_logout = None
if request.user.profile.login_clipper:
# Récupèration de la vue de déconnexion de CAS
# Ici, car request sera modifié après
next_page = request.META.get('HTTP_REFERER', None)
cas_logout = cas_logout_view(request, next_page=next_page)
# Authentification du compte générique
token = GenericTeamToken.objects.create(token=get_random_string(50))
user = authenticate(username="kfet_genericteam", token=token.token)
login(request, user)
messages.success(request, "Connecté en utilisateur partagé")
return cas_logout or render(request, "kfet/login_genericteam.html")
@permission_required('kfet.manage_perms')
def account_group(request):
user_pre = Prefetch(
'user_set',
queryset=User.objects.select_related('profile__account_kfet'),
)
groups = (
Group.objects
.filter(name__icontains='K-Fêt')
.prefetch_related('permissions', user_pre)
)
return render(request, 'kfet/account_group.html', {
'groups': groups,
})
class AccountGroupCreate(SuccessMessageMixin, CreateView):
model = Group
template_name = 'kfet/account_group_form.html'
form_class = GroupForm
success_message = 'Nouveau groupe : %(name)s'
success_url = reverse_lazy('kfet.account.group')
class AccountGroupUpdate(SuccessMessageMixin, UpdateView):
queryset = Group.objects.filter(name__icontains='K-Fêt')
template_name = 'kfet/account_group_form.html'
form_class = GroupForm
success_message = 'Groupe modifié : %(name)s'
success_url = reverse_lazy('kfet.account.group')

View file

@ -1,18 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib.auth.context_processors import PermWrapper
from kfet.config import kfet_config from kfet.config import kfet_config
def auth(request):
if hasattr(request, 'real_user'):
return {
'user': request.real_user,
'perms': PermWrapper(request.real_user),
}
return {}
def config(request): def config(request):
return {'kfet_config': kfet_config} return {'kfet_config': kfet_config}

View file

@ -5,9 +5,8 @@ from decimal import Decimal
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.contrib.auth.models import User, Group, Permission from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.forms import modelformset_factory
from django.forms import modelformset_factory, widgets
from django.utils import timezone from django.utils import timezone
from djconfig.forms import ConfigForm from djconfig.forms import ConfigForm
@ -18,6 +17,8 @@ from kfet.models import (
TransferGroup, Supplier) TransferGroup, Supplier)
from gestioncof.models import CofProfile from gestioncof.models import CofProfile
from .auth.forms import UserGroupForm # noqa
# ----- # -----
# Widgets # Widgets
@ -128,60 +129,6 @@ class UserRestrictTeamForm(UserForm):
fields = ['first_name', 'last_name', 'email'] fields = ['first_name', 'last_name', 'email']
class UserGroupForm(forms.ModelForm):
groups = forms.ModelMultipleChoiceField(
Group.objects.filter(name__icontains='K-Fêt'),
label='Statut équipe',
required=False)
def clean_groups(self):
kfet_groups = self.cleaned_data.get('groups')
other_groups = self.instance.groups.exclude(name__icontains='K-Fêt')
return list(kfet_groups) + list(other_groups)
class Meta:
model = User
fields = ['groups']
class KFetPermissionsField(forms.ModelMultipleChoiceField):
def __init__(self, *args, **kwargs):
queryset = Permission.objects.filter(
content_type__in=ContentType.objects.filter(app_label="kfet"),
)
super().__init__(
queryset=queryset,
widget=widgets.CheckboxSelectMultiple,
*args, **kwargs
)
def label_from_instance(self, obj):
return obj.name
class GroupForm(forms.ModelForm):
permissions = KFetPermissionsField()
def clean_name(self):
name = self.cleaned_data['name']
return 'K-Fêt %s' % name
def clean_permissions(self):
kfet_perms = self.cleaned_data['permissions']
# TODO: With Django >=1.11, the QuerySet method 'difference' can be used.
# other_groups = self.instance.permissions.difference(
# self.fields['permissions'].queryset
# )
other_perms = self.instance.permissions.exclude(
pk__in=[p.pk for p in self.fields['permissions'].queryset],
)
return list(kfet_perms) + list(other_perms)
class Meta:
model = Group
fields = ['name', 'permissions']
class AccountNegativeForm(forms.ModelForm): class AccountNegativeForm(forms.ModelForm):
class Meta: class Meta:

View file

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('kfet', '0057_merge'),
]
operations = [
migrations.DeleteModel(
name='GenericTeamToken',
),
]

View file

@ -14,6 +14,8 @@ from datetime import date
import re import re
import hashlib import hashlib
from .auth.models import GenericTeamToken # noqa
from .config import kfet_config from .config import kfet_config
from .utils import to_ukf from .utils import to_ukf
@ -710,7 +712,3 @@ class Operation(models.Model):
return templates[self.type].format(nb=self.article_nb, return templates[self.type].format(nb=self.article_nb,
article=self.article, article=self.article,
amount=self.amount) amount=self.amount)
class GenericTeamToken(models.Model):
token = models.CharField(max_length = 50, unique = True)

View file

@ -12,34 +12,30 @@ from django.views.generic.edit import CreateView, UpdateView
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib import messages from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth import authenticate, login from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.models import User, Permission
from django.contrib.auth.models import User, Permission, Group
from django.http import JsonResponse, Http404 from django.http import JsonResponse, Http404
from django.forms import formset_factory from django.forms import formset_factory
from django.db import transaction from django.db import transaction
from django.db.models import F, Sum, Prefetch, Count from django.db.models import F, Sum, Prefetch, Count
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce
from django.utils import timezone from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django_cas_ng.views import logout as cas_logout_view
from gestioncof.models import CofProfile from gestioncof.models import CofProfile
from kfet.config import kfet_config from kfet.config import kfet_config
from kfet.decorators import teamkfet_required from kfet.decorators import teamkfet_required
from kfet.models import ( from kfet.models import (
Account, Checkout, Article, AccountNegative, Account, Checkout, Article, AccountNegative,
CheckoutStatement, GenericTeamToken, Supplier, SupplierArticle, Inventory, CheckoutStatement, Supplier, SupplierArticle, Inventory,
InventoryArticle, Order, OrderArticle, Operation, OperationGroup, InventoryArticle, Order, OrderArticle, Operation, OperationGroup,
TransferGroup, Transfer, ArticleCategory) TransferGroup, Transfer, ArticleCategory)
from kfet.forms import ( from kfet.forms import (
AccountTriForm, AccountBalanceForm, AccountNoTriForm, UserForm, CofForm, AccountTriForm, AccountBalanceForm, AccountNoTriForm, UserForm, CofForm,
UserRestrictTeamForm, UserGroupForm, AccountForm, CofRestrictForm, UserRestrictTeamForm, UserGroupForm, AccountForm, CofRestrictForm,
AccountPwdForm, AccountNegativeForm, UserRestrictForm, AccountRestrictForm, AccountPwdForm, AccountNegativeForm, UserRestrictForm, AccountRestrictForm,
GroupForm, CheckoutForm, CheckoutRestrictForm, CheckoutStatementCreateForm, CheckoutForm, CheckoutRestrictForm, CheckoutStatementCreateForm,
CheckoutStatementUpdateForm, ArticleForm, ArticleRestrictForm, CheckoutStatementUpdateForm, ArticleForm, ArticleRestrictForm,
KPsulOperationGroupForm, KPsulAccountForm, KPsulCheckoutForm, KPsulOperationGroupForm, KPsulAccountForm, KPsulCheckoutForm,
KPsulOperationFormSet, AddcostForm, FilterHistoryForm, KPsulOperationFormSet, AddcostForm, FilterHistoryForm,
@ -54,25 +50,9 @@ import heapq
import statistics import statistics
from kfet.statistic import ScaleMixin, last_stats_manifest, tot_ventes, WeekScale from kfet.statistic import ScaleMixin, last_stats_manifest, tot_ventes, WeekScale
from .auth.views import ( # noqa
@teamkfet_required account_group, login_genericteam, AccountGroupCreate, AccountGroupUpdate,
def login_genericteam(request): )
# Check si besoin de déconnecter l'utilisateur de CAS
cas_logout = None
if request.user.profile.login_clipper:
# Récupèration de la vue de déconnexion de CAS
# Ici, car request sera modifié après
next_page = request.META.get('HTTP_REFERER', None)
cas_logout = cas_logout_view(request, next_page=next_page)
# Authentification du compte générique
token = GenericTeamToken.objects.create(token=get_random_string(50))
user = authenticate(username="kfet_genericteam", token=token.token)
login(request, user)
messages.success(request, "Connecté en utilisateur partagé")
return cas_logout or render(request, "kfet/login_genericteam.html")
def put_cleaned_data_in_dict(dict, form): def put_cleaned_data_in_dict(dict, form):
@ -505,37 +485,6 @@ def account_update(request, trigramme):
}) })
@permission_required('kfet.manage_perms')
def account_group(request):
user_pre = Prefetch(
'user_set',
queryset=User.objects.select_related('profile__account_kfet'),
)
groups = (
Group.objects
.filter(name__icontains='K-Fêt')
.prefetch_related('permissions', user_pre)
)
return render(request, 'kfet/account_group.html', {
'groups': groups,
})
class AccountGroupCreate(SuccessMessageMixin, CreateView):
model = Group
template_name = 'kfet/account_group_form.html'
form_class = GroupForm
success_message = 'Nouveau groupe : %(name)s'
success_url = reverse_lazy('kfet.account.group')
class AccountGroupUpdate(SuccessMessageMixin, UpdateView):
queryset = Group.objects.filter(name__icontains='K-Fêt')
template_name = 'kfet/account_group_form.html'
form_class = GroupForm
success_message = 'Groupe modifié : %(name)s'
success_url = reverse_lazy('kfet.account.group')
class AccountNegativeList(ListView): class AccountNegativeList(ListView):
queryset = ( queryset = (
AccountNegative.objects AccountNegative.objects