From d60a62a68a5c3442a6b464cca1c1a218d57d8ecc Mon Sep 17 00:00:00 2001 From: Leif Johansson Date: Thu, 3 Mar 2011 23:28:11 +0100 Subject: new acl UI --- coip/apps/membership/views.py | 4 +++ coip/apps/name/forms.py | 24 ++++++++++--- coip/apps/name/models.py | 1 + coip/apps/name/views.py | 40 +++++++++++++++++----- coip/extensions/templatetags/permdisplay.py | 4 +-- coip/urls.py | 7 ++-- site-media/css/style.css | 3 ++ templates/apps/name/acls.html | 38 +++++++++++++++------ templates/apps/name/addace.html | 51 ++++++++++++++++++++++++++++ templates/apps/name/name.html | 2 +- templates/edit.html | 52 +++++++++++++++-------------- templates/edit_fieldsets.html | 8 ++--- 12 files changed, 178 insertions(+), 56 deletions(-) create mode 100644 templates/apps/name/addace.html diff --git a/coip/apps/membership/views.py b/coip/apps/membership/views.py index fd7036e..7c4c4e1 100644 --- a/coip/apps/membership/views.py +++ b/coip/apps/membership/views.py @@ -36,6 +36,10 @@ def join(request,id,membername=None): if form.is_valid(): m = form.save() return HttpResponseRedirect(name.url()) + else: + return respond_to(request, + {'text/html': 'apps/membership/edit.html'}, + {'form': form,'name': name, 'formtitle': 'Add a member to %s' % name.short}) else: if membername: try: diff --git a/coip/apps/name/forms.py b/coip/apps/name/forms.py index dc36ecd..549456f 100644 --- a/coip/apps/name/forms.py +++ b/coip/apps/name/forms.py @@ -6,7 +6,7 @@ Created on Jun 24, 2010 from django import forms from coip.apps.name.models import Name, Attribute, NameLink from django.forms import fields -from django.forms.widgets import HiddenInput, CheckboxSelectMultiple +from django.forms.widgets import HiddenInput, CheckboxSelectMultiple, TextInput from form_utils.forms import BetterModelForm, BetterForm class NameForm(forms.ModelForm): @@ -71,7 +71,23 @@ class NameLinkForm(forms.ModelForm): class NameLinkDeleteForm(forms.Form): confirm = fields.BooleanField(label="Confirm") -class PermissionForm(forms.Form): +class PermissionForm(BetterForm): dst = fields.IntegerField(widget=HiddenInput) - subject = fields.CharField(min_length=1024) - permissions = fields.MultipleChoiceField(widget=CheckboxSelectMultiple,choices=[('r','read'),('w','write'),('l','list'),('i','insert'),('d','delete')]) + subject = fields.CharField(max_length=1024,label="Group",widget=TextInput(attrs={'size': 40})) + permissions = fields.MultipleChoiceField(widget=CheckboxSelectMultiple, + choices=[('r','read'), + ('w','write'), + ('l','list members and groups'), + ('i','manage members'), + ('d','delete'), + ('a','manage access')]) + class Meta: + fieldsets = [('subject',{'fields': ['dst','subject'], + 'legend': 'Step 1: Select a group', + 'classes': ['step'], + 'description': 'Start typing in the textfield to find the group you want.'}), + ('permission',{'fields': ['permissions'], + 'legend': 'Step 2: Set permissions', + 'classes': ['step','submit_step'], + 'description': 'Select the rights that members of the group should have.'})] + \ No newline at end of file diff --git a/coip/apps/name/models.py b/coip/apps/name/models.py index a1384a3..d8c089e 100644 --- a/coip/apps/name/models.py +++ b/coip/apps/name/models.py @@ -204,6 +204,7 @@ class NameLink(models.Model): access_control = 0 part_of = 1 + child_access_control = 2 def __unicode__(self): return "%s -> %s [%s %s]" % (self.src,self.dst,self.type,self.data) diff --git a/coip/apps/name/views.py b/coip/apps/name/views.py index 90c0773..3032374 100644 --- a/coip/apps/name/views.py +++ b/coip/apps/name/views.py @@ -9,12 +9,13 @@ from django.http import HttpResponseNotFound, HttpResponseForbidden,\ HttpResponseRedirect, Http404 from django.contrib.auth.decorators import login_required from coip.multiresponse import respond_to, json_response, render403 -from pprint import pformat +from pprint import pformat, pprint import logging from coip.apps.name.forms import NameEditForm, NewNameForm, NameDeleteForm,\ PermissionForm from django.shortcuts import get_object_or_404 from django.contrib.auth.models import User +from django.db.models import Q @login_required def delete(request,id): @@ -89,7 +90,18 @@ def edit(request,id): @login_required -def editacl(request,id,type): +def lsacl(request,id,type=NameLink.access_control): + name = get_object_or_404(Name,pk=id) + + if not name.has_permission(request.user,'a'): + return render403("You do not have permission to list permissions on %s" % (name)) + + return respond_to(request, + {'text/html': 'apps/name/acls.html'}, + {'name': name, 'acl': name.lsacl()}) + +@login_required +def addacl(request,id,type=NameLink.access_control): name = get_object_or_404(Name,pk=id) if not name.has_permission(request.user,'a'): @@ -103,13 +115,17 @@ def editacl(request,id,type): p = form.cleaned_data['permissions'] if not p: p = [] - perms = p.join('') - link = NameLink.objects.get_or_create(src=name,dst=dst,type=NameLink.access_control) + perms = "".join(p) + (link,created) = NameLink.objects.get_or_create(src=name,dst=dst,type=NameLink.access_control) link.data = perms link.save() - - form = PermissionForm() - return respond_to(request,{'text/html': 'apps/name/acls.html'},{'form': form, 'name': name, 'acl': name.lsacl(),'formtitle': 'Add Permission','submitname':'Add'}) + return HttpResponseRedirect("/name/%s/acl/%s" % (id,type)) + else: + form = PermissionForm() + + return respond_to(request, + {'text/html': 'apps/name/addace.html'}, + {'form': form, 'name': name,'formtitle': 'Add Permission','submitname':'Add'}) @login_required def links(request,id,type=NameLink.access_control): @@ -207,4 +223,12 @@ def rtree(request,id=None): @login_required def ctree(request,id=None): - return _tree(request,id,False) \ No newline at end of file + return _tree(request,id,False) + +@login_required +def search(request): + list = [] + if request.REQUEST.has_key('term'): + term = request.REQUEST['term'] + list = [{'label': name.short,'value': name.id} for name in Name.objects.filter(Q(short__contains=term) | Q(value__contains=term))] + return json_response(list) \ No newline at end of file diff --git a/coip/extensions/templatetags/permdisplay.py b/coip/extensions/templatetags/permdisplay.py index 23e6ed3..3928094 100644 --- a/coip/extensions/templatetags/permdisplay.py +++ b/coip/extensions/templatetags/permdisplay.py @@ -25,7 +25,7 @@ permdisplay.is_safe = True register.filter(permdisplay) def acldstdisplay(dst): - if dst.display.startswith("user:"): + if dst.display.startswith("user:") and dst.display.count(":") == 1: (pfx,username) = split(dst.display,":",1) user = User.objects.get(username=username) if user: @@ -33,7 +33,7 @@ def acldstdisplay(dst): else: return "Unknown user \"%s\"" % username else: - return "Members of %s" % (dst.display,dst.id,dst.short) + return "members of %s (%s)" % (dst.short,dst.display) acldstdisplay.is_safe = True diff --git a/coip/urls.py b/coip/urls.py index ffabf11..edca1cc 100644 --- a/coip/urls.py +++ b/coip/urls.py @@ -35,19 +35,22 @@ urlpatterns = patterns('', # Names (r'^name/id/(?P[0-9]+)(?:\.([^\.]+))?$', 'coip.apps.name.views.show_by_id'), (r'^name$', 'coip.apps.name.views.show_root'), + (r'^name/search.json$', 'coip.apps.name.views.search'), (r'^name/(?P[0-9]+)/edit$', 'coip.apps.name.views.edit'), (r'^name/(?P[0-9]+)/delete$', 'coip.apps.name.views.delete'), (r'^name/(?P[0-9]+)/add$', 'coip.apps.name.views.add'), (r'^name/(?P[0-9]+)/join$', 'coip.apps.membership.views.join'), (r'^name/(?P[0-9]+)/join/(?P[^\/]+)$', 'coip.apps.membership.views.join'), (r'^name/(?P[0-9]+)/leave/(?P[^\/]+)$', 'coip.apps.membership.views.leave'), - (r'^name/(?P.+)(?:\.([^\.]+))?$', 'coip.apps.name.views.show_by_name'), # Name Links (r'^name/(?P[0-9]+)/link/(?P[0-9]+).json$', 'coip.apps.name.views.links'), (r'^namelink/(?P[0-9]+)/remove$', 'coip.apps.name.views.removelink'), - (r'^name/(?P[0-9]+)/link/(?P[0-9]+)$', 'coip.apps.name.views.editacl'), + # ACL + (r'^name/(?P[0-9]+)/acl/(?P[0-9]+)$', 'coip.apps.name.views.lsacl'), + (r'^name/(?P[0-9]+)/acl/(?P[0-9]+)/add$', 'coip.apps.name.views.addacl'), # Links (r'^name/(?P[0-9]+)/addlink$', 'coip.apps.link.views.add'), + (r'^name/(?P.+)(?:\.([^\.]+))?$', 'coip.apps.name.views.show_by_name'), (r'^link/(?P[0-9]+)/remove$', 'coip.apps.link.views.remove'), # Membership (r'^membership/(?P[0-9]+)$', 'coip.apps.membership.views.show'), diff --git a/site-media/css/style.css b/site-media/css/style.css index b827c95..4dd4e45 100644 --- a/site-media/css/style.css +++ b/site-media/css/style.css @@ -14,6 +14,7 @@ div#footer li { float: left; margin: 0 0.15em} .ilist li { float: left; display: inline; padding: inherit; } .rlist ul { list-style: none inside; padding: inherit; } .rlist li { float: right; display: inline; padding: inherit; } +.formpadding { padding: 5px; } p.description { padding-top: 20px; padding-bottom: 5px; } div#headline{ font: 300% "Trebuchet MS", sans-serif; margin-bottom: 20px;} .name { font: 100% "Trebuchet MS", sans-serif; margin-top: 5px;} @@ -26,6 +27,8 @@ li.links { padding: 0; margin: 0; } form .ui-widget ul { list-style: none inside; padding: 0; margin: 0; } form .ui-widget li { float: right; border-right: 1px solid #CECECE; padding-right: 5px; margin: 0; vertical-align: middle;} .fieldlabel { font-weight: bold; } +.fieldinput ul { list-style: none inside; padding: 0; margin: 0; } +.fieldinput li { padding: 0; margin: 0; } div#tree { padding-bottom: 50px;} #linklist { float: right; margin-right: 50px; } #linklist ul{ list-style: none; padding: 0; margin: 0; } diff --git a/templates/apps/name/acls.html b/templates/apps/name/acls.html index 5b91429..3d3d134 100644 --- a/templates/apps/name/acls.html +++ b/templates/apps/name/acls.html @@ -1,14 +1,32 @@ -{% extends "edit.html" %} +{% extends "tree.html" %} {% load permdisplay %} -{% block beforeform %} -

Permissions on {{name}}

- +{% block widgets %} + $("#acl").accordion({ + header: 'h3', + collapsible: true, + active: false + }); +{% endblock %} +{% block content %} +

Permissions on {{name.short}}

+
{% for ace in acl %} -
- - - - +
+

Permissions for {{ace.dst|acldstdisplay}}

+
+
{{ace.dst|acldstdisplay}} {{ace.data|permdisplay}}.
+
+ +
+
+
{% endfor %} -
{{ace.dst|acldstdisplay}}{{ace.data|permdisplay}}
+ + {% endblock %} \ No newline at end of file diff --git a/templates/apps/name/addace.html b/templates/apps/name/addace.html new file mode 100644 index 0000000..17d8362 --- /dev/null +++ b/templates/apps/name/addace.html @@ -0,0 +1,51 @@ +{% extends "edit_fieldsets.html" %} +{% load permdisplay %} +{% block widgets %} + $('#wizard').formwizard({ + validationEnabled: true, + focusFirstInput: true, + textSubmit: "Finish", + validationOptions: { + rules: { + subject_label: 'required' + } + } + }); + $('#id_subject').autocomplete({ + source: "/name/search.json", + focus: function(event, ui) { + $('#id_subject').val(ui.item.label); + return false; + }, + select: function(event, ui) { + $('#id_subject').val(ui.item.label); + $('#id_dst').val(ui.item.value); + return false; + }, + minLength: 2, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } + }); +{% endblock %} +{% block beforeform %} +

