diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-09 00:50:54 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-09 00:50:54 +0200 |
commit | 14b6a6c93003b422cb08c5313f64a228e743d2ac (patch) | |
tree | cf8ef814f1cc3c305b6eb3e527518c4230bbd293 | |
parent | 80e20f22b4e79e79a5bb7d65f602f6642522ca3e (diff) | |
download | Chimère-14b6a6c93003b422cb08c5313f64a228e743d2ac.tar.bz2 Chimère-14b6a6c93003b422cb08c5313f64a228e743d2ac.zip |
Admin: fix and improve moderation groups management
-rw-r--r-- | chimere/admin.py | 42 | ||||
-rw-r--r-- | chimere/fixtures/initial_data.json | 44 | ||||
-rw-r--r-- | chimere/forms.py | 3 | ||||
-rw-r--r-- | chimere/models.py | 111 | ||||
-rw-r--r-- | chimere/templates/chimere/detail.html | 17 | ||||
-rw-r--r-- | chimere/views.py | 3 |
6 files changed, 168 insertions, 52 deletions
diff --git a/chimere/admin.py b/chimere/admin.py index 42835a2..7663bd5 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -25,6 +25,7 @@ import datetime from django import forms from django.conf import settings from django.contrib import admin +from django.db.models import Q from django.http import HttpResponse from django.shortcuts import render_to_response from django.utils.translation import ugettext_lazy as _ @@ -38,25 +39,13 @@ from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ NewsAdminForm, CategoryAdminForm, ImporterAdminForm, \ PictureFileAdminForm, MultimediaFileAdminForm from chimere.models import Category, Icon, SubCategory, Marker, \ - PropertyModel, News, Route, Area, ColorTheme, Color, MultimediaType, \ - MultimediaFile, PictureFile, Importer, Layer, AreaLayers + PropertyModel, News, Route, Area, ColorTheme, Color, \ + MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ + get_areas_for_user, get_users_by_area from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\ CSVManager from chimere.widgets import TextareaWidget -def get_areas_for_user(user): - """ - Getting subcats for a specific user - """ - perms = user.get_all_permissions() - areas = set() - prefix = 'chimere.change_area_' - for perm in perms: - if perm.startswith(prefix): - area = Area.objects.get(urn=perm[len(prefix):]) - areas.add(area) - return areas - def validate(modeladmin, request, queryset): for item in queryset: item.status = 'A' @@ -131,13 +120,14 @@ class MarkerAdmin(admin.ModelAdmin): qs = self.model._default_manager.get_query_set() if not request.user.is_superuser: areas = get_areas_for_user(request.user) - if areas: - in_areas = " or ".join([area.getIncludeSql() for area in areas]) - qs = qs.extra(where=[in_areas]) + contained = Q() + for area in areas: + contained = contained | area.getIncludeMarker() + qs = qs.filter(contained) ordering = self.ordering or () if ordering: qs = qs.order_by(*ordering) - return qs + return qs.distinct() class RouteAdmin(admin.ModelAdmin): """ @@ -155,10 +145,10 @@ class RouteAdmin(admin.ModelAdmin): qs = self.model._default_manager.get_query_set() if not request.user.is_superuser: areas = get_areas_for_user(request.user) - if areas: - in_areas = " or ".join([area.getIncludeSql( - geometry='"chimere_route".route') for area in areas]) - qs = qs.extra(where=[in_areas]) + contained = Q() + for area in areas: + contained = contained | area.getIncludeRoute() + qs = qs.filter(contained) ordering = self.ordering or () if ordering: qs = qs.order_by(*ordering) @@ -240,11 +230,6 @@ class ColorThemeAdmin(admin.ModelAdmin): class IconAdmin(admin.ModelAdmin): exclude = ['height', 'width'] -class MultimediaTypeAdmin(admin.ModelAdmin): - search_fields = ("name",) - list_display = ('name', 'media_type', 'mime_type', 'iframe', 'available') - list_filter = ('media_type', 'available') - # register of differents database fields admin.site.register(News, NewsAdmin) admin.site.register(Category, CategoryAdmin) @@ -254,5 +239,4 @@ admin.site.register(Route, RouteAdmin) admin.site.register(PropertyModel) admin.site.register(Area, AreaAdmin) admin.site.register(ColorTheme, ColorThemeAdmin) -admin.site.register(MultimediaType, MultimediaTypeAdmin) admin.site.register(Layer) diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json index 473640c..21ba13c 100644 --- a/chimere/fixtures/initial_data.json +++ b/chimere/fixtures/initial_data.json @@ -195,5 +195,49 @@ "layer_code": "new OpenLayers.Layer.MapQuestOSM()", "name": "OSM - MapQuest" } + }, + { + "pk": 1, + "model": "auth.group", + "fields": { + "name": "Application administrator", + "permissions": [ + 67, + 68, + 40, + 41, + 42, + 37, + 38, + 39, + 34, + 35, + 36, + 43, + 44, + 45, + 49, + 50, + 51, + 55, + 56, + 57, + 28, + 29, + 30, + 58, + 59, + 60, + 64, + 65, + 66, + 61, + 62, + 63, + 46, + 47, + 48 + ] + } } ] diff --git a/chimere/forms.py b/chimere/forms.py index ea08474..bb31ffe 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -433,7 +433,8 @@ class AreaAdminForm(forms.ModelForm): Admin page to create an area """ area = AreaField(label=_("Area"), fields=(PointField(), PointField())) - welcome_message = forms.CharField(widget=TextareaAdminWidget) + welcome_message = forms.CharField(widget=TextareaAdminWidget, + required=False) class Meta: model = Area diff --git a/chimere/models.py b/chimere/models.py index 593d712..88c1f0c 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,16 +25,16 @@ import simplejson as json from lxml import etree from PIL import Image from subprocess import Popen, PIPE - from django import forms from django.conf import settings from django.contrib import admin -from django.contrib.auth.models import Permission, ContentType +from django.contrib.auth.models import User, Permission, ContentType, Group from django.contrib.gis.db import models from django.contrib.gis.gdal import SpatialReference from django.core.files import File from django.core.exceptions import ValidationError, ObjectDoesNotExist from django.core.urlresolvers import reverse +from django.db.models import Q from django.db.models.signals import post_save, pre_save, m2m_changed from django.template import defaultfilters from django.utils.translation import ugettext_lazy as _ @@ -513,6 +513,12 @@ class Marker(GeographicItem): url = reverse('chimere:tiny', args=[area_name, urn]) return url + +PRE_ATTRS = { + 'Marker':('name', 'geometry', 'import_version'), + 'Route':('name', 'geometry', 'import_version'), + 'Area':('urn', 'name'), + } def geometry_pre_save(cls, pre_save_geom_values): def geom_pre_save(sender, **kwargs): if not kwargs['instance'] or not kwargs['instance'].pk: @@ -520,8 +526,8 @@ def geometry_pre_save(cls, pre_save_geom_values): instance = kwargs['instance'] try: instance = cls.objects.get(pk=instance.pk) - pre_save_geom_values[instance.pk] = (instance.name, - instance.geometry, instance.import_version) + pre_save_geom_values[instance.pk] = [getattr(instance, attr) + for attr in PRE_ATTRS[cls.__name__]] except ObjectDoesNotExist: pass return geom_pre_save @@ -836,7 +842,7 @@ class Route(GeographicItem): null=True, height_field='height', width_field='width') height = models.IntegerField(_(u"Height"), blank=True, null=True) width = models.IntegerField(_(u"Width"), blank=True, null=True) - objects = BaseGeoManager() + objects = models.GeoManager() def __unicode__(self): return self.name @@ -1139,20 +1145,34 @@ class Area(models.Model, SimpleArea): ''' return cls.objects.filter(available=True) - def getIncludeSql(self, geometry='"chimere_marker".point'): - """ - Get the sql statement for the test if the point is included in the area - """ - area = "ST_GeometryFromText('POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f"\ - "))', %d)" % (self.upper_left_corner.x, self.upper_left_corner.y, + def getWkt(self): + return "SRID=%d;POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f))" % ( + settings.CHIMERE_EPSG_DISPLAY_PROJECTION, + self.upper_left_corner.x, self.upper_left_corner.y, self.lower_right_corner.x, self.upper_left_corner.y, self.lower_right_corner.x, self.lower_right_corner.y, self.upper_left_corner.x, self.lower_right_corner.y, self.upper_left_corner.x, self.upper_left_corner.y, - settings.CHIMERE_EPSG_DISPLAY_PROJECTION ) - sql = "ST_Contains(" + area + ", " + geometry + ")" - return sql + + def getIncludeMarker(self): + """ + Get the sql statement for the test if the point is included in the area + """ + return Q(point__contained=self.getWkt()) + + def getIncludeRoute(self): + """ + Get the sql statement for the test if the route is included in the area + """ + return Q(route__contained=self.getWkt()) + +pre_save_area_values = {} +def area_pre_save(sender, **kwargs): + if not kwargs['instance']: + return + geometry_pre_save(Area, pre_save_area_values)(sender, **kwargs) +pre_save.connect(area_pre_save, sender=Area) def area_post_save(sender, **kwargs): if not kwargs['instance']: @@ -1163,21 +1183,82 @@ def area_post_save(sender, **kwargs): for default in defaults: default.default = False default.save() + # manage permissions + old_urn, old_name = area.urn, area.name + if area.pk in pre_save_area_values: + old_urn, old_name = pre_save_area_values[area.pk] + perm, old_groups, old_users = None, [], [] + if area.urn != old_urn: + oldmnemo = 'change_area_' + old_urn + old_perm = Permission.objects.filter(codename=oldmnemo) + if old_perm.count(): + perm = old_perm.all()[0] + perm.codename = 'change_area_' + area.urn + perm.save() if not area.urn: area.urn = defaultfilters.slugify(area.name) area.save() mnemo = 'change_area_' + area.urn perm = Permission.objects.filter(codename=mnemo) + lbl = "Can change " + area.name if not perm.count(): - lbl = "Can change " + area.name content_type = ContentType.objects.get(app_label="chimere", model="area") perm = Permission(name=lbl, content_type_id=content_type.id, codename=mnemo) perm.save() + else: + perm = perm.all()[0] + if old_name != area.name: + perm.name = lbl + perm.save() + # manage moderation group + groupname = area.name + " moderation" + if old_name != area.name: + old_groupname = old_name + " moderation" + old_gp = Group.objects.filter(name=old_groupname) + if old_gp.count(): + old_gp = old_gp.all()[0] + old_gp.name = groupname + old_gp.save() + group = Group.objects.filter(name=groupname) + if not group.count(): + group = Group.objects.create(name=groupname) + group.permissions.add(perm) + for app_label, model in (('chimere', 'marker'), + ('chimere', 'route'), + ('chimere', 'multimediafile'), + ('chimere', 'picturefile'), + ('chimere', 'routefile')): + ct = ContentType.objects.get(app_label=app_label, model=model) + for p in Permission.objects.filter(content_type=ct).all(): + group.permissions.add(p) post_save.connect(area_post_save, sender=Area) +def get_areas_for_user(user): + """ + Getting subcats for a specific user + """ + perms = user.get_all_permissions() + areas = set() + prefix = 'chimere.change_area_' + for perm in perms: + if perm.startswith(prefix): + try: + area = Area.objects.get(urn=perm[len(prefix):]) + areas.add(area) + except ObjectDoesNotExist: + pass + return areas + +def get_users_by_area(area): + if not area: + return [] + perm = 'change_area_'+area.urn + return User.objects.filter(Q(groups__permissions__codename=perm)| + Q(user_permissions__codename=perm)).all() + class AreaLayers(models.Model): area = models.ForeignKey(Area) layer = models.ForeignKey(Layer) diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html index 7cf678e..c195fbe 100644 --- a/chimere/templates/chimere/detail.html +++ b/chimere/templates/chimere/detail.html @@ -27,7 +27,17 @@ {% if marker.multimedia_items %} <a href='#' id='show_gallery_link'>{% trans "Show multimedia gallery" %}</a> {% endif %} - </div>{% if share_networks %} + </div> + {% comment %} + <a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'> + {% trans "Submit a modification" %} + </a> + {% endcomment %} + {% if moderator_emails %} + <a href="mailto:?from={{moderator_emails}}&subject={% trans "Propose amendment" %}&body={% trans "I would like to propose an amendment for this item:"%} {{share_url}}"> + {% trans "Propose amendment" %} + </a>{%endif%} + {% if share_networks %} {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %} <a href='{{share_network.1}}'>{{share_network.0}}</a> {% endfor %}{%else%} @@ -35,11 +45,6 @@ <li>{% trans "Share"%}</li>{% for share_network in share_networks %} <li><a href='{{share_network.1}}'><img src="{{share_network.2}}" alt="{{share_network.0}}"/></a></li> {% endfor %}</ul>{% endif %} - {% comment %} - <a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'> - {% trans "Submit a modification" %} - </a> - {% endcomment %} {% endif %} </div> {% if marker.multimedia_items %} diff --git a/chimere/views.py b/chimere/views.py index f96a66b..567840e 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -42,7 +42,8 @@ from django.utils.translation import ugettext as _ from chimere.actions import actions from chimere.models import Category, SubCategory, PropertyModel, \ - Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile + Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile, \ + get_users_by_area from chimere.widgets import getMapJS, PointChooserWidget, \ RouteChooserWidget, AreaWidget |