summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeif Johansson <leifj@sunet.se>2011-03-03 23:28:11 +0100
committerLeif Johansson <leifj@sunet.se>2011-03-03 23:28:11 +0100
commitd60a62a68a5c3442a6b464cca1c1a218d57d8ecc (patch)
treebc7f4d62751fff095bfcd547a95714b19e5b5487
parent5bf172664d789d10781441e2a812f626c15c8da6 (diff)
new acl UI
-rw-r--r--coip/apps/membership/views.py4
-rw-r--r--coip/apps/name/forms.py24
-rw-r--r--coip/apps/name/models.py1
-rw-r--r--coip/apps/name/views.py40
-rw-r--r--coip/extensions/templatetags/permdisplay.py4
-rw-r--r--coip/urls.py7
-rw-r--r--site-media/css/style.css3
-rw-r--r--templates/apps/name/acls.html38
-rw-r--r--templates/apps/name/addace.html51
-rw-r--r--templates/apps/name/name.html2
-rw-r--r--templates/edit.html52
-rw-r--r--templates/edit_fieldsets.html8
12 files changed, 178 insertions, 56 deletions
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 <a class=\"tip\" title=\"%s\" href=\"/name/id/%d\">%s</a>" % (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<id>[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<id>[0-9]+)/edit$', 'coip.apps.name.views.edit'),
(r'^name/(?P<id>[0-9]+)/delete$', 'coip.apps.name.views.delete'),
(r'^name/(?P<id>[0-9]+)/add$', 'coip.apps.name.views.add'),
(r'^name/(?P<id>[0-9]+)/join$', 'coip.apps.membership.views.join'),
(r'^name/(?P<id>[0-9]+)/join/(?P<membername>[^\/]+)$', 'coip.apps.membership.views.join'),
(r'^name/(?P<id>[0-9]+)/leave/(?P<membername>[^\/]+)$', 'coip.apps.membership.views.leave'),
- (r'^name/(?P<name>.+)(?:\.([^\.]+))?$', 'coip.apps.name.views.show_by_name'),
# Name Links
(r'^name/(?P<id>[0-9]+)/link/(?P<type>[0-9]+).json$', 'coip.apps.name.views.links'),
(r'^namelink/(?P<id>[0-9]+)/remove$', 'coip.apps.name.views.removelink'),
- (r'^name/(?P<id>[0-9]+)/link/(?P<type>[0-9]+)$', 'coip.apps.name.views.editacl'),
+ # ACL
+ (r'^name/(?P<id>[0-9]+)/acl/(?P<type>[0-9]+)$', 'coip.apps.name.views.lsacl'),
+ (r'^name/(?P<id>[0-9]+)/acl/(?P<type>[0-9]+)/add$', 'coip.apps.name.views.addacl'),
# Links
(r'^name/(?P<id>[0-9]+)/addlink$', 'coip.apps.link.views.add'),
+ (r'^name/(?P<name>.+)(?:\.([^\.]+))?$', 'coip.apps.name.views.show_by_name'),
(r'^link/(?P<id>[0-9]+)/remove$', 'coip.apps.link.views.remove'),
# Membership
(r'^membership/(?P<id>[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 %}
-<h1>Permissions on {{name}}</h1>
-<table style="margin-bottom: 20px;">
+{% block widgets %}
+ $("#acl").accordion({
+ header: 'h3',
+ collapsible: true,
+ active: false
+ });
+{% endblock %}
+{% block content %}
+<h1>Permissions on {{name.short}}</h1>
+<div id="acl" style="margin-bottom: 20px;">
{% for ace in acl %}
-<tr>
- <td>{{ace.dst|acldstdisplay}}</td>
- <td>{{ace.data|permdisplay}}</td>
- <td><a href="/namelink/{{ace.id}}/remove"><span class="ui-icon ui-icon-trash"></span></td>
-</tr>
+ <div id="{{ace.id}}">
+ <h3 class="listheader">Permissions for {{ace.dst|acldstdisplay}}</h3>
+ <div>
+ <div>{{ace.dst|acldstdisplay}} {{ace.data|permdisplay}}.</div>
+ <div class="rlist button">
+ <ul>
+ <li><a href="/namelink/{{ace.id}}/remove">Remove</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
{% endfor %}
-</table>
+</div>
+<div class="ilist button">
+ <ul>
+ <li><a href="/name/{{name.id}}/acl/0/add">Add Permission</a></li>
+ </ul>
+</div>
{% 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 %}
+<h1>Permissions on {{name.short}}</h1>
+<div id="acl" style="margin-bottom: 20px;">
+{% for ace in acl %}
+<div id="{{acc.id}}">
+ <h3 class="listheader">Permissions for {{ace.dst|acldstdisplay}}</h3>
+ <div>
+ <div>{{ace.dst|acldstdisplay}} {{ace.data|permdisplay}}.</div>
+ <div class="rlist button">
+ <ul>
+ <li><a href="/namelink/{{ace.id}}/remove">Remove</a></li>
+ </ul>
+ </div>
+ </div>
+</div>
+{% endfor %}
+</div>
+{% 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 @@
<div class="rlist">
<ul>
{% if render.acl %}
- <li class="button"><a href="/name/{{name.id}}/link/0">Modify Access</a></li>
+ <li class="button"><a href="/name/{{name.id}}/acl/0">Modify Access</a></li>
{% endif %}
{% if render.edit %}
<li class="button"><a href="/name/{{name.id}}/edit">Modify</a></li>
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 %}
- <form method="POST" class="ui-helper-reset ui-widget-contents ui-corner-all">
- <div class="infopanel">
- <h1>{{formtitle}}</h1>
- <table class="formtable">
- {% for field in form %}
- <tr>
- <td>
- {% if not field.is_hidden %}
- <div class="ui-widget fieldlabel">{{ field.label_tag }}</div>
- {% endif %}
- {% if field.errors %}
- <div class="ui-widget ui-state-error">{{ field.errors }}</div>
- {% endif %}
- <div class="ui-widget">{{ field }}</div>
- </td>
- </tr>
- {% endfor %}
- </table>
- </div>
- <br/>
- <div class="button">
- <input type="submit" value="{{submitname}}" />
- <input type="button" onClick="document.location='{{name.url}}'" value="Cancel"/>
+{% block beforeform %}{% endblock %}
+<div>
+ <form method="POST" class="bbq ui-helper-reset ui-widget ui-widget-content ui-corner-all formpadding">
+ <h1>{{formtitle}}</h1>
+ <table class="formtable">
+ {% for field in form %}
+ <tr>
+ <td>
+ {% if not field.is_hidden %}
+ <div class="ui-widget fieldlabel">{{ field.label_tag }}</div>
+ {% endif %}
+ {% if field.errors %}
+ <div class="ui-widget ui-state-error">{{ field.errors }}</div>
+ {% endif %}
+ <div class="ui-widget">{{ field }}</div>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ <div class="ilist button" style="padding-bottom: 10px;">
+ <ul>
+ <li><input type="submit" value="{{submitname}}" /></li>
+ {% if name %}
+ <li style="float: right;"><input type="button" onClick="document.location='{{name.url}}'" value="Done"/></li>
+ {% endif %}
+ </ul>
</div>
</form>
+</div>
{% 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 %}
- <div class="infopanel">
- <form method="POST" id="wizard" class="bbq" style="padding: 5px;">
+ <div>
+ <form method="POST" id="wizard" class="bbq formpadding">
<h1>{{formtitle}}</h1>
{% if form.non_field_errors %}{{ form.non_field_errors }}{% endif %}
{% for fieldset in form.fieldsets %}
@@ -22,9 +22,9 @@
{% else %}
<li class="links {% if field.field.required %}required{% endif %}" {{ field.row_attrs }}>
{{ field.errors }}
- <label for="id_{{ field.html_name }}">{{ field.label }}
+ <label for="id_{{ field.html_name }}" class="fieldlabel">{{ field.label }}
{% if field.field.required %}<b>*</b>{% endif %}</label>
- {{ field }}
+ <div class="fieldinput">{{ field }}</div>
</li>
{% endif %}
{% endfor %}