From a14d940db2914a0ee5302a2bb0737e3a8dc6a8a5 Mon Sep 17 00:00:00 2001 From: Skia Date: Fri, 5 Feb 2016 16:59:42 +0100 Subject: [PATCH] Some refactoring and misc improvements --- README.md | 28 +++++++++++++-- club/migrations/0002_auto_20160202_1345.py | 4 +-- club/models.py | 37 +++++++++++++++++-- club/templates/club/club_detail.jinja | 11 +++--- club/urls.py | 2 +- club/views.py | 20 ++++++++--- core/fixtures/pages.json | 2 +- core/management/commands/setup.py | 36 +++++++++++++------ core/migrations/0001_initial.py | 8 ++--- core/models.py | 32 ++++++++++------- core/views/__init__.py | 42 ++++++++++++++++------ core/views/forms.py | 24 ++++++------- core/views/page.py | 2 +- sith/settings.py | 8 +++-- subscription/models.py | 6 +++- subscription/views.py | 11 ++++++ 16 files changed, 199 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index a635bc72..856bfe08 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,33 @@ There is a Doxyfile at the root of the project, meaning that if you have Doxygen generate a complete HTML documentation that will be available in the *./doc/html/* folder. ### Dependencies: - * Django 1.8 - * Pillow +See requirements.txt The development is done with sqlite, but it is advised to set a more robust DBMS for production (Postgresql for example) +### Misc about development + +#### Controlling the rights + +When you need to protect an object, there are three levels: + * Editing the object properties + * Editing the object various values + * Viewing the object + +Now you have many solutions in your model: + * You can define a `is_owned_by(self, user)`, a `can_be_edited_by(self, user)`, and/or a `can_be_viewed_by(self, user)` + method, each returning True is the user passed can edit/view the object, False otherwise. + This allows you to make complex request when the group solution is not powerful enough. + It's useful too when you want to define class-wide permissions, e.g. the club members, that are viewable only for + Subscribers. + * You can add an `owner_group` field, as a ForeignKey to Group. Second is an `edit_groups` field, as a ManyToMany to + Group, and third is a `view_groups`, same as for edit. + +Finally, when building a class based view, which is highly advised, you just have to inherit it from CanEditPropMixin, +CanEditMixin, or CanViewMixin, which are located in core.views. Your view will then be protected using either the +appropriate group fields, or the right method to check user permissions. + + + + diff --git a/club/migrations/0002_auto_20160202_1345.py b/club/migrations/0002_auto_20160202_1345.py index 0d88c844..78170bdc 100644 --- a/club/migrations/0002_auto_20160202_1345.py +++ b/club/migrations/0002_auto_20160202_1345.py @@ -14,12 +14,12 @@ class Migration(migrations.Migration): operations = [ migrations.AddField( model_name='club', - name='edit_group', + name='edit_groups', field=models.ManyToManyField(to='core.Group', blank=True, related_name='editable_club'), ), migrations.AddField( model_name='club', - name='view_group', + name='view_groups', field=models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_club'), ), ] diff --git a/club/models.py b/club/models.py index 83db8425..839d9094 100644 --- a/club/models.py +++ b/club/models.py @@ -6,6 +6,7 @@ from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from core.models import User, Group +from subscription.models import Subscriber # Create your models here. @@ -31,8 +32,8 @@ class Club(models.Model): # email = models.EmailField(_('email address'), unique=True) # This should, and will be generated automatically owner_group = models.ForeignKey(Group, related_name="owned_club", default=settings.AE_GROUPS['root']['id']) - edit_group = models.ManyToManyField(Group, related_name="editable_club", blank=True) - view_group = models.ManyToManyField(Group, related_name="viewable_club", blank=True) + edit_groups = models.ManyToManyField(Group, related_name="editable_club", blank=True) + view_groups = models.ManyToManyField(Group, related_name="viewable_club", blank=True) def check_loop(self): """Raise a validation error when a loop is found within the parent list""" @@ -53,6 +54,38 @@ class Club(models.Model): def get_absolute_url(self): return reverse('club:club_view', kwargs={'club_id': self.id}) + def is_owned_by(self, user): + """ + Method to see if that object can be super edited by the given user + """ + if user.groups.filter(name=settings.AE_GROUPS['board']['name']).exists(): + return True + return False + + def can_be_edited_by(self, user): + """ + Method to see if that object can be edited by the given user + """ + ms = self.get_membership_for(user) + if ms is not None and ms.role >= 7: + return True + return False + + def can_be_viewed_by(self, user): + """ + Method to see if that object can be seen by the given user + """ + sub = Subscriber.objects.filter(pk=user.pk).first() + if sub is None: + return False + return sub.is_subscribed() + + def get_membership_for(self, user): + """ + Returns the current membership the given user + """ + return self.members.filter(user=user.id).filter(end_date=None).first() + class Membership(models.Model): """ The Membership class makes the connection between User and Clubs diff --git a/club/templates/club/club_detail.jinja b/club/templates/club/club_detail.jinja index 68d78dde..fc3b8927 100644 --- a/club/templates/club/club_detail.jinja +++ b/club/templates/club/club_detail.jinja @@ -3,17 +3,16 @@ {% block content %}

Club

Back to list

- {% if user.can_edit(club) %} + {% if can_edit(club, user) %}

Edit

-

Edit members

{% endif %} - {% if user.is_owner(club) or user.membership.filter(end_date=None).filter(club=club.id).first() is not none %} + {% if can_edit_prop(club, user) %}

Prop - TODO FIXME: this code sucks and is just a test! - We need something really easy to manage the views rights regarding the subscribing status and the membership of - someone!

{% endif %} + {% if can_view(club, user) %} +

Members

+ {% endif %}

{{ club.name }}

{{ club.address }}