User can leave groups and code is cleaner when updating project permissions
authorverrierj
Tue, 08 Nov 2011 15:21:20 +0100
changeset 235 e5e5c4aeede9
parent 234 331f767d8996
child 236 8d8a59ef2b06
User can leave groups and code is cleaner when updating project permissions
src/ldt/ldt/ldt_utils/forms.py
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/security.py
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_ldt.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/groups.html
src/ldt/ldt/ldt_utils/urls.py
src/ldt/ldt/ldt_utils/views.py
src/ldt/ldt/locale/en/LC_MESSAGES/django.mo
src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo
src/ldt/ldt/static/ldt/css/workspace.css
src/ldt/ldt/static/ldt/js/projectscontents.js
--- a/src/ldt/ldt/ldt_utils/forms.py	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/forms.py	Tue Nov 08 15:21:20 2011 +0100
@@ -21,6 +21,10 @@
         model = Project
         exclude = ("ldt_id", "ldt", "created_by", "changed_by", "creation_date", "modification_date", "state", "owner")   
 
+class PermissionForm(forms.Form):
+    share = forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={'class':'checkbox_group'}))
+    perms = forms.CharField(widget=forms.HiddenInput(attrs={'class':'perm_field'})) 
+    group = forms.IntegerField(required=False, widget=forms.HiddenInput())
 
 class ReindexForm(forms.Form):
     contents = forms.ModelMultipleChoiceField(Content.objects.all()) #@UndefinedVariable
@@ -40,7 +44,6 @@
     
 
 class ContentForm(forms.ModelForm):
-
     #iri_id = forms.CharField(max_length=1024, widget=forms.HiddenInput, initial=generate_uuid)
     iriurl = forms.CharField(max_length=1024, widget=forms.HiddenInput, required=False)
     content_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False, label=_("content.content_creation_date"))
--- a/src/ldt/ldt/ldt_utils/models.py	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Tue Nov 08 15:21:20 2011 +0100
@@ -383,8 +383,6 @@
         assign('change_project', user, project)
         for content in contents:
             project.contents.add(content)
-        for group in groups:
-            assign('view_project', group, project)
         project.save()
         return create_ldt(project, user)
 
--- a/src/ldt/ldt/ldt_utils/security.py	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/security.py	Tue Nov 08 15:21:20 2011 +0100
@@ -1,42 +1,13 @@
-#from django.conf import settings
-#from ldt.ldt_utils.models import Project
-#
-#
-#def group_security(func):
-#    def wrapper(request, *args, **kwargs):
-#        if settings.USE_GROUP_PERMISSIONS:
-#            if not request.user:
-#                raise AttributeError("A user should be set in the request.")
-#            
-#            if Project.objects_safe.has_user():
-#                response = func(request, *args, **kwargs)
-#            else:                    
-#                Project.objects_safe.check_perm_for(request.user)
-#                
-#                old_project_manager = Project.objects                         
-#                old_save_method = Project.save
-#                Project.save = save_security(request.user)(Project.save)
-#                Project.objects = Project.objects_safe
-#                
-#                response = func(request, *args, **kwargs)
-#                
-#                Project.objects = old_project_manager 
-#                Project.save = old_save_method     
-#                Project.objects_safe.stop_checking()
-#            
-#        else:
-#            response = func(request, *args, **kwargs)
-#        return response
-#    return wrapper
-#
-# 
-#def save_security(user):
-#    def wrapper(func):
-#        def wrapped(self, *args, **kwargs):
-#            
-#            if not user.has_perm('change_project', self):
-#                raise AttributeError('User %s does not have sufficient permissions to change object %s' % (user, self))
-#            
-#            return func(self, *args, **kwargs)
-#        return wrapped
-#    return wrapper
\ No newline at end of file
+from django.contrib.auth.models import Group
+from guardian.shortcuts import assign, remove_perm
+
+def assign_project_to_groups(project, permissions):
+    for elem in permissions:
+        group = Group.objects.get(id=elem['group'])
+        if elem['share']:
+            assign('view_project', group, project)
+            if elem['perms'] == 'write':
+                assign('change_project', group, project)
+        else:
+            remove_perm('view_project', group, project)
+            remove_perm('change_project', group, project) 
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_ldt.html	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_ldt.html	Tue Nov 08 15:21:20 2011 +0100
@@ -49,26 +49,34 @@
 {% block js_declaration %}
 	{{ block.super }}
 	<script type="text/javascript">
