View Issue Details

IDProjectCategoryView StatusLast Update
03788User patchesOtherpublic2012-06-21 13:33
ReporterMazi Assigned To 
PrioritynormalSeveritytweak 
Status confirmedResolutionopen 
Product Version1.87 
Summary03788: New label set handling
Description

Referring to this forum thread (https://www.limesurvey.org/en/support/forums/5-can-i-do-this-with-limesurvey/31678-labet-set-sharing-issue-multi-user-site?limit=10&start=10#32920) and two (http://ideas.limesurvey.org/ideatorrent/idea/16/ and http://ideas.limesurvey.org/ideatorrent/idea/15/) entries in our idea tracker a user has taken care of the label set management problem.

Devs: Please review the code so maybe we can take this into the next 1.87beta release.

TagsNo tags attached.
Complete LimeSurvey version number (& build)

Relationships

related to 04075 confirmed New Label Sharing System 

Activities

Kemmotar

Kemmotar

2009-10-28 10:27

reporter   ~09886

Last edited: 2009-10-28 10:35

In order to modify labelset management I had to modify the group management, inserting a new type of user, the group manager, who has the duty to manage the group (adding/removing users) and the right to give "edit labelset right" to other users in the group (obviously only in the group in which he has manager role). Group manager manage group instead of group owner, considering that group owner is a superadmin and he can't manage all groups he created.
Another change I had to do is about who can add/remove users to/from a group (superadmin, group owner and group manager) and who can modify user rights for group. Superadmin and group owner can assign group manager role and the group manager can only assign labelset editor role.

Which kind of action can be made in usergroup page:

superadmin: edit rights, delete users, add users
group owner: edit rights, delete users, add users
group manager: edit rights, delete users, add users
labelset editor: null

Which kind of rights can be assigned:

superadmin: manage group, edit labelset
group owner: manage group, edit labelset
group manager: edit labelset

user372

2009-10-28 11:38

  ~09887

@ Kemmotar: Can you provide a SVN diff-patch of your modification?

Kemmotar

Kemmotar

2009-11-02 17:38

reporter   ~09958

Should I provide you a document with the description of every changes?

user372

2009-11-02 18:19

  ~09959

@ c_schmitz and/or Lemeur: please review the attached patch - Thx!

lemeur

lemeur

2009-11-06 23:04

developer   ~09983

@Kemmotar,

Thanks for the work on this fix.

However I cannot integrate it since it lacks the upgrade DB code.

Please checkout latest SVN version, then apply my uploaded PATCH-3788.diff patch which is basically yours (but it applies cleanly to latest dev tree).

Then increment $dbversion in version.php.

Finally have a look to the limesurvey/admin/update directory, and update the "upgrade-XXX.php" scripts so that updating to the new DB scehma will be possible without having to install LS from scratch.

Could you do this as soon as possible so that your fix is integrated in the upcomming release ?

Please let me know.

Regards,
Thibault

Kemmotar

Kemmotar

2009-11-09 11:09

reporter   ~10022

Uhm... I've made the update to the latest SVN version 7860 and when I apply your patch it gives me an outdated patch error. I noticed that your patch can be applied to 7840 revision and not to 7860. I'm sorry, this could be due to my delay on reading your note.

Kemmotar

lemeur

lemeur

2009-11-09 11:28

developer   ~10023

@Kemmotar,
Please try the patch-3788-rev7860.diff patch file for latest svn version.

Thanks in advance,
Thibault

Kemmotar

Kemmotar

2009-11-09 15:00

reporter   ~10026

Did you have updated only the revision number of the diff patch? I get the same error because the code is changed and then TortoiseSVN can'y apply the patch, even if I update to revision 7840. Sorry but I'm inexperienced in using SVN so, if I provide you a diff patch, for the latest revision (7863), with only the database updates changes? Is it ok for you?

lemeur

lemeur

2009-11-09 17:08

developer   ~10030

Yes, you can provide just a partial patch for DB updates.

Thanks in advance,
Thibault

2009-11-11 00:39

 

Patch-7870.diff (34,564 bytes)   
Index: version.php
===================================================================
--- version.php	(revision 7870)
+++ version.php	(working copy)
@@ -1,7 +1,7 @@
 <?php
 
     $versionnumber = "1.87beta";
-    $dbversionnumber = 141;
+    $dbversionnumber = 142;
     $buildnumber = '';
 
-?>
\ No newline at end of file
+?>
Index: common.php
===================================================================
--- common.php	(revision 7870)
+++ common.php	(working copy)
@@ -382,7 +382,7 @@
 			{
 			  $adminmenu .= "<img src='$imagefiles/blank.gif' alt='' width='40'   />\n";
 			}
-		if($_SESSION['USER_RIGHT_MANAGE_LABEL'] == 1)
+		if($_SESSION['USER_RIGHT_MANAGE_LABEL'] == 1 || islabelseteditor($_SESSION['loginID']) == 1)
 			{
 			$adminmenu  .= "<a href=\"#\" onclick=\"window.open('$scriptname?action=labels', '_top')\" title=\"".$clang->gTview("Edit/Add Label Sets")."\">\n" 
                         ."<img src='$imagefiles/labels.png'  name='LabelsEditor' alt='". $clang->gT("Edit/Add Label Sets")."' /></a>\n"
@@ -1537,6 +1537,43 @@
 	return $thissurvey;
 }
 
+function getlabelsetseditable($uid, $superadmin)
+{
+	global $connect;
+	
+	$uid = sanitize_int($uid);
+	$superadmin = sanitize_int($superadmin);
+	
+	//select only labelsets from groups in which user has editing rights
+	$query = "SELECT lid, name, label_name
+				FROM (".db_table_name('labelsets')." AS ls 
+				INNER JOIN (SELECT ugid FROM ".db_table_name('user_groups_rights')." WHERE (uid = ".$uid." AND edit_labelset = 1)) AS tugr ON ls.ugid = tugr.ugid
+				INNER JOIN ".db_table_name('user_groups')." AS ug ON ug.ugid = tugr.ugid)
+				GROUP BY name, lid, label_name";
+	$result = db_execute_assoc($query) or safe_die ("Couldn't get list of label sets<br />$query<br />".$connect->ErrorMsg());
+	
+	$labelsets=array();
+	while ($row=$result->FetchRow())
+	{
+		$labelsets[] = array('lid' => $row['lid'], 'labelset_name' => $row['label_name'], 'group_name' => $row['name']);
+	}
+	
+	//only for superadmin, uncategorized labelsets
+	if ($superadmin == 1)
+	{
+		$uncategorizedGroup = "Uncategorized";
+		$query = "SELECT lid, label_name FROM ".db_table_name('labelsets')." WHERE ugid=0";
+		
+		$result = db_execute_assoc($query) or safe_die ("Couldn't get list of label sets<br />$query<br />".$connect->ErrorMsg());
+		
+		while ($row=$result->FetchRow())
+		{
+			$labelsets[] = array('lid' => $row['lid'], 'labelset_name' => $row['label_name'], 'group_name' => $uncategorizedGroup);
+		}
+	}
+	
+	return $labelsets;
+}
 
 function getlabelsets($languages=null)
 // Returns a list with label sets
@@ -1566,7 +1603,22 @@
 	return $labelsets;
 }
 