Permissions on {{name.short}}

+
+{% for ace in acl %} +
+

Permissions for {{ace.dst|acldstdisplay}}

+
+
{{ace.dst|acldstdisplay}} {{ace.data|permdisplay}}.
+
+ +
+
+
+{% endfor %} +
+{% endblock %} \ No newline at end of file diff --git a/templates/apps/name/name.html b/templates/apps/name/name.html index 2b773bf..32dad82 100644 --- a/templates/apps/name/name.html +++ b/templates/apps/name/name.html @@ -27,7 +27,7 @@
    {% if render.acl %} -
  • Modify Access
  • +
  • Modify Access
  • {% endif %} {% if render.edit %}
  • Modify
  • diff --git a/templates/edit.html b/templates/edit.html index 337264d..0a17922 100644 --- a/templates/edit.html +++ b/templates/edit.html @@ -4,31 +4,33 @@ $('#id_description').wysiwyg(); {% endblock %} {% block content %} - {% block beforeform %} - {% endblock %} -
    -
    -

    {{formtitle}}

    - - {% for field in form %} - - - - {% endfor %} -
    - {% if not field.is_hidden %} -
    {{ field.label_tag }}
    - {% endif %} - {% if field.errors %} -
    {{ field.errors }}
    - {% endif %} -
    {{ field }}
    -
    -
    -
    -
    - - +{% block beforeform %}{% endblock %} +
    + +

    {{formtitle}}

    + + {% for field in form %} + + + + {% endfor %} +
    + {% if not field.is_hidden %} +
    {{ field.label_tag }}
    + {% endif %} + {% if field.errors %} +
    {{ field.errors }}
    + {% endif %} +
    {{ field }}
    +
    +
    +
      +
    • + {% if name %} +
    • + {% endif %} +
    +
    {% endblock %} \ No newline at end of file diff --git a/templates/edit_fieldsets.html b/templates/edit_fieldsets.html index d528a4c..0a8186f 100644 --- a/templates/edit_fieldsets.html +++ b/templates/edit_fieldsets.html @@ -3,8 +3,8 @@ {% block content %} {% block beforeform %} {% endblock %} -
    -
    +
    +

    {{formtitle}}

    {% if form.non_field_errors %}{{ form.non_field_errors }}{% endif %} {% for fieldset in form.fieldsets %} @@ -22,9 +22,9 @@ {% else %} {% endif %} {% endfor %} -- cgit v1.1