-	function checkbox_selection(id_checkbox, checkbox_type) {
+	function check_uncheck_all(name) {
 		var check_all = '{% trans "check all" %}';
 		var uncheck_all = '{% trans "uncheck all" %}';
-		var id_str = "#" + id_checkbox;
+		var id_name = "#global_checkbox_" + name;
 		
-		$(id_str).attr('title', uncheck_all);
+		$(id_name).attr('title', uncheck_all);
 		
-		$(id_str).change(function () {
-			var checkbox_ids = ".cellcheckbox input[name=\"" + checkbox_type + "\"]";
-			if ($(id_str).is(":checked")) {
-				$(checkbox_ids).prop('checked', true);
-				$(id_str).attr('title', uncheck_all );
+		$(id_name).change(function () {
+			var checkbox_names = ".checkbox_" + name;
+			if ($(id_name).is(":checked")) {
+				$(checkbox_names).prop('checked', true);
+				$(id_name).attr('title', uncheck_all );
 			} else {
-				$(checkbox_ids).prop('checked', false);
-				$(id_str).attr('title', check_all);
+				$(checkbox_names).prop('checked', false);
+				$(id_name).attr('title', check_all);
 			}
-			$(checkbox_ids).trigger("change");
+			$(checkbox_names).trigger("change");
 		});		
 	}
 	
+	function check_initial_groups() {
+		$(".checkbox_group").each(function (elem) {
+			if ( $(".choice", $(this).closest('tr')).length ) {
+				$(this).prop('checked', true);				
+			}		
+		});			
+	}
+	
 	$(document).ready(function() {	
 		
 		$("#close_button").click(function (e) {
@@ -76,8 +84,9 @@
 			parent.$.nmTop().close();
 		});
 		
-		checkbox_selection("check_contents", "contents");
-		checkbox_selection("check_groups", "groups");
+		check_uncheck_all("content");
+		check_uncheck_all("group");
+		check_initial_groups();		
 
         $(".permission").live("click", function () {
             var group_name = $(this).attr('value');
@@ -92,10 +101,10 @@
             	var perm = 'write';            	
             }
             
-            $("input[name=\"perm_" + group_id + "\"]").attr('value', perm);
+            $(".perm_field",$(this).parent().parent()).attr('value', perm);
         });
         
-        $("input[name=\"groups\"]").bind("change", function() {
+        $(".checkbox_group").bind("change", function() {
             var line = $(this).closest('td').next().next();
             
             if (!$(this).is(":checked")) {
@@ -153,7 +162,7 @@
 						<td class="cellcheckbox">
 						{% if not ldt_id %}
 							{% if contents|length > 1 %}
-							<input class="selectallcontents" id="check_contents" type="checkbox" checked="true" />	 
+							<input class="selectallcontents" id="global_checkbox_content" type="checkbox" checked="true" />	 
 							{% endif %}
 						{% endif %}	
 						</td>				
@@ -163,7 +172,7 @@
 				    <tbody class="projectscontentsbody">
 				{% for content in contents %}
 					<tr class="imageline {% cycle 'projectscontentsoddline' 'projectscontentsevenline'%}">
-					    <td class="cellcheckbox"><input type="checkbox" name="contents" value="{{ content.id }}" checked="true" {% if ldt_id %}disabled="disabled"{% endif %} /></td>
+					    <td class="cellcheckbox"><input type="checkbox" class="checkbox_content" name="contents" value="{{ content.id }}" checked="true" {% if ldt_id %}disabled="disabled"{% endif %} /></td>
 					    <td class="contenttitle">{{ content.title }}</td>
 					</tr>
 				{% endfor %}
@@ -173,18 +182,20 @@
 		</div>
 	</div>	
      
-    
-	<div id="righttable" class="span-11">
+     {{ form.errors }}
+     {{group_form.errors}}
+   <div id="righttable" class="span-11">
 	    <label>{% trans "group list"%}</label>
 	
         <div class="span-10 last" id="ldtcreatecontentslistcontainer">
             <div class="span-10 last projectscontentstablediv" id="ldtcreatecontentstablediv">
                 <table class="projectscontentstable">
+                    {{ management_form }}
                 
                     <tr class="projectscontentsheader last" id="contentslistheader">
                         <td class="cellcheckbox">
                         {% if groups|length > 1 %}
-                        	<input class="selectallgroups" id="check_groups" type="checkbox" checked="true"/>
+                        	<input class="selectallgroups" id="global_checkbox_group" type="checkbox" checked="true"/>
                         {% endif %}                            
                         </td>				
                         <td class="projectcontentsheadertitle">{% trans "nom" %}</td>
@@ -193,24 +204,26 @@
                 
                     <tbody class="projectscontentsbody">
                 
-                	{% for group in groups %}
-                    <tr class="imageline projectscontentsoddline">
-                        <td class="cellcheckbox"><input type="checkbox" name="groups" value="{{ group.id }}" {% if group.member %}checked="true"{% endif %} /></td>
-                        <td class="projecttitle">{{ group.name }}</td>
-                        <td><a value="group_{{group.id}}" class="perm_read permission {% if group.member and not group.change%}choice{% endif %}" title="{% trans "This group can read the project" %}">{% trans "perm.read" %}</a>
-                        <a value="group_{{group.id}}" class="perm_write permission {% if group.member and group.change %}choice{% endif %}" title="{% trans "This group can change the project" %}">{% trans "perm.write" %}</a></td>
-                        <input type="hidden" name="perm_{{group.id}}" value="read" />
-                    </tr>
-                	{% endfor %}
-                
+				    {% for form, group in group_form %}			    			    
+				    <tr class="imageline projectscontentsoddline">
+				    	<td class="cellcheckbox">{{ form.share }}</td>
+				    	<td class="projecttitle">{{ group.name }}</td>
+				    	<td>
+				    	<a value="group_{{group.id}}" class="perm_read permission {% if group.member and not group.change%}choice{% endif %}" title="{% trans "This group can read the project" %}">{% trans "perm.read" %}</a>
+				        <a value="group_{{group.id}}" class="perm_write permission {% if group.member and group.change %}choice{% endif %}" title="{% trans "This group can change the project" %}">{% trans "perm.write" %}</a>
+				       	</td>
+				       	{{ form.perms }}
+				       	{{ form.group }}
+				    </tr>
+				    {% endfor %} 
+				                
                     </tbody>
                 </table>		
             </div>		
-        </div>
-       
-    </div>    
-    
-            
+        </div>       
+    </div> 
+               
+               
     <div id="submitcontent-buttons" class="span-11 last">
 		<button type="button" id="close_button"  value="close">{% trans 'close_cancel' %}</button>
 		{% if ldt_id %}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/groups.html	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/groups.html	Tue Nov 08 15:21:20 2011 +0100
@@ -23,9 +23,9 @@
         //alert("group id = " + $(this).attr('id') + ", url = " + get_group_projects_url);
         id_group = $(this).attr('id');
         // Remove icons from all the lines
-        $(".next_icon, td .create_group").hide();
+        $(".next_icon, td .grouplink").hide();
         // Display icons from the good line
-        $(".next_icon, .create_group",this).show();
+        $(".next_icon, .grouplink",this).show();
         // Show the search textfield and update the id_group in the hidden input
         $('#search_div').show();
         $('#id_group').val(id_group);
@@ -44,6 +44,8 @@
             },
     		error: function(jqXHR, textStatus, errorThrown) {
     			alert(jqXHR.responseText);
+    			resp = $.parseJSON(jqXHR.responseText);
+    			alert(resp.message);
     		}
         });
     });
@@ -73,10 +75,11 @@
 			{% get_obj_perms request.user for group as "group_perms" %}
 			
 			{% if "change_group" in group_perms %}
-			    <td class="cellimg"><a class="create_group" title="Change this group" href="{% url ldt.ldt_utils.views.update_group group_id=group.id%}">c</a></td>
+			    <td class="cellimg"><a class="grouplink create_group" title="{% trans "Change this group"%}" href="{% url ldt.ldt_utils.views.update_group group_id=group.id%}">c</a></td>
 			   <td><b>{{ group.name }}</b></td>
 			{% else %}
-			    <td class="cellimg"></td><td>{{ group.name }}</td>
+			    <td class="cellimg"><a class="grouplink" title="{% trans "Leave this group" %}" href="{% url ldt.ldt_utils.views.leave_group group.id%}">l</a></td>
+			    <td>{{ group.name }}</td>
 			{% endif %}
 			<td class="align_right"><img src="{{LDT_MEDIA_PREFIX}}/img/control_play.png" class="next_icon"/></td>
 			
--- a/src/ldt/ldt/ldt_utils/urls.py	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/urls.py	Tue Nov 08 15:21:20 2011 +0100
@@ -37,6 +37,7 @@
     url(r'^segmentHighlight/(?P<project_id>.*)/(?P<content_id>.*)/(?P<ensemble_id>.*)/(?P<cutting_id>.*)/(?P<segment_id>.*)/$', 'views.highlight_segment'),
     url(r'^createGroup/$', 'views.create_group'),
     url(r'^updateGroup/(?P<group_id>.*)$', 'views.update_group'),
+    url(r'^leaveGroup/(?P<group_id>.*)$', 'views.leave_group'),
 )
 
 urlpatterns += patterns('',
--- a/src/ldt/ldt/ldt_utils/views.py	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/ldt_utils/views.py	Tue Nov 08 15:21:20 2011 +0100
@@ -6,6 +6,7 @@
 from django.db.models import Q
 from django.forms.models import model_to_dict
 from django.forms.util import ErrorList
+from django.forms.formsets import formset_factory
 from django.http import (HttpResponse, HttpResponseRedirect,
     HttpResponseForbidden, HttpResponseServerError)
 from ldt.indexation import get_results_with_context, highlight_documents
@@ -17,7 +18,7 @@
 from django.utils.html import escape
 from django.utils.translation import ugettext as _, ungettext
 from forms import (LdtAddForm, SearchForm, AddProjectForm, CopyProjectForm,
-    ContentForm, MediaForm, GroupAddForm)
+    ContentForm, MediaForm, GroupAddForm, PermissionForm)
 from guardian.shortcuts import assign, remove_perm, get_perms
 from ldt.ldt_utils.models import Content
 from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
@@ -40,6 +41,8 @@
 import re
 import datetime
 
+from security import assign_project_to_groups
+
 @login_required
 def workspace(request):
     
@@ -387,23 +390,22 @@
 
 @login_required
 def create_ldt_view(request):
+    permission_formset = formset_factory(PermissionForm, extra=0)
+    
     if request.method == "POST" :
         form = LdtAddForm(request.POST)
         form_status = "none"
         contents = Content.objects.all()
         groups = request.user.groups.all()
-        
-        if form.is_valid():
+        group_form = permission_formset(request.POST)
+                
+        if form.is_valid() and group_form.is_valid():
             user = request.user
-            p = Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents'],
-                                   description=form.cleaned_data['description'], groups=form.cleaned_data['groups'])
             
-            for k in request.POST:
-                if k.startswith('perm_'):
-                    group_id = k.split('_')[-1]
-                    group = Group.objects.get(id=group_id)
-                    if request.POST[k] == 'write':
-                        assign('change_project', group, p)
+            p = Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents'],
+                                   description=form.cleaned_data['description'])
+            
+            assign_project_to_groups(p, group_form.cleaned_data)          
             
             form_status = "saved"
             contents = []
@@ -411,9 +413,22 @@
         form = LdtAddForm()
         contents = Content.objects.all() #@UndefinedVariable
         groups = request.user.groups.all()
+        
+        perm_list = [] 
+        for group in groups:
+            perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
+        permission = permission_formset(initial=perm_list)
+              
+        management_form = permission.management_form
+        group_form = zip(permission, groups)
+        
         form_status = "none"
+        
+    if form_status != 'none':
+        management_form = None
+    
             
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'groups': groups, 'form': form, 'form_status':form_status, 'create_project_action':reverse(create_ldt_view), 'language_code' : settings.LANGUAGE_CODE[2:]}, context_instance=RequestContext(request))
+    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'group_form': group_form, 'management_form': management_form, 'form_status':form_status, 'create_project_action':reverse(create_ldt_view), 'language_code' : settings.LANGUAGE_CODE[2:]}, context_instance=RequestContext(request))
      
 def created_ldt(request):
     return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request))