+function islabelseteditor($uid)
+{
+	global $connect;
+	
+	$uid = sanitize_int($uid);
+	
+	$query = "SELECT uid FROM ".db_table_name('user_groups_rights')." WHERE (uid = ".$uid." AND edit_labelset = 1)";
+	$result = db_execute_assoc($query) or safe_die ("Couldn't get list of label sets<br />$query<br />".$connect->ErrorMsg());
+	
+	if ($result->RecordCount() > 0)
+		return 1;
+	else
+		return 0;
+}
 
+
 function checkifemptydb()
 {
 	global $connect, $dbprefix;
@@ -4582,6 +4634,48 @@
  	return $connect->Execute($uquery);     //Checked
 }
 
+// set the rights of a user in a group
+function setusergrouprights($uid, $ugid, $rights)
+{
+	global $connect;
+    $uid=sanitize_int($uid);
+	$ugid=sanitize_int($ugid);
+	$updates = "manage_group=".$rights['manage_group'];
+	$updates = "edit_labelset=".$rights['edit_labelset'];
+
+	//control if user already exist in table
+	$squery = "SELECT uid FROM ".db_table_name('user_groups_rights')." WHERE uid = ".$uid;
+	$sresult = $connect->Execute($squery);
+	
+	if ($sresult->RecordCount() > 0)
+	{ //user entry already exist
+		$ugquery = "UPDATE ".db_table_name('user_groups_rights')." SET ".$updates." WHERE uid = ".$uid." AND ugid=".$ugid;
+	}
+	else
+	{ //new user entry
+		$ugquery = "INSERT INTO ".db_table_name('user_groups_rights')." VALUES ".$updates;
+	}
+ 	return $connect->Execute($ugquery);     //Checked
+}
+
+// get the uid of the group manager
+function getusergroupmanager($ugid)
+{
+	global $connect;
+	$ugid=sanitize_int($ugid);
+	$ugquery = "SELECT uid FROM ".db_table_name('user_groups_rights')." WHERE ugid = ".$ugid." AND manage_group = 1";
+	return $connect->Execute($ugquery); 
+}
+
+// get the uid of the group owner
+function getusergroupowner($ugid)
+{
+	global $connect;
+	$ugid=sanitize_int($ugid);
+	$ugquery = "SELECT uid FROM ".db_table_name('user_groups')." WHERE ugid = ".$ugid;
+	return $connect->Execute($ugquery); 
+}
+
 // set the rights for a survey
 function setsurveyrights($uids, $rights)
 {
@@ -4600,6 +4694,26 @@
 	return $connect->Execute($uquery);   //Checked 
 }
 
+// get list of groups in which the user is enrolled
+function getusergroups($uid)
+{
+	global $connect;
+	$uid=sanitize_int($uid);
+	
+	$query = "SELECT ug.ugid, name FROM ".db_table_name('user_groups')." AS ug INNER JOIN 
+		(SELECT ugid FROM ".db_table_name('user_in_groups')." WHERE uid = {$uid}) AS u ON ug.ugid = u.ugid";
+	
+	$result = db_execute_assoc($query) or safe_die ("Couldn't get list of groups<br />$query<br />".$connect->ErrorMsg());
+	
+	$groups=array();
+	while ($row=$result->FetchRow())
+	{
+		$groups[] = array('ugid' => $row['ugid'], 'group_name' => $row['name']);
+	}
+	
+	return $groups;
+}
+
 function createPassword()
 {
 	$pwchars = "abcdefhjmnpqrstuvwxyz23456789";
Index: admin/userrighthandling.php
===================================================================
--- admin/userrighthandling.php	(revision 7870)
+++ admin/userrighthandling.php	(working copy)
@@ -64,7 +64,8 @@
 	. "<img src='$imagefiles/seperator.gif' alt='' />\n";
 
 	if($ugid && $grpresultcount > 0 &&
-		$_SESSION['loginID'] == $grow['owner_id'])
+		($_SESSION['loginID'] == $grow['owner_id']
+		 || $_SESSION['USER_RIGHT_SUPERADMIN'] == 1))
 	{
 		$usergroupsummary .=  "<a href=\"#\" onclick=\"window.open('$scriptname?action=editusergroup&amp;ugid=$ugid','_top')\""
 		. "title='".$clang->gTview("Edit Current User Group")."'>" 
@@ -76,7 +77,8 @@
 	}
 
 	if($ugid && $grpresultcount > 0 &&
-		$_SESSION['loginID'] == $grow['owner_id'])
+		($_SESSION['loginID'] == $grow['owner_id']
+		 || $_SESSION['USER_RIGHT_SUPERADMIN'] == 1))
 	{
 //		$usergroupsummary .= "<a href='$scriptname?action=delusergroup&amp;ugid=$ugid' onclick=\"return confirm('".$clang->gT("Are you sure you want to delete this entry?","js")."')\""
 		$usergroupsummary .= "<a href='#' onclick=\"if (confirm('".$clang->gT("Are you sure you want to delete this entry?","js")."')) {".get2post("$scriptname?action=delusergroup&amp;ugid=$ugid")."}\" "
@@ -112,7 +114,7 @@
 }
 
 
