mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-10-31 00:53:08 +00:00 
			
		
		
		
	Implement generic right checking for any View with the right parents
This commit is contained in:
		
							
								
								
									
										23
									
								
								core/migrations/0008_auto_20151127_1007.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								core/migrations/0008_auto_20151127_1007.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | from __future__ import unicode_literals | ||||||
|  |  | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('core', '0007_auto_20151126_1613'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='page', | ||||||
|  |             name='view_group', | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='page', | ||||||
|  |             name='view_group', | ||||||
|  |             field=models.ManyToManyField(default=1, to='core.Group', related_name='viewable_pages'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										23
									
								
								core/migrations/0009_auto_20151127_1007.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								core/migrations/0009_auto_20151127_1007.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | from __future__ import unicode_literals | ||||||
|  |  | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('core', '0008_auto_20151127_1007'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='page', | ||||||
|  |             name='edit_group', | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='page', | ||||||
|  |             name='edit_group', | ||||||
|  |             field=models.ManyToManyField(to='core.Group', related_name='editable_pages', default=1), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -154,9 +154,11 @@ class Page(models.Model): | |||||||
|     # playing with a Page object, use get_full_name() instead! |     # playing with a Page object, use get_full_name() instead! | ||||||
|     full_name = models.CharField(_('page name'), max_length=255, blank=True) |     full_name = models.CharField(_('page name'), max_length=255, blank=True) | ||||||
|  |  | ||||||
|  | # TODO: Rightable abstract class from which every object with right needed will be able to be child of | ||||||
|  | # Put thoses 3 attributes there | ||||||
|     owner_group = models.ForeignKey(Group, related_name="owned_pages", default=1) |     owner_group = models.ForeignKey(Group, related_name="owned_pages", default=1) | ||||||
|     edit_group = models.ForeignKey(Group, related_name="editable_pages", default=1) |     edit_group = models.ManyToManyField(Group, related_name="editable_pages", default=1) | ||||||
|     view_group = models.ForeignKey(Group, related_name="viewable_pages", default=1) |     view_group = models.ManyToManyField(Group, related_name="viewable_pages", default=1) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         unique_together = ('name', 'parent') |         unique_together = ('name', 'parent') | ||||||
|   | |||||||
| @@ -1,4 +1,65 @@ | |||||||
|  |  | ||||||
|  | from django.http import HttpResponseForbidden | ||||||
|  | from django.core.exceptions import PermissionDenied | ||||||
|  | from django.views.generic.base import View | ||||||
|  |  | ||||||
|  | # TODO: see models.py's TODO! | ||||||
|  | class CanEditPropMixin(View): | ||||||
|  |     """ | ||||||
|  |     This view is made to protect any child view that would be showing some properties of an object that are restricted | ||||||
|  |     to only the owner group of the given object. | ||||||
|  |     In other word, you can make a view with this view as parent, and it would be retricted to the users that are in the | ||||||
|  |     object's owner_group | ||||||
|  |     """ | ||||||
|  |     def dispatch(self, request, *arg, **kwargs): | ||||||
|  |         res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) | ||||||
|  |         obj = self.object | ||||||
|  |         user = self.request.user | ||||||
|  |         if obj is None: | ||||||
|  |             return res | ||||||
|  |         if user.is_superuser or user.groups.filter(name=obj.owner_group.name).exists(): | ||||||
|  |             return res | ||||||
|  |         return HttpResponseForbidden("403, Forbidden") | ||||||
|  |  | ||||||
|  | class CanEditMixin(CanEditPropMixin): | ||||||
|  |     """ | ||||||
|  |     This view makes exactly the same this as its direct parent, but checks the group on the edit_group field of the | ||||||
|  |     object | ||||||
|  |     """ | ||||||
|  |     def dispatch(self, request, *arg, **kwargs): | ||||||
|  |         res = super(CanEditMixin, self).dispatch(request, *arg, **kwargs) | ||||||
|  |         if res.status_code != 403: | ||||||
|  |             return res | ||||||
|  |         obj = self.object | ||||||
|  |         user = self.request.user | ||||||
|  |         if obj is None: | ||||||
|  |             return res | ||||||
|  |         for g in obj.edit_group.all(): | ||||||
|  |             if user.groups.filter(name=g.name).exists(): | ||||||
|  |                 return super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) | ||||||
|  |         return HttpResponseForbidden("403, Forbidden") | ||||||
|  |  | ||||||
|  | class CanViewMixin(CanEditMixin): | ||||||
|  |     """ | ||||||
|  |     This view still makes exactly the same this as its direct parent, but checks the group on the view_group field of | ||||||
|  |     the object | ||||||
|  |     """ | ||||||
|  |     def dispatch(self, request, *arg, **kwargs): | ||||||
|  |         res = super(CanViewMixin, self).dispatch(request, *arg, **kwargs) | ||||||
|  |         if res.status_code != 403: | ||||||
|  |             return res | ||||||
|  |         obj = self.object | ||||||
|  |         user = self.request.user | ||||||
|  |         if obj is None: | ||||||
|  |             return res | ||||||
|  |         for g in obj.view_group.all(): | ||||||
|  |             if user.groups.filter(name=g.name).exists(): | ||||||
|  |                 return super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) | ||||||
|  |         raise PermissionDenied | ||||||
|  |         return HttpResponseForbidden("403, Forbidden") | ||||||
|  |  | ||||||
| from .user import * | from .user import * | ||||||
| from .page import * | from .page import * | ||||||
| from .site import * | from .site import * | ||||||
| from .group import * | from .group import * | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,6 +33,17 @@ class UserGroupsForm(forms.ModelForm): | |||||||
|             'user_permissions': CheckboxSelectMultiple, |             'user_permissions': CheckboxSelectMultiple, | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | class PagePropForm(forms.ModelForm): | ||||||
|  |     error_css_class = 'error' | ||||||
|  |     required_css_class = 'required' | ||||||
|  |     class Meta: | ||||||
|  |         model = Page | ||||||
|  |         fields = ['parent', 'name', 'owner_group', 'edit_group', 'view_group', ] | ||||||
|  |         widgets = { | ||||||
|  |             'edit_group': CheckboxSelectMultiple, | ||||||
|  |             'view_group': CheckboxSelectMultiple, | ||||||
|  |         } | ||||||
|  |  | ||||||
| class GroupEditForm(forms.ModelForm): | class GroupEditForm(forms.ModelForm): | ||||||
|     error_css_class = 'error' |     error_css_class = 'error' | ||||||
|     required_css_class = 'required' |     required_css_class = 'required' | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ from django.contrib.auth.decorators import login_required, permission_required | |||||||
| from django.utils.decorators import method_decorator | from django.utils.decorators import method_decorator | ||||||
|  |  | ||||||
| from core.models import Page | from core.models import Page | ||||||
|  | from core.views.forms import PagePropForm | ||||||
|  | from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin | ||||||
|  |  | ||||||
| class PageListView(ListView): | class PageListView(ListView): | ||||||
|     model = Page |     model = Page | ||||||
| @@ -14,12 +16,23 @@ class PageListView(ListView): | |||||||
|         context = super(PageListView, self).get_context_data(**kwargs) |         context = super(PageListView, self).get_context_data(**kwargs) | ||||||
|         return context |         return context | ||||||
|  |  | ||||||
| class PageView(DetailView): | # Define some right management callable for user_passes_test | ||||||
|     model = Page | def user_can_view(as_view): | ||||||
|  |     def guy(*arg, **kwargs): | ||||||
|  |         res = self.as_view(*arg, **kwargs) | ||||||
|  |  | ||||||
|     @method_decorator(permission_required('core.can_view')) |         user = self.request.user | ||||||
|     def dispatch(self, *args, **kwargs): |         obj = self.page | ||||||
|         return super(PageView, self).dispatch(*args, **kwargs) |         for g in obj.view_group.all(): | ||||||
|  |             if g in user.groups.all(): | ||||||
|  |                 print("Allowed") | ||||||
|  |                 return res | ||||||
|  |         print("Not allowed") | ||||||
|  |         return res | ||||||
|  |     return guy | ||||||
|  |  | ||||||
|  | class PageView(CanViewMixin, DetailView): | ||||||
|  |     model = Page | ||||||
|  |  | ||||||
|     def get_object(self): |     def get_object(self): | ||||||
|         self.page = Page.get_page_by_full_name(self.kwargs['page_name']) |         self.page = Page.get_page_by_full_name(self.kwargs['page_name']) | ||||||
| @@ -34,14 +47,11 @@ class PageView(DetailView): | |||||||
|             context['new_page'] = self.kwargs['page_name'] |             context['new_page'] = self.kwargs['page_name'] | ||||||
|         return context |         return context | ||||||
|  |  | ||||||
| class PagePropView(UpdateView): | class PagePropView(CanEditPropMixin, UpdateView): | ||||||
|     model = Page |     model = Page | ||||||
|     fields = ['parent', 'name', 'owner_group', 'edit_group', 'view_group', ] |     form_class = PagePropForm | ||||||
|     template_name_suffix = '_prop' |     template_name_suffix = '_prop' | ||||||
|  |  | ||||||
|     def __init__(self, *args, **kwargs): |  | ||||||
|         super(PagePropView, self).__init__(*args, **kwargs) |  | ||||||
|  |  | ||||||
|     def get_object(self): |     def get_object(self): | ||||||
|         page_name = self.kwargs['page_name'] |         page_name = self.kwargs['page_name'] | ||||||
|         p = Page.get_page_by_full_name(page_name) |         p = Page.get_page_by_full_name(page_name) | ||||||
| @@ -66,7 +76,7 @@ class PagePropView(UpdateView): | |||||||
|             context['new_page'] = self.kwargs['page_name'] |             context['new_page'] = self.kwargs['page_name'] | ||||||
|         return context |         return context | ||||||
|  |  | ||||||
| class PageEditView(UpdateView): | class PageEditView(CanEditMixin, UpdateView): | ||||||
|     model = Page |     model = Page | ||||||
|     fields = ['title', 'content',] |     fields = ['title', 'content',] | ||||||
|     template_name_suffix = '_edit' |     template_name_suffix = '_edit' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user