@@ -772,10 +787,10 @@
 
 @login_required
 def update_project(request, ldt_id):
-
+    permission_formset = formset_factory(PermissionForm, extra=0)
     project = get_object_or_404(Project, ldt_id=ldt_id)
     contents = project.contents.all()
-    groups = request.user.groups.all()
+    groups = request.user.groups.all()    
     
     for g in groups:
         list_perms = get_perms(g, project)
@@ -801,10 +816,13 @@
                 project.delete()
             form_status = 'deleted'
             form = AddProjectForm()
+            group_form = permission_formset()
         else:
             form_status = 'saved'
             form = AddProjectForm(request.POST)
-            if form.is_valid():
+            group_form = permission_formset(request.POST)
+            
+            if form.is_valid() and group_form.is_valid():
                 if project.title != form.cleaned_data['title'] or project.description != form.cleaned_data['description']:
                     project.title = form.cleaned_data['title']
                     project.description = form.cleaned_data['description']
@@ -814,12 +832,28 @@
                     res[0].set("abstract", project.description)
                     project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
                     project.save()
+                    
+                assign_project_to_groups(project, group_form.cleaned_data)
     else:
         form = AddProjectForm({'title':unicode(project.title), 'description':unicode(project.get_description())})
-        form_status = 'none'
         
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'groups': groups, 'ldt_id': ldt_id, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.update_project", args=[ldt_id])}, context_instance=RequestContext(request))
+        perm_list = [] 
+        for group in groups:
+            perm_list.append({'share': False, 'perms': 'read', 'group': group.id })
+        permission = permission_formset(initial=perm_list)    
+        management_form = permission.management_form
 