-if ($action == "adduser" || $action=="deluser" || $action == "moduser" || $action == "userrights"  || $action == "usertemplates")
+if ($action == "adduser" || $action=="deluser" || $action == "moduser" || $action == "userrights"  || $action == "usertemplates" || $action == "usergrouprights")
 {
 	include("usercontrol.php");
 }
@@ -374,7 +376,90 @@
 	}
 }	// if
 
+if ($action == "setusergrouprights") // aggiungo da Giorgio Riva
+{
+	if (isset($postuserid) && $postuserid)
+	{
+		$squery = "SELECT uid FROM {$dbprefix}users WHERE uid=$postuserid";
+		$sresult = $connect->Execute($squery);//Checked
+		$sresultcount = $sresult->RecordCount();
+	}
+	else
+	{
+		include("access_denied.php");
+	}
+	
+	// RELIABLY CHECK MY RIGHTS
+	if ( $sresultcount >  0 && $_SESSION['loginID'] != $postuserid )
+	{
+		//User can or can't manage this group
+		$uggroupmanager = getusergroupmanager($ugid);
+		$uggroupowner = getusergroupowner($postusergroupid);
+	
+		if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupmanager || $egurow['uid'] == $uggroupowner)
+		{
+			$usergroupsummary .= "<table width='100%' border='0'>\n<tr><td colspan='2' class='header' align='center'>\n"
+			. "".$clang->gT("Set User Rights").": ".htmlspecialchars(sanitize_user($_POST['user']))."</td></tr>\n";
+			
+			$squery = "SELECT * FROM {$dbprefix}user_groups_rights WHERE uid=$postuserid AND ugid=$postusergroupid";
+			$sresult = $connect->Execute($squery); //Checked
+			$usr = $sresult->FetchRow();
+		
+			// manage group checkbox if superadmin or group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $crow['owner_id'])
+			{
+				$usergroupsummary .= "<th align='center'>".$clang->gT("Manage Group")."</th>\n";
+			}
+			// edit labelset checkbox if superadmin, group manager or group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupmanager || $egurow['uid'] == $uggroupowner)
+			{
+				$usergroupsummary .= "<th align='center'>".$clang->gT("Manage Labels")."</th>\n";
+			}
 
+			$usergroupsummary .="<th></th>\n</tr>\n"
+			."<tr><form method='post' action='$scriptname'></tr>"
+			."<form action='$scriptname' method='post'>\n";
+			//content
+			
+			// manage group checkbox if superadmin or group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupowner)
+			{
+				$usergroupsummary .= "<td align='center'><input type=\"checkbox\"  class=\"checkboxbtn\" name=\"manage_group\" id=\"manage_group\" value=\"manage_group\"";
+				if($usr['manage_group']) {
+					$usergroupsummary .= " checked='checked' ";
+				}
+				$usergroupsummary .=" /></td>\n";
+			}
+			// edit labelset checkbox if superadmin, group manager or group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupmanager || $egurow['uid'] == $uggroupowner)
+			{
+				$usergroupsummary .= "<td align='center'><input type=\"checkbox\"  class=\"checkboxbtn\" name=\"edit_labelset\" id=\"edit_labelset\" value=\"edit_labelset\"";
+				if($usr['edit_labelset']) {
+					$usergroupsummary .= " checked='checked' ";
+				}
+				$usergroupsummary .=" /></td>\n";
+			}
+
+			$usergroupsummary .= "<tr><form method='post' action='$scriptname'></tr>"	// added by Dennis
+			."\n<tr><td colspan='2' align='center'>"
+			."<input type='submit' value='".$clang->gT("Save Now")."' />"
+			."<input type='hidden' name='action' value='usergrouprights' />"
+			."<input type='hidden' name='uid' value='{$postuserid}' /></td></tr>"
+			."<input type='hidden' name='ugid' value='{$postusergroupid}' /></td></tr>"
+			."</form>"
+			. "</table>\n";
+		}	// if
+		else
+		{
+			include("access_denied.php");
+		}
+	}	// if
+	else
+	{
+		include("access_denied.php");
+	}
+}	// if
+
 if($action == "setasadminchild")
 {
 	// Set user as child of ADMIN FOR 
@@ -645,39 +730,47 @@
 
 if ($action == "delusergroup")
 {
-		if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1)
+	if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $grow['owner_id'])
 	{
-	$usersummary = "<br /><strong>".$clang->gT("Deleting User Group")."</strong><br />\n";
+		$usersummary = "<br /><strong>".$clang->gT("Deleting User Group")."</strong><br />\n";
 
-	if(!empty($postusergroupid) && ($postusergroupid > -1))
-	{
-		$query = "SELECT ugid, name, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = {$postusergroupid} AND owner_id = ".$_SESSION['loginID'];
-		$result = db_select_limit_assoc($query, 1);
-		if($result->RecordCount() > 0)
+		if(!empty($postusergroupid) && ($postusergroupid > -1))
 		{
-			$row = $result->FetchRow();
+			$query = "SELECT ugid, name, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = {$postusergroupid}";
+			$result = db_select_limit_assoc($query, 1);
+			if($result->RecordCount() > 0)
+			{
+				$row = $result->FetchRow();
 
-			$remquery = "DELETE FROM ".db_table_name('user_groups')." WHERE ugid = {$postusergroupid} AND owner_id = {$_SESSION['loginID']}";
-			if($connect->Execute($remquery)) //Checked
-			{
-				$usersummary .= "<br />".$clang->gT("Group Name").": {$row['name']}<br />\n";
+				$remquery = "DELETE FROM ".db_table_name('user_groups')." WHERE ugid = {$postusergroupid} AND owner_id = {$_SESSION['loginID']}";
+				if($connect->Execute($remquery)) //Checked
+				{
+					// remove any entry from user_in_groups table
+					$uigremquery = "DELETE FROM ".db_table_name('user_in_groups')." WHERE ugid = {$postusergroupid}";
+					$connect->Execute($uigremquery);
+					
+					// update any labelset associated to this group, assigning to the uncategorized group
+					$lremquery = "UPDATE ".db_table_name('labelsets')." SET ugid=0 WHERE ugid = {$postusergroupid}";
+					$connect->Execute($lremquery);
+				
+					$usersummary .= "<br />".$clang->gT("Group Name").": {$row['name']}<br />\n";
+				}
+				else
+				{
+					$usersummary .= "<br />".$clang->gT("Could not delete user group.")."<br />\n";
+				}
 			}
 			else
 			{
-				$usersummary .= "<br />".$clang->gT("Could not delete user group.")."<br />\n";
+				include("access_denied.php");
 			}
 		}
 		else
 		{
-			include("access_denied.php");
+			$usersummary .= "<br />".$clang->gT("Could not delete user group. No group selected.")."<br />\n";
 		}
+		$usersummary .= "<br /><a href='$scriptname?action=editusergroups'>".$clang->gT("Continue")."</a><br />&nbsp;\n";
 	}
-	else
-	{
-		$usersummary .= "<br />".$clang->gT("Could not delete user group. No group selected.")."<br />\n";
-	}
-	$usersummary .= "<br /><a href='$scriptname?action=editusergroups'>".$clang->gT("Continue")."</a><br />&nbsp;\n";
-	}
 }
 
 if ($action == "usergroupindb")
@@ -696,6 +789,12 @@
 			$ugid = addUserGroupInDB($db_group_name, $db_group_description);
 			if($ugid > 0)
 			{
+				//array containing user rights
+				$rights = array();
+				$rights['manage_group']=1;
+				$rights['edit_labelset']=1;
+				$ugr = setusergrouprights($_SESSION['loginID'],$ugid,$rights);
+			
 				$usersummary .= "<br />".$clang->gT("Group Name").": ".$html_group_name."<br />\n";
 	
 				if(isset($db_group_description) && strlen($db_group_description) > 0)
@@ -865,6 +964,9 @@
 				$result2 = db_select_limit_assoc($query2, 1);
 				$row2 = $result2->FetchRow();
 	
+				//Get group manager's id
+				$uggroupmanager = getusergroupmanager($ugid);
+	
 				$row = 1;
 				$usergroupentries='';
 				while ($egurow = $eguresult->FetchRow())
@@ -891,7 +993,18 @@
 					$usergroupentries .= "<tr class='$bgcc'>\n"
                         . "<td align='center'>\n";
     
-                    if($_SESSION['USER_RIGHT_SUPERADMIN'] == 1)
+
+                                       // Edit rigths button. Visible only for superadmin, group managers and group owner
+                                       if($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupmanager || $egurow['uid'] == $crow['owner_id'])
+                                        {
+                                               $usergroupentries .= "<form method='post' action='$scriptname?action=setusergrouprights&amp;ugid=$ugid'>"
+                                               ." <input type='submit' value='".$clang->gT("Set User Rights")."' />"
+                                               ." <input type='hidden' name='user' value='{$egurow['users_name']}' />"
+                                               ." <input name='uid' type='hidden' value='{$egurow['uid']}' />"
+                                               ." <input name='ugid' type='hidden' value='{$ugid}' /></form>";
+                                       }
+                                       //Delete button. Visible only for superadmin, group managers and group owner.
+                                       if($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $egurow['uid'] == $uggroupmanager || $egurow['uid'] == $crow['owner_id'])
                     {
                         $usergroupentries .= "<form method='post' action='$scriptname?action=deleteuserfromgroup&amp;ugid=$ugid'>"
                         ." <input type='image' src='$imagefiles/token_delete.png' alt='".$clang->gT("Delete this user group")."' onclick='return confirm(\"".$clang->gT("Are you sure you want to delete this entry?","js")."\")' />"
@@ -910,7 +1023,7 @@
 	            if (isset($usergroupentries)) {$usergroupsummary .= $usergroupentries;};
                 $usergroupsummary .= '</tbody></table>';                      
 	
-				if(isset($row2['ugid']))
+				if($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $crow['owner_id'] || $_SESSION['loginID'] == $uggroupmanager)
 				{
 					$usergroupsummary .= "<form action='$scriptname?ugid={$ugid}' method='post'>\n"
 					. "<table class='users'><tbody><tr><td>&nbsp;</td>\n"
@@ -938,19 +1051,25 @@
 
 if($action == "deleteuserfromgroup")
 {
-	if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1)
+	$uggroupowner = getusergroupowner($ugid);
+	$uggroupmanager = getusergroupmanager($ugid);
+	//Only if current user is superadmin, group owner or group manager
+	if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $uggroupowner || $_SESSION['loginID'] == $uggroupmanager)
 	{
 		$ugid = $postusergroupid;
 		$uid = $postuserid;
 		$usersummary = "<br /><strong>".$clang->gT("Delete User")."</strong><br />\n";
 	
-		$query = "SELECT ugid, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = ".$ugid." AND ((owner_id = ".$_SESSION['loginID']." AND owner_id != ".$uid.") OR (owner_id != ".$_SESSION['loginID']." AND $uid = ".$_SESSION['loginID']."))";
-		$result = db_execute_assoc($query); //Checked
-		if($result->RecordCount() > 0)
+		// $query = "SELECT ugid, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = ".$ugid." AND ((owner_id = ".$_SESSION['loginID']." AND owner_id != ".$uid.") OR (owner_id != ".$_SESSION['loginID']." AND $uid = ".$_SESSION['loginID']."))";
+		// $result = db_execute_assoc($query); //Checked
+		if($postuserid != $uggroupowner)
 		{
 			$remquery = "DELETE FROM ".db_table_name('user_in_groups')." WHERE ugid = {$ugid} AND uid = {$uid}";
 			if($connect->Execute($remquery)) //Checked
 			{
+				$ugrremquery = "DELETE FROM ".db_table_name('user_groups_rights')." WHERE ugid = {$ugid} AND uid = {$uid}";
+				$connect->Execute($ugrremquery);
+			
 				$usersummary .= "<br />".$clang->gT("Username").": ".sanitize_xss_string(strip_tags($_POST['user']))."<br />\n";
 			}
 			else
@@ -983,20 +1102,30 @@
 if($action == "addusertogroup")
 { 
 	$ugid=returnglobal('ugid');
-    if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1)
+    $uggroupowner = getusergroupowner($ugid);
+	$uggroupmanager = getusergroupmanager($ugid);
+	//Only if current user is superadmin, group owner or group manager
+    if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $uggroupowner || $_SESSION['loginID'] == $uggroupmanager)
 	{
 		$addsummary = "<br /><strong>".$clang->gT("Adding User to group")."...</strong><br />\n";
 	
-		$query = "SELECT ugid, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = {$ugid} AND owner_id = ".$_SESSION['loginID']." AND owner_id != ".$postuserid;
-		$result = db_execute_assoc($query); //Checked
-		if($result->RecordCount() > 0)
+		// $query = "SELECT ugid, owner_id FROM ".db_table_name('user_groups')." WHERE ugid = {$ugid} AND owner_id = ".$_SESSION['loginID']." AND owner_id != ".$postuserid;
+		// $result = db_execute_assoc($query); //Checked
+		if($postuserid != $uggroupowner)
 		{
 			if($postuserid > 0)
 			{
 				$isrquery = "INSERT INTO {$dbprefix}user_in_groups VALUES({$ugid},{$postuserid})";
 				$isrresult = $connect->Execute($isrquery); //Checked
 	
-				if($isrresult)
+				//array containing user rights
+				$rights = array();
+				//new users have no rights
+				$rights['manage_group']=0;
+				$rights['edit_labelset']=0;
+				$ugrresult = setusergrouprights($postuserid,$ugid,$rights);
+	
+				if($isrresult && $ugrresult)
 				{
 					$addsummary .= "<br />".$clang->gT("User added.")."<br />\n";
 				}
Index: admin/admin.php
===================================================================
--- admin/admin.php	(revision 7870)
+++ admin/admin.php	(working copy)
@@ -477,11 +477,11 @@
 
       
  if ($action=='adduser' || $action=='deluser' || $action=='moduser' || $action=='setusertemplates' || $action=='usertemplates' ||                                        //Still to check 
-     $action=='userrights' || $action=='modifyuser' || $action=='editusers' || 
+     $action=='userrights'|| $action=='usergrouprights' || $action=='modifyuser' || $action=='editusers' || 
      $action=='addusergroup' || $action=='editusergroup' || $action=='mailusergroup' ||
      $action=='delusergroup' || $action=='usergroupindb' || $action=='mailsendusergroup' || 
      $action=='editusergroupindb' || $action=='editusergroups' || $action=='deleteuserfromgroup' ||
-     $action=='addusertogroup' || $action=='setuserrights' || $action=='setasadminchild') 
+     $action=='addusertogroup' || $action=='setuserrights' || $action=='setasadminchild' || $action=='setusergrouprights') 
  
  {
      include ('userrighthandling.php');
Index: admin/labels.php
===================================================================
--- admin/labels.php	(revision 7870)
+++ admin/labels.php	(working copy)
@@ -78,17 +78,27 @@
 	$labelsoutput.= "<option value=''";
 	if (!isset($lid) || $lid<1) {$labelsoutput.= " selected='selected'";}
 	$labelsoutput.= ">".$clang->gT("Please Choose...")."</option>\n";
-	$labelsets=getlabelsets();
-	if (count($labelsets)>0)
+	// only labelsets editable will be displayed
+	$labelsets=getlabelsetseditable($_SESSION['loginID'], $_SESSION['USER_RIGHT_SUPERADMIN']);
+	$group = "";
+	if (count($labelsets) > 0)
 	{
 		foreach ($labelsets as $lb)
 		{
-			$labelsoutput.="<option value='admin.php?action=labels&amp;lid={$lb[0]}'";
-			if ($lb[0] == $lid) {$labelsoutput.= " selected='selected'";}
-			$labelsoutput.= ">{$lb[1]}</option>\n";
+			if ($lb['group_name'] != $group)
+			{
+				if ($group != "")
+					$labelsoutput.="</optgroup>";
+				$group = $lb['group_name'];
+				$labelsoutput.="<optgroup label='".$group."'>";
+			}
+			$labelsoutput.="<option value='admin.php?action=labels&amp;lid={$lb['lid']}'";
+			if ($lb['lid'] == $lid) {$labelsoutput.= " selected='selected'";}
+			$labelsoutput.= ">{$lb['labelset_name']}</option>\n";
 		}
 	}
 	
+	$labelsoutput.= "\t</optgroup>\n";	
 	$labelsoutput.= "\t</select>\n"
     ."<a href=\"#\" onclick=\"window.open('admin.php?action=newlabelset', '_top')\"" 
     ."title=\"".$clang->gTview("Add new label set")."\">"
@@ -114,9 +124,9 @@
 	{
 		if ($action == "editlabelset")
 		{
-         	$query = "SELECT label_name,".db_table_name('labelsets').".lid, languages FROM ".db_table_name('labelsets')." WHERE lid=".$lid;
+         	$query = "SELECT label_name,".db_table_name('labelsets').".lid, languages, ugid FROM ".db_table_name('labelsets')." WHERE lid=".$lid;
 			$result=db_execute_assoc($query);
-			while ($row=$result->FetchRow()) {$lbname=$row['label_name']; $lblid=$row['lid']; $langids=$row['languages'];}
+			while ($row=$result->FetchRow()) {$lbname=$row['label_name']; $lblid=$row['lid']; $langids=$row['languages']; $lbusergroup=$row['ugid'];}
 		}
 		$labelsoutput.="<table width='100%' class='form2columns'>\n"
 		."\t<tr>\n"
@@ -166,6 +176,27 @@
 					$labelsoutput.= ">".$langname['description']." - ".$langname['nativedescription']."</option>\n";
 				}
 			}
+			
+		$labelsoutput.= "\t</select></td></tr>\n"	
+		. "\t<tr><td><strong>".$clang->gT("Groups").":</strong></td>\n"
+		. "<td><select id='groups' name='groups'>";
+		
+		$groups = getusergroups($_SESSION['loginID']);
+		
+		if (count($groups) > 0)
+		{
+			foreach ($groups as $gp)
+			{
+				$labelsoutput.="<option value='{$gp['ugid']}'";
+				if ($action == "editlabelset")
+				{
+					if ($gp['ugid'] == $lbusergroup) {
+						$labelsoutput.= " selected='selected'";
+					}
+				}
+				$labelsoutput.= ">{$gp['group_name']}</option>\n";
+			}
+		}
 
 		$labelsoutput.= "\t</select></td></tr><tr>\n"
 		."<td></td><td></td>\n"
@@ -540,6 +571,11 @@
 	{
 		$postlabel_name=sanitize_labelname($_POST['label_name']);
 	}
+	
+	if (isset($_POST['groups']))
+	{
+		$postugid=sanitize_int($_POST['groups']);
+	}
 
 	$newlanidarray=explode(" ",trim($postlanguageids));
 
@@ -602,7 +638,7 @@
 	}
 
 	// Update the labelset itself
-	$query = "UPDATE ".db_table_name('labelsets')." SET label_name={$postlabel_name}, languages={$postlanguageids} WHERE lid=$lid";
+	$query = "UPDATE ".db_table_name('labelsets')." SET label_name={$postlabel_name}, languages={$postlanguageids}, ugid={$postugid} WHERE lid=$lid";
 	if (!$result = $connect->Execute($query))
 	{
 		$labelsoutput.= "<script type=\"text/javascript\">\n<!--\n alert(\"".$clang->gT("Update of Label Set failed","js")." - ".$query." - ".$connect->ErrorMsg()."\")\n //-->\n</script>\n";
@@ -650,11 +686,16 @@
 	{
 		$postlabel_name=sanitize_labelname($_POST['label_name']);
 	}
+	
+	if (isset($_POST['groups']))
+	{
+		$postugid=sanitize_int($_POST['groups']);
+	}
 
 	$postlabel_name = db_quoteall($postlabel_name,true);
 	$postlanguageids = db_quoteall($postlanguageids,true);
 
-	$query = "INSERT INTO ".db_table_name('labelsets')." (label_name,languages) VALUES ({$postlabel_name},{$postlanguageids})";
+	$query = "INSERT INTO ".db_table_name('labelsets')." (label_name,languages,ugid) VALUES ({$postlabel_name},{$postlanguageids},{$postugid})";
 	if (!$result = $connect->Execute($query))
 	{
 		$labelsoutput.= "<script type=\"text/javascript\">\n<!--\n alert(\"".$clang->gT("Insert of Label Set failed","js")." - ".$query." - ".$connect->ErrorMsg()."\")\n //-->\n</script>\n";
Index: admin/install/create-mysql.sql
===================================================================
--- admin/install/create-mysql.sql	(revision 7870)
+++ admin/install/create-mysql.sql	(working copy)
@@ -71,6 +71,7 @@
   `lid` int(11) NOT NULL auto_increment,
   `label_name` varchar(100) NOT NULL default '',
   `languages` varchar(200) default 'en',
+  `ugid` int(11) NOT NULL default 0,
   PRIMARY KEY  (`lid`)
 ) ENGINE=$databasetabletype AUTO_INCREMENT=1 CHARACTER SET utf8 COLLATE utf8_unicode_ci;
 
@@ -267,8 +268,14 @@
      PRIMARY KEY  (`ugid`,`uid`)	
 ) ENGINE=$databasetabletype CHARACTER SET utf8 COLLATE utf8_unicode_ci;
 
+CREATE TABLE `prefix_user_groups_rights` (
+  `ugid` int(10) unsigned NOT NULL,
+  `uid` int(10) unsigned NOT NULL,
+  `manage_group` tinyint(1) NOT NULL default '0',
+  `edit_labelset` tinyint(1) NOT NULL default '0',
+  PRIMARY KEY  (`ugid`,`uid`)
+) ENGINE=$databasetabletype CHARACTER SET utf8 COLLATE utf8_unicode_ci;
 
-
 CREATE TABLE `prefix_users` (
   `uid` int(11) NOT NULL auto_increment PRIMARY KEY,
   `users_name` varchar(64) NOT NULL UNIQUE default '',
Index: admin/install/create-postgres.sql
===================================================================
--- admin/install/create-postgres.sql	(revision 7870)
+++ admin/install/create-postgres.sql	(working copy)
@@ -104,7 +104,8 @@
 CREATE TABLE prefix_labelsets (
     lid serial NOT NULL,
     label_name character varying(100) DEFAULT ''::character varying NOT NULL,
-    languages character varying(200) DEFAULT 'en'::character varying
+    languages character varying(200) DEFAULT 'en'::character varying,
+    ugid integer DEFAULT 0 NOT NULL
 );
 
 
@@ -327,6 +328,14 @@
     uid integer NOT NULL
 );
 
+CREATE TABLE prefix_user_groups_rights (
+    ugid integer NOT NULL,
+    uid integer NOT NULL,
+    manage_group integer DEFAULT 0 NOT NULL,
+    edit_labelset integer DEFAULT 0 NOT NULL
+);
+
+
 --
 -- Name: prefix_users; Type: TABLE; Schema: public; Owner: postgres; Tablespace: 
 --
Index: admin/install/create-mssql.sql
===================================================================
--- admin/install/create-mssql.sql	(revision 7870)
+++ admin/install/create-mssql.sql	(working copy)
@@ -138,6 +138,7 @@
   [lid] INT NOT NULL IDENTITY (1,1),
   [label_name] VARCHAR(100) NOT NULL default '',
   [languages] VARCHAR(200) default 'en',
+  [ugid] INT NOT NULL default '0',
   PRIMARY KEY  ([lid])
 ) 
 ;
@@ -337,6 +338,15 @@
 ) 
 ;
 
+CREATE TABLE [prefix_user_groups_rights] (
+      [ugid] INT NOT NULL,
+      [uid] INT NOT NULL,
+      [manage_group] TINYINT NOT NULL defualt '0',
+      [edit_labelset] TINYINT NOT NULL default '0'
+)
+;
+
+
 -- 
 -- Table structure for table [user_in_groups]
 -- 
Index: admin/usercontrol.php
===================================================================
--- admin/usercontrol.php	(revision 7870)
+++ admin/usercontrol.php	(working copy)
@@ -448,6 +448,14 @@
 				// Delete user rights
 				$dquery="DELETE FROM {$dbprefix}surveys_rights WHERE uid=".$postuserid;
 				$dresult=$connect->Execute($dquery); //Checked
+				
+				//Delete user from his usergroups
+				$dquery="DELETE FROM {$dbprefix}user_in_groups WHERE uid=".$postuserid;
+				$dresult=$connect->Execute($dquery);
+				
+				//Delete user group rights
+				$dquery="DELETE FROM {$dbprefix}user_groups_rights WHERE uid=".$postuserid;
+				$dresult=$connect->Execute($dquery);
 
 				if($postuserid == $_SESSION['loginID']) killSession();	// user deleted himself
 
@@ -615,6 +623,58 @@
 	}
 }
 
+elseif ($action == "usergrouprights")
+{
+	$addsummary = "<br /><strong>".$clang->gT("Set User Rights")."</strong><br />\n";
+
+	$uggroupowner = getusergroupowner($postusergroupid);
+	$uggroupmanager = getusergroupmanager($postusergroupid);
+	
+	// A user can't modify his own rights ;-)
+	if($postuserid != $_SESSION['loginID'])
+	{
+		$squery = "SELECT uid FROM {$dbprefix}users WHERE uid=$postuserid AND parent_id=".$_SESSION['loginID'];
+		$sresult = $connect->Execute($squery); // Checked
+		$sresultcount = $sresult->RecordCount();
+
+		//array containing user rights
+		$rights = array();
+		$rights['manage_group']=0;
+		$rights['edit_labelset']=0;
+		
+		// only superadmin, group manager and group owner can change user permission for groups
+		if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $uggroupmanager || $_SESSION['loginID'] == uggroupowner)
+		{
+			// manage group right, avaible only for superadmin and group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == uggroupowner)
+			{
+				if(isset($_POST['manage_group']))
+					$rights['manage_group']=1;
+			}
+			
+			// edit labelset right, avaible only for superadmin, group manager and group owner
+			if ($_SESSION['USER_RIGHT_SUPERADMIN'] == 1 || $_SESSION['loginID'] == $uggroupmanager || $_SESSION['loginID'] == uggroupowner)
+			{
+				if(isset($_POST['edit_labelset']))
+					$rights['edit_labelset']=1;
+			}
+			
+			if ($postuserid<>1) setusergrouprights($postuserid, $postusergroupid, $rights);
+			$addsummary .= "<br />".$clang->gT("Update user rights successful.")."<br />\n";
+			$addsummary .= "<br /><br /><a href='$scriptname?action=editusergroups&ugid=$postusergroupid'>".$clang->gT("Continue")."</a><br />&nbsp;\n";
+		}
+		else
+		{
+			include("access_denied.php");
+		}
+	}
+	else
+	{
+		$addsummary .= "<br />".$clang->gT("You are not allowed to change your own rights!")."<br />\n";
+		$addsummary .= "<br /><br /><a href='$scriptname?action=editusergroups&ugid==$postusergroupid'>".$clang->gT("Continue")."</a><br />&nbsp;\n";
+	}
+}
+
 elseif ($action == "usertemplates")
 {
       $addsummary = "<div class='header'>".$clang->gT("Set Template Rights")."</div><p>\n";
Index: admin/update/upgrade-mysql.php
===================================================================
--- admin/update/upgrade-mysql.php	(revision 7870)
+++ admin/update/upgrade-mysql.php	(working copy)
@@ -335,6 +335,18 @@
 	    modify_database("", "ALTER TABLE `prefix_surveys` ADD `tokenlength` tinyint(2) default '15'"); echo $modifyoutput; flush();
         modify_database("", "UPDATE `prefix_settings_global` SET `stg_value`='141' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
 	}
+	if ($oldversion < 142)
+	{
+		modify_database("", "ALTER TABLE `prefix_labelsets` ADD `ugid` int(11) NOT NULL default 0"); echo $modifyoutput; flush();
+		modify_database("", "CREATE TABLE `prefix_user_groups_rights` (
+			`ugid` int(10) unsigned NOT NULL,
+			`uid` int(10) unsigned NOT NULL,
+			`manage_group` tinyint(1) NOT NULL default '0',
+			`edit_labelset` tinyint(1) NOT NULL default '0',
+			PRIMARY KEY  (`ugid`,`uid`)
+			) ENGINE=$databasetabletype CHARACTER SET utf8 COLLATE utf8_unicode_ci;"); echo $modifyoutput; flush();
+		modify_database("", "UPDATE `prefix_settings_global` SET `stg_value`='142' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
+	}
 	
     return true;
 }
@@ -500,4 +512,4 @@
                 }
             }
         }
-}
\ No newline at end of file
+}
Index: admin/update/upgrade-postgres.php
===================================================================
--- admin/update/upgrade-postgres.php	(revision 7870)
+++ admin/update/upgrade-postgres.php	(working copy)
@@ -174,8 +174,19 @@
 	    modify_database("", "ALTER TABLE prefix_surveys ADD \"tokenlength\" TEXT"); echo $modifyoutput; flush();
         modify_database("", "UPDATE prefix_settings_global SET stg_value='141' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
 	}
-	
 
+	if ($oldversion < 142)
+	{
+		modify_database("", "ALTER TABLE 'prefix_labelsets' ADD ugid integer DEFAULT 0 NOT NULL"); echo $modifyoutput; flush();
+		modify_database("", "CREATE TABLE prefix_user_groups_rights (
+							ugid integer NOT NULL,
+							uid integer NOT NULL,
+							manage_group integer DEFAULT 0 NOT NULL,
+							edit_labelset integer DEFAULT 0 NOT NULL
+						);"); echo $modifyoutput; flush();
+        modify_database("", "UPDATE prefix_settings_global SET stg_value='142' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
+	}
+
     return true;
 }
 
Index: admin/update/upgrade-mssql.php
===================================================================
--- admin/update/upgrade-mssql.php	(revision 7870)
+++ admin/update/upgrade-mssql.php	(working copy)
@@ -348,6 +348,18 @@
         modify_database("", "UPDATE [prefix_settings_global] SET [stg_value]='141' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
 	}
 
+	if ($oldversion < 142) 
+	{
+		modify_database("", "ALTER TABLE [prefix_labelsets] ADD [ugid] INT NOT NULL default '0'"); echo $modifyoutput; flush();
+		modify_database("", "CREATE TABLE [prefix_user_groups_rights] (
+			[ugid] INT NOT NULL,
+			[uid] INT NOT NULL,
+			[manage_group] TINYINT NOT NULL defualt '0',
+			[edit_labelset] TINYINT NOT NULL default '0'
+				);"); echo $modifyoutput; flush();
+		modify_database("", "UPDATE [prefix_settings_global] SET [stg_value]='141' WHERE stg_name='DBVersion'"); echo $modifyoutput; flush();
+	}
+
     return true;
 }
 
Patch-7870.diff (34,564 bytes)   
lemeur

lemeur

2009-11-11 00:46

developer   ~10057

@Kemmotar,
You'll find atatched the resulting patch as I have integrated it to the dev branch.

However, after some tests and a great discussion in the dev team it has not been accepted because it would make permission management too tricky and not consisten with what existed in previous versions.

Another option may be used in the future: mostly using the labelsets as a template which would be copied/linked locally when used in questions.

I assign this ticket back to Carsten then.

lemeur

lemeur

2009-11-11 00:47

developer   ~10058

Carsten,
What should we do with this ticket now ?
Move it to feature request ?

Kemmotar

Kemmotar

2009-11-11 15:23

reporter   ~10063

Oh, I'm regret for this decision. Is there a possibility for a future integration? Maybe with some changes.

I'll apply it on our installation anyway, because we need these new features.

c_schmitz

c_schmitz

2009-11-11 16:56

administrator   ~10065

Kenmotar,

Thank you for your patch and I am sorry that we had to deny it.
I wish people would contact us before they start implementing new things to avoid such disappointments.
If you are interested to work in the project and rework label sets so it satisfies yours and our needs, please get in touch with me at carsten.schmitz (at) limesurvey.org or on IRC.

lemeur

lemeur

2009-11-11 16:58

developer   ~10066

Last edited: 2009-11-11 17:00

Hi Kemmotar,

I'm very sorry, you prove great ability by creating this fix, and I must admit the feature itself is interresting. However it is very confusing for the end user: the rights are at the group level, wether they are defined at the user level for all other aspects.

I let Carsten reply as far as a possibility for a future integration.
==> Which he as done by submitting a message just before me ;-)

Kemmotar

Kemmotar

2009-11-12 16:11

reporter   ~10080

Ok, I discussed about it with my office manager. Carsten, you'll receive an email very soon. ;)

c_schmitz

c_schmitz

2010-03-13 16:17

administrator   ~11323

Keeping patch as workaround. Won't be implemented.

Issue History

Date Modified Username Field Change
2009-10-21 15:03 Mazi New Issue
2009-10-21 15:56 Mazi Project Development => Bug reports
2009-10-28 10:27 Kemmotar Note Added: 09886
2009-10-28 10:31 Kemmotar Note Edited: 09886
2009-10-28 10:32 Kemmotar Note Edited: 09886
2009-10-28 10:33 Kemmotar Note Edited: 09886
2009-10-28 10:35 Kemmotar Note Edited: 09886
2009-10-28 11:38 user372 Note Added: 09887
2009-11-02 17:36 Kemmotar File Added: 03788 New label set handling.diff
2009-11-02 17:38 Kemmotar Note Added: 09958
2009-11-02 18:19 user372 Note Added: 09959
2009-11-02 18:19 user372 Status new => assigned
2009-11-02 18:19 user372 Assigned To => c_schmitz
2009-11-03 22:45 lemeur Assigned To c_schmitz => lemeur
2009-11-06 22:59 lemeur File Added: PATCH-3788.diff
2009-11-06 23:04 lemeur Note Added: 09983
2009-11-06 23:04 lemeur Status assigned => feedback
2009-11-09 11:09 Kemmotar Note Added: 10022
2009-11-09 11:26 lemeur File Added: patch-3788-rev7860.diff
2009-11-09 11:28 lemeur Note Added: 10023
2009-11-09 15:00 Kemmotar Note Added: 10026
2009-11-09 15:07 Kemmotar File Added: database-update-PATCH-revs7863.patch
2009-11-09 17:08 lemeur Note Added: 10030
2009-11-11 00:39 lemeur File Deleted: 03788 New label set handling.diff
2009-11-11 00:39 lemeur File Deleted: PATCH-3788.diff
2009-11-11 00:39 lemeur File Deleted: patch-3788-rev7860.diff
2009-11-11 00:39 lemeur File Deleted: database-update-PATCH-revs7863.patch
2009-11-11 00:39 lemeur File Added: Patch-7870.diff
2009-11-11 00:46 lemeur Note Added: 10057
2009-11-11 00:47 lemeur Status feedback => assigned
2009-11-11 00:47 lemeur Assigned To lemeur => c_schmitz
2009-11-11 00:47 lemeur Note Added: 10058
2009-11-11 00:47 lemeur Status assigned => new
2009-11-11 15:23 Kemmotar Note Added: 10063
2009-11-11 16:56 c_schmitz Note Added: 10065
2009-11-11 16:58 lemeur Note Added: 10066
2009-11-11 17:00 lemeur Note Edited: 10066
2009-11-11 22:49 c_schmitz Assigned To c_schmitz =>
2009-11-11 22:49 c_schmitz Project Bug reports => User patches
2009-11-12 16:11 Kemmotar Note Added: 10080
2009-11-22 21:27 c_schmitz Status new => acknowledged
2010-03-13 16:17 c_schmitz Note Added: 11323
2010-03-13 16:17 c_schmitz Status acknowledged => confirmed
2010-03-14 00:04 c_schmitz Relationship added related to 04075
2012-06-21 13:33 c_schmitz Priority none => normal