+        form_status = 'none'
+  
+    if form_status == 'none':
+        group_form = zip(permission, groups)
+    else:
+        management_form = None
+    
+        
+    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'groups': groups,
+                              'ldt_id': ldt_id, 'contents':contents, 'group_form': group_form, 'management_form': management_form, 
+                              'create_project_action':reverse("ldt.ldt_utils.views.update_project", args=[ldt_id])}, context_instance=RequestContext(request))
 
 @login_required
 def copy_project(request, ldt_id):
@@ -1198,8 +1232,7 @@
 @login_required
 def update_group(request, group_id):
     
-    group = get_object_or_404(Group, id=group_id)
-    
+    group = get_object_or_404(Group, id=group_id)    
     user_list = User.objects.exclude(id=settings.ANONYMOUS_USER_ID).exclude(id=request.user.id)
     members_list = User.objects.filter(groups__id=group_id)
     form_status = ''    
@@ -1207,7 +1240,7 @@
     if not request.user.has_perm('change_group', group):
         user_list = []
         form_status = 'saved'
-        form = GroupAddForm()
+        form = GroupAddForm(instance=group)
         return render_to_response("ldt/ldt_utils/create_group.html", {'group_id' : group_id, 'form' : form, 'form_status' : form_status, 'user_list' : user_list}, context_instance=RequestContext(request))
 
     for u in user_list:
@@ -1241,3 +1274,18 @@
         form = GroupAddForm({'name':unicode(group.name), 'members_list':members_list})    
     
     return render_to_response("ldt/ldt_utils/create_group.html", {'group_id' : group_id, 'form' : form, 'form_status' : form_status, 'user_list' : user_list}, context_instance=RequestContext(request))
+
+@login_required
+def leave_group(request, group_id, redirect=True):
+    group = get_object_or_404(Group, id=group_id)
+    redirect = boolean_convert(redirect)
+    
+    if not request.user.has_perm('change_group', group):
+        request.user.groups.remove(group)
+        
+    if redirect:        
+        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.groups'))
+    else:
+        return HttpResponse(simplejson.dumps({'res':True}, ensure_ascii=False), mimetype='application/json')
+        
+
Binary file src/ldt/ldt/locale/en/LC_MESSAGES/django.mo has changed
Binary file src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo has changed
--- a/src/ldt/ldt/static/ldt/css/workspace.css	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/static/ldt/css/workspace.css	Tue Nov 08 15:21:20 2011 +0100
@@ -100,7 +100,7 @@
 .projectscontentsheader  {
 	background: #b5b5b5;
 	padding: 1px 2px;
-	text-align: left;	
+	text-align: left;
 }
 .projectcontentsheadertitle {
 	font-weight: bold;
@@ -137,7 +137,6 @@
 	color: #4F5155;
 }
 
-
 .projecttitle {
 	width: 367px;
 	padding: 2px 10px 2px 5px;	
@@ -163,6 +162,9 @@
 	padding-right: 16px;
 }
 
+.permissionscol {
+}
+
 .cellimg {
 	width: 18px;
 	text-align: center;
@@ -201,6 +203,6 @@
     margin-top: 20px;
 }
 
-.next_icon, tr .create_group {
+.next_icon, .grouplink {
 	display: none;
 }
--- a/src/ldt/ldt/static/ldt/js/projectscontents.js	Mon Nov 07 16:24:17 2011 +0100
+++ b/src/ldt/ldt/static/ldt/js/projectscontents.js	Tue Nov 08 15:21:20 2011 +0100
@@ -53,7 +53,7 @@
         });
     });
     
-    $('.cellimgdiv img, .publishedproject, .unpublishedproject, .create_group').qtip({
+    $('.cellimgdiv img, .publishedproject, .unpublishedproject, .grouplink').qtip({
     	style: {
     		classes: 'ui-tooltip-dark ui-tooltip-rounded'
     	}