Commit cc6510fec12e535219586ce16d9cd05748fd4535

Authored by bshuttle
1 parent 3189d37e

- add role-allocations

- ensure that workflow and permission respect role-based allocations.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4454 c91229c3-7414-0410-bfa2-8a42b809f60b
config/tableMappings.inc
... ... @@ -142,4 +142,5 @@ $default->permission_dynamic_assignments_table = 'permission_dynamic_assignments
142 142 $default->notifications_table = "notifications";
143 143 $default->authentication_sources_table = "authentication_sources";
144 144 $default->dashlet_disable_table = "dashlet_disables";
  145 +$default->role_allocations_table = "role_allocations";
145 146 ?>
... ...
lib/permissions/permissionutil.inc.php
... ... @@ -10,6 +10,7 @@ require_once(KT_LIB_DIR . "/permissions/permissionlookupassignment.inc.php");
10 10 require_once(KT_LIB_DIR . "/permissions/permissionobject.inc.php");
11 11 require_once(KT_LIB_DIR . "/permissions/permissiondynamiccondition.inc.php");
12 12 require_once(KT_LIB_DIR . "/groups/GroupUtil.php");
  13 +require_once(KT_LIB_DIR . "/roles/roleallocation.inc.php");
13 14  
14 15 class KTPermissionUtil {
15 16 // {{{ generateDescriptor
... ... @@ -182,9 +183,11 @@ class KTPermissionUtil {
182 183 $oPD = KTPermissionDescriptor::get($oPA->getPermissionDescriptorID());
183 184 $aGroupIDs = $oPD->getGroups();
184 185 $aUserIDs = array();
  186 + $aRoleIDs = $oPD->getRoles();
185 187 $aAllowed = array(
186 188 "group" => $aGroupIDs,
187 189 "user" => $aUserIDs,
  190 + "role" => $aRoleIDs,
188 191 );
189 192 $aMapPermAllowed[$oPA->getPermissionID()] = $aAllowed;
190 193 }
... ... @@ -207,6 +210,31 @@ class KTPermissionUtil {
207 210 }
208 211 }
209 212  
  213 + // if we have roles: nearest folder.
  214 + $iRoleSourceFolder = null;
  215 + if (is_a($oFolderOrDocument, 'Document')) { $iRoleSourceFolder = $oFolderOrDocument->getFolderID(); }
  216 + else { $iRoleSourceFolder = $oFolderOrDocument->getId(); }
  217 +
  218 + // very minor perf win: map role_id (in context) to PD.
  219 + $_roleCache = array();
  220 +
  221 + foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
  222 + if (array_key_exists('role', $aAllowed)) {
  223 + foreach ($aAllowed['role'] as $iRoleId) {
  224 + // store the PD <-> RoleId map
  225 + if (!array_key_exists($iRoleId, $_roleCache)) {
  226 + $oRoleAllocation =& RoleAllocation::getAllocationsForFolderAndRole($iRoleSourceFolder, $iRoleId);
  227 + $_roleCache[$iRoleId] = $oRoleAllocation;
  228 + }
  229 + // roles are _not_ always assigned (can be null at root)
  230 + if ($_roleCache[$iRoleId] != null) {
  231 + $aAllowed['user'] = array_merge($aAllowed['user'], $_roleCache[$iRoleId]->getUsers());
  232 + $aAllowed['group'] = array_merge($aAllowed['group'], $_roleCache[$iRoleId]->getGroups());
  233 + }
  234 + }
  235 + }
  236 + }
  237 +
210 238 $aMapPermDesc = array();
211 239 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
212 240 $oLookupPD = KTPermissionUtil::getOrCreateDescriptor($aAllowed);
... ...
lib/roles/Role.inc
... ... @@ -21,170 +21,43 @@
21 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 22 *
23 23 * @version $Revision$
24   - * @author Rob Cherry, Jam Warehouse (Pty) Ltd, South Africa
  24 + * @author Brad Shuttleworth, Jam Warehouse (Pty) Ltd, South Africa
25 25 * @package lib.roles
26 26 */
  27 +
  28 +require_once(KT_LIB_DIR . "/ktentity.inc");
  29 +require_once(KT_LIB_DIR . "/util/ktutil.inc");
  30 +
27 31 class Role extends KTEntity {
28 32  
29 33 /** role object primary key */
30 34 var $iId;
31   - /** role name */
32 35 var $sName;
33   - /** is an active user*/
34   - var $bActive;
35   - /** role has document read permission */
36   - var $bCanRead;
37   - /** role has document write */
38   - var $bCanWrite;
39 36  
  37 + var $_aFieldToSelect = array(
  38 + 'iId' => 'id',
  39 + 'sName' => 'name',
  40 + );
40 41  
41   -
42   - /**
43   - * Default constructor
44   - *
45   - * @param String Role name
46   - * @param boolean Role has document read permission
47   - * @param boolean Role has document write permission
48   - *
49   - */
50   - function Role($sNewName = null, $bNewCanRead = false, $bNewCanWrite = false) {
  42 + function Role($sNewName = null, $x=null, $y=null) {
51 43 //object not yet created in database
52 44 $this->iId = -1;
53 45 $this->sName = $sNewName;
54   - $this->bCanRead = $bNewCanRead;
55   - $this->bCanWrite = $bNewCanWrite;
56   - }
57   -
58   - function getName() {
59   - return $this->sName;
60   - }
61   -
62   - function getID() {
63   - return $this->iId;
64   - }
65   -
66   - function getActive() {
67   - return $this->bActive;
68   - }
69   -
70   - function setActive($bNewValue) {
71   - $this->bActive = $bNewValue;
72   - }
73   -
74   - function getReadable() {
75   - return $this->bCanRead;
76   - }
77   -
78   - function setReadable($bNewValue) {
79   - $this->bCanRead = $bNewValue;
80   - }
81   -
82   - function getWriteable() {
83   - return $this->bCanWrite;
84   - }
85   -
86   - function setWriteable($bNewValue) {
87   - $this->bCanWrite = $bNewValue;
88   - }
89   -
90   - function setName($bNewValue) {
91   - $this->sName = $bNewValue;
92 46 }
93 47  
94   - function _fieldValues () {
95   - return array(
  48 + function getName() { return $this->sName; }
  49 + function setName($sNewValue) { $this->sName = $sNewValue; }
  50 +
  51 + function _fieldValues () { return array(
  52 + 'id' => $this->iId,
96 53 'name' => $this->sName,
97   - 'active' => KTUtil::anyToBool($this->bActive),
98   - 'can_read' => KTUtil::anyToBool($this->bCanRead),
99   - 'can_write' => KTUtil::anyToBool($this->bCanWrite),
100 54 );
101 55 }
102 56  
103   - function _table () {
104   - global $default;
105   - return $default->roles_table;
106   - }
107   -
108   - /**
109   - * Delete the current object from the database
110   - *
111   - * @return boolean true on successful deletion, false otherwise and set $_SESSION["errorMessage"]
112   - *
113   - */
114   - function delete() {
115   - global $default, $lang_err_database, $lang_err_object_key;
116   - //only delete the object if it exists in the database
117   - /*
118   - if ($this->iId >= 0) {
119   -
120   - $sql = $default->db;
121   - $query = "SELECT role_id FROM ". $default->groups_folders_approval_table ." WHERE role_id = ?";
122   - $aParams = array($this->iId);
123   - $sql->query(array($query, $aParams));
124   - $rows = $sql->num_rows($sql);
125   -
126   - if ($rows > 0){
127   - $_SESSION["errorMessage"] = "Role::The Role " . $this->sName . " is Assigned to a folder!";
128   - return false;
129   - }
130   - }
131   - */
132   - return parent::delete();
133   - }
134   -
135   - /**
136   - * Static function.
137   - * Given a roles primary key it will create a
138   - * Roles object and populate it with the
139   - * corresponding database values
140   - *
141   - * @return Role populated Role object on successful query, false otherwise and set $_SESSION["errorMessage"]
142   - */
143   - function & get($iRoleID) {
144   - global $default;
145   - $sql = $default->db;
146   - $result = $sql->query(array("SELECT * FROM $default->roles_table WHERE id = ?", $iRoleID));/*ok*/
147   - if ($result) {
148   - if ($sql->next_record()) {
149   - $oRole = & new Role($sql->f("name"), $sql->f("can_read"), $sql->f("can_write"));
150   - $oRole->iId = $iRoleID;
151   - $oRole->bActive = $sql->f("active");
152   - return $oRole;
153   - }
154   - $_SESSION["errorMessage"] = $lang_err_object_not_exist . "id = " . $iRoleID . " table = $default->roles_table";
155   - return false;
156   - }
157   - $_SESSION["errorMessage"] = $lang_err_database;
158   - return false;
159   - }
160   -
161   -/**
162   - * Static function
163   - * Get a list of web documents
164   - *
165   - * @param String Where clause (not required)
166   - *
167   - * @return Array array of Role objects, false otherwise and set $_SESSION["errorMessage"]
168   - */
169   - function getList($sWhereClause = null) {
170   - return KTEntityUtil::getList(Role::_table(), 'Role', $sWhereClause);
171   - }
172   -}
173   -
174   -
175   -
176   -/**
177   -* Static function
178   -*
179   -* Creates a roles object from an array
180   -*
181   -* @param Array Array of parameters. Must match order of parameters in constructor
182   -*
183   -* @return User user object
184   -*/
185   -function & roleCreateFromArray($aParameters) {
186   - $oRole = & new Role($aParameters[0], $aParameters[1], $aParameters[2], $aParameters[3], $aParameters[4], $aParameters[5], $aParameters[6], $aParameters[7], $aParameters[8], $aParameters[9], $aParameters[10]);
187   - return $oRole;
  57 + function _table () { return KTUtil::getTableName('roles'); }
  58 + function & get($iRoleId) { return KTEntityUtil::get('Role', $iRoleId); }
  59 + function & getList($sWhereClause = null) { return KTEntityUtil::getList2('Role', $sWhereClause); }
  60 + function & createFromArray($aOptions) { return KTEntityUtil::createFromArray('Role', $aOptions); }
188 61 }
189 62  
190 63 ?>
... ...
lib/roles/roleallocation.inc.php 0 → 100644
  1 +<?php
  2 +
  3 +require_once(KT_LIB_DIR . "/ktentity.inc");
  4 +require_once(KT_LIB_DIR . "/util/ktutil.inc");
  5 +require_once(KT_LIB_DIR . "/database/dbutil.inc");
  6 +
  7 +require_once(KT_LIB_DIR . "/permissions/permissiondescriptor.inc.php");
  8 +require_once(KT_LIB_DIR . "/permissions/permissionutil.inc.php");
  9 +require_once(KT_LIB_DIR . "/users/User.inc");
  10 +require_once(KT_LIB_DIR . "/groups/Group.inc");
  11 +require_once(KT_LIB_DIR . "/foldermanagement/Folder.inc");
  12 +
  13 +class RoleAllocation extends KTEntity {
  14 +
  15 + /** role object primary key */
  16 + var $iId=-1;
  17 + var $iFolderId;
  18 + var $iRoleId;
  19 + var $iPermissionDescriptorId;
  20 +
  21 + var $_bUsePearError = true;
  22 +
  23 + var $_aFieldToSelect = array(
  24 + 'iId' => 'id',
  25 + 'iRoleId' => 'role_id',
  26 + 'iFolderId' => 'folder_id',
  27 + 'iPermissionDescriptorId' => 'permission_descriptor_id',
  28 + );
  29 +
  30 + function setFolderId($iFolderId) { $this->iFolderId = $iFolderId; }
  31 + function setRoleId($iRoleId) { $this->iRoleId = $iRoleId; }
  32 + function setPermissionDescriptorId($iPermissionDescriptorId) { $this->iPermissionDescriptorId = $iPermissionDescriptorId; }
  33 + function getFolderId() { return $this->iFolderId; }
  34 + function getRoleId() { return $this->iRoleId; }
  35 + function getPermissionDescriptorId() { return $this->iPermissionDescriptorId; }
  36 +
  37 + // aggregate: set (for this alloc) the array('user' => array(), 'group' => array()).
  38 + function setAllowed($aAllowed) {
  39 + $oDescriptor = KTPermissionUtil::getOrCreateDescriptor($aAllowed); // fully done, etc.
  40 + $this->iPermissionDescriptorId = $oDescriptor->getId();
  41 + }
  42 +
  43 + function _fieldValues () { return array(
  44 + 'role_id' => $this->iRoleId,
  45 + 'folder_id' => $this->iFolderId,
  46 + 'permission_descriptor_id' => $this->iPermissionDescriptorId,
  47 + );
  48 + }
  49 +
  50 + /* getAllocationForFolderAndRole($iFolderId, $iRoleId)
  51 + *
  52 + * this is the key function: for a given folder and role,
  53 + * returns either a RoleAllocation object, or null
  54 + * (if there is none). It scans _up_ the hierachy of folders,
  55 + * trying to find the nearest such object with a folder_id
  56 + * in the mapping.
  57 + */
  58 + function & getAllocationsForFolderAndRole($iFolderId, $iRoleId) {
  59 + // FIXME the query we use here is ... not very pleasant.
  60 + // NBM: is this the "right" way to do this?
  61 + $raTable = KTUtil::getTableName('role_allocations');
  62 +
  63 + $fTable = Folder::_table();
  64 +
  65 + $oFolder =& Folder::get($iFolderId);
  66 + $parents = $oFolder->getParentFolderIDs() . ',' . $iFolderId; // this is formatted as 1,2,3,4,5,6 - perfect for "WHERE".
  67 +
  68 + // FIXME what (if anything) do we need to do to check that this can't be used as an attack?
  69 + $folders = '(' . $parents . ')';
  70 +
  71 + $sQuery = "SELECT ra.id as `id` FROM " . $raTable . " AS ra " .
  72 + ' LEFT JOIN ' . $fTable . ' AS f ON (f.id = ra.folder_id) ' .
  73 + ' WHERE f.id IN ' . $folders .
  74 + ' ORDER BY CHAR_LENGTH(f.parent_folder_ids) desc, f.parent_folder_ids DESC; ';
  75 + $aParams = array();
  76 +
  77 + $aRoleAllocIds = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'id');
  78 +
  79 + if (false) {
  80 + print '<pre>';
  81 + var_dump($aRoleAllocIds);
  82 + print '';
  83 + print $sQuery;
  84 + print '</pre>';
  85 + }
  86 +
  87 + if (empty($aRoleAllocIds)) {
  88 + return null;
  89 + }
  90 +
  91 + $iAllocId = $aRoleAllocIds[0]; // array pop?
  92 + return RoleAllocation::get($iAllocId);
  93 + }
  94 +
  95 + // static, boilerplate.
  96 + function _table () { return KTUtil::getTableName('role_allocations'); }
  97 + function & get($iRoleId) { return KTEntityUtil::get('RoleAllocation', $iRoleId); }
  98 + function & getList($sWhereClause = null) { return KTEntityUtil::getList2('RoleAllocation', $sWhereClause); }
  99 + function & createFromArray($aOptions) { return KTEntityUtil::createFromArray('RoleAllocation', $aOptions); }
  100 +
  101 + function getPermissionDescriptor() {
  102 + // could be an error - return as-is.
  103 + $oDescriptor =& KTPermissionDescriptor::get($this->iPermissionDescriptorId);
  104 + return $oDescriptor;
  105 + }
  106 +
  107 + // setting users and groups needs to use permissionutil::getOrCreateDescriptor
  108 + function getUsers() {
  109 + $oDescriptor = $this->getPermissionDescriptor();
  110 + $aUsers = array();
  111 + if (PEAR::isError($oDescriptor) || ($oDescriptor == false)) {
  112 + return $aUsers;
  113 + }
  114 + $aAllowed = $oDescriptor->getAllowed();
  115 + if ($aAllowed['user'] !== null) {
  116 + $aUsers = $aAllowed['user'];
  117 + }
  118 +
  119 + // now we want to map to oUsers, since that's what groups do.
  120 + $aFullUsers = array();
  121 + foreach ($aUsers as $iUserId) {
  122 + $oUser = User::get($iUserId);
  123 + if (!(PEAR::isError($oUser) || ($oUser == false))) {
  124 + $aFullUsers[] = $oUser;
  125 + }
  126 + }
  127 +
  128 + return $aFullUsers;
  129 + }
  130 +
  131 + function getGroups() {
  132 + $oDescriptor = $this->getPermissionDescriptor();
  133 + $aGroups = array();
  134 + if (PEAR::isError($oDescriptor) || ($oDescriptor == false)) {
  135 + return $aGroups;
  136 + }
  137 + $aAllowed = $oDescriptor->getAllowed();
  138 + if ($aAllowed['group'] !== null) {
  139 + $aGroups = $aAllowed['group'];
  140 + }
  141 +
  142 + // now we want to map to oUsers, since that's what groups do.
  143 + $aFullGroups = array();
  144 + foreach ($aGroups as $iGroupId) {
  145 + $oGroup = Group::get($iGroupId);
  146 + if (!(PEAR::isError($oGroup) || ($oGroup == false))) {
  147 + $aFullGroups[] = $oGroup;
  148 + }
  149 + }
  150 +
  151 + return $aFullGroups;
  152 + }
  153 +
  154 + // utility function to establish user membership in this allocation.
  155 + // FIXME nbm: is there are more coherent way to do this ITO your PD infrastructure?
  156 + function hasMember($oUser) {
  157 + $oPD = $this->getPermissionDescriptor();
  158 + if (PEAR::isError($oPD) || ($oPD == false)) {
  159 + return false;
  160 + }
  161 + $aAllowed = $oPD->getAllowed();
  162 + $iUserId = $oUser->getId();
  163 +
  164 + if ($aAllowed['user'] != null) {
  165 + if (array_search($iUserId, $aAllowed['user']) !== false) {
  166 + return true;
  167 + }
  168 + }
  169 +
  170 + // now we need the group objects.
  171 + // FIXME this could accelerated to a single SQL query on group_user_link.
  172 + $aGroups = $this->getGroups();
  173 + if (PEAR::isError($aGroups) || ($aGroups == false)) {
  174 + return false;
  175 + } else {
  176 + foreach ($aGroups as $oGroup) {
  177 + if ($oGroup->hasMember($oUser)) {
  178 + return true;
  179 + }
  180 + }
  181 + }
  182 +
  183 + return false;
  184 + }
  185 +
  186 +}
  187 +
  188 +?>
... ...
lib/workflow/workflowutil.inc.php
... ... @@ -8,6 +8,7 @@ require_once(KT_LIB_DIR . &#39;/permissions/permissionutil.inc.php&#39;);
8 8 require_once(KT_LIB_DIR . '/groups/GroupUtil.php');
9 9 require_once(KT_LIB_DIR . '/documentmanagement/DocumentTransaction.inc');
10 10 require_once(KT_LIB_DIR . '/search/searchutil.inc.php');
  11 +require_once(KT_LIB_DIR . '/roles/roleallocation.inc.php');
11 12  
12 13 class KTWorkflowUtil {
13 14 // {{{ saveTransitionsFrom
... ... @@ -338,6 +339,18 @@ class KTWorkflowUtil {
338 339 continue;
339 340 }
340 341 }
  342 + $iRoleId = $oTransition->getGuardRoleId();
  343 + if ($iRoleId) {
  344 + $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($oDocument->getFolderID(), $iRoleId);
  345 +
  346 + if ($oRoleAllocation == null) { // no role allocation, no fulfillment.
  347 + continue;
  348 + }
  349 +
  350 + if (!$oRoleAllocation->hasMember($oUser)) {
  351 + continue;
  352 + }
  353 + }
341 354  
342 355 $iConditionId = $oTransition->getGuardConditionId();
343 356 if ($iConditionId) {
... ...
plugins/ktcore/KTPermissions.php
1 1 <?php
2 2  
  3 +require_once(KT_LIB_DIR . '/actions/folderaction.inc.php');
3 4 require_once(KT_LIB_DIR . '/actions/documentaction.inc.php');
4 5 require_once(KT_LIB_DIR . '/widgets/fieldWidgets.php');
5 6  
6 7 require_once(KT_LIB_DIR . "/foldermanagement/Folder.inc");
7 8 require_once(KT_LIB_DIR . "/groups/Group.inc");
  9 +require_once(KT_LIB_DIR . "/users/User.inc");
  10 +require_once(KT_LIB_DIR . "/roles/Role.inc");
  11 +require_once(KT_LIB_DIR . "/roles/roleallocation.inc.php");
  12 +
8 13  
9 14 require_once(KT_LIB_DIR . "/permissions/permission.inc.php");
10 15 require_once(KT_LIB_DIR . "/permissions/permissionobject.inc.php");
... ... @@ -77,3 +82,413 @@ class KTDocumentPermissionsAction extends KTDocumentAction {
77 82 }
78 83 $oPlugin->registerAction('documentaction', 'KTDocumentPermissionsAction', 'ktcore.actions.document.permissions');
79 84  
  85 +
  86 +class KTRoleAllocationPlugin extends KTFolderAction {
  87 + var $sDisplayName = 'Allocate Roles';
  88 + var $sName = 'ktcore.actions.folder.roles';
  89 +
  90 + var $_sShowPermission = "ktcore.permissions.write";
  91 + var $bAutomaticTransaction = true;
  92 +
  93 + function do_main() {
  94 + $this->oPage->setTitle(_("Allocate Roles"));
  95 + $this->oPage->setBreadcrumbDetails(_("Allocate Roles"));
  96 + $oTemplating = new KTTemplating;
  97 + $oTemplate = $oTemplating->loadTemplate("ktcore/folder/roles");
  98 +
  99 + // we need to have:
  100 + // - a list of roles
  101 + // - with their users / groups
  102 + // - and that allocation id
  103 + $aRoles = array(); // stores data for display.
  104 +
  105 + $aRoleList = Role::getList();
  106 + foreach ($aRoleList as $oRole) {
  107 + $iRoleId = $oRole->getId();
  108 + $aRoles[$iRoleId] = array("name" => $oRole->getName());
  109 + $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($this->oFolder->getId(), $iRoleId);
  110 +
  111 + $u = array();
  112 + $g = array();
  113 + $aid = null;
  114 + $raid = null;
  115 + if ($oRoleAllocation == null) {
  116 + ; // nothing.
  117 + } else {
  118 + $raid = $oRoleAllocation->getId(); // real_alloc_id
  119 + if ($oRoleAllocation->getFolderId() == $this->oFolder->getId()) {
  120 + $aid = $oRoleAllocation->getid(); // alloc_id
  121 + }
  122 + $oPermDesc = KTPermissionDescriptor::get($oRoleAllocation->getPermissionDescriptorId());
  123 + if (!PEAR::isError($oPermDesc)) {
  124 + $aAllowed = $oPermDesc->getAllowed();
  125 + if (!empty($aAllowed['user'])) {
  126 + $u = $aAllowed['user'];
  127 + }
  128 + if (!empty($aAllowed['group'])) {
  129 + $g = $aAllowed['group'];
  130 + }
  131 + }
  132 + }
  133 + $aRoles[$iRoleId]['users'] = $u;
  134 + $aRoles[$iRoleId]['groups'] = $g;
  135 + $aRoles[$iRoleId]['allocation_id'] = $aid;
  136 + $aRoles[$iRoleId]['real_allocation_id'] = $raid;
  137 + }
  138 +
  139 + /*
  140 + print '<pre>';
  141 + var_dump($aRoles);
  142 + print '</pre>';
  143 + */
  144 +
  145 +
  146 +
  147 + // FIXME this is test data.
  148 + /*
  149 + $aRoles = array(
  150 + 1 => array('name' => 'Manager', 'users' => array(1), 'groups' => array(1), 'allocation_id' => 1),
  151 + 2 => array('name' => 'Peasant', 'users' => array(1), 'groups' => array(), 'allocation_id' => 2),
  152 + 3 => array('name' => 'Inherited', 'users' => array(), 'groups' => array(1), 'allocation_id' => null),
  153 + );
  154 + */
  155 +
  156 +
  157 + // final step.
  158 +
  159 + // map to users, groups.
  160 + foreach ($aRoles as $key => $role) {
  161 + $_users = array();
  162 + foreach ($aRoles[$key]['users'] as $iUserId) {
  163 + $oUser = User::get($iUserId);
  164 + if (!(PEAR::isError($oUser) || ($oUser == false))) {
  165 + $_users[] = $oUser->getName();
  166 + }
  167 + }
  168 + if (empty($_users)) {
  169 + $aRoles[$key]['users'] = '<span class="descriptiveText"> ' . _('no users') . '</span>';
  170 + } else {
  171 + $aRoles[$key]['users'] = join(', ',$_users);
  172 + }
  173 +
  174 + $_groups = array();
  175 + foreach ($aRoles[$key]['groups'] as $iGroupId) {
  176 + $oGroup = Group::get($iGroupId);
  177 + if (!(PEAR::isError($oGroup) || ($oGroup == false))) {
  178 + $_groups[] = $oGroup->getName();
  179 + }
  180 + }
  181 + if (empty($_groups)) {
  182 + $aRoles[$key]['groups'] = '<span class="descriptiveText"> ' . _('no groups') . '</span>';
  183 + } else {
  184 + $aRoles[$key]['groups'] = join(', ',$_groups);
  185 + }
  186 + }
  187 +
  188 + $aTemplateData = array(
  189 + 'context' => &$this,
  190 + 'roles' => $aRoles,
  191 + );
  192 + return $oTemplate->render($aTemplateData);
  193 + }
  194 +
  195 +
  196 +
  197 + function do_overrideParent() {
  198 + $role_id = KTUtil::arrayGet($_REQUEST, 'role_id', null);
  199 + $oRole = Role::get($role_id);
  200 + if (PEAR::isError($oRole)) {
  201 + $this->errorRedirectToMain(_('Invalid Role.'));
  202 + }
  203 + // FIXME do we need to check that this role _isn't_ allocated?
  204 + $oRoleAllocation = new RoleAllocation();
  205 + $oRoleAllocation->setFolderId($this->oFolder->getId());
  206 + $oRoleAllocation->setRoleId($role_id);
  207 +
  208 + // create a new permission descriptor.
  209 + // FIXME we really want to duplicate the original (if it exists)
  210 +
  211 + $aAllowed = array(); // no-op, for now.
  212 + $this->startTransaction();
  213 +
  214 + $oRoleAllocation->setAllowed($aAllowed);
  215 + $res = $oRoleAllocation->create();
  216 +
  217 + if (PEAR::isError($res) || ($res == false)) {
  218 + $this->errorRedirectToMain(_('Failed to create the role allocation.') . print_r($res, true), sprintf('fFolderId=%d', $this->oFolder->getId()));
  219 + }
  220 +
  221 + $this->renegeratePermissionsForRole($oRoleAllocation->getRoleId());
  222 +
  223 + $this->successRedirectToMain(_('Role allocation created.'), sprintf('fFolderId=%d', $this->oFolder->getId()));
  224 + }
  225 +
  226 + function do_useParent() {
  227 + $role_id = KTUtil::arrayGet($_REQUEST, 'role_id', null);
  228 + $oRole = Role::get($role_id);
  229 + if (PEAR::isError($oRole)) {
  230 + $this->errorRedirectToMain(_('Invalid Role.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  231 + }
  232 + $role_id = $oRole->getId(); // numeric, for various testing purposes.
  233 +
  234 + $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($this->oFolder->getId(), $role_id);
  235 +
  236 + if ($oRoleAllocation->getFolderId() != $this->oFolder->getId()) {
  237 + $this->errorRedirectToMain(_('Already using a different descriptor.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  238 + }
  239 + $this->startTransaction();
  240 +
  241 + $res = $oRoleAllocation->delete();
  242 +
  243 + if (PEAR::isError($res) || ($res == false)) {
  244 + $this->errorRedirectToMain(_('Unable to change role allocation.') . print_r($res, true), sprintf('fFolderId=%d',$this->oFolder->getId()));
  245 + exit(0);
  246 + }
  247 +
  248 + $this->renegeratePermissionsForRole($oRoleAllocation->getRoleId());
  249 + $this->successRedirectToMain(_('Role now uses parent.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  250 + }
  251 +
  252 + function do_editRoleUsers() {
  253 +
  254 + $role_allocation_id = KTUtil::arrayGet($_REQUEST, 'alloc_id');
  255 + $oRoleAllocation = RoleAllocation::get($role_allocation_id);
  256 + if ((PEAR::isError($oRoleAllocation)) || ($oRoleAllocation=== false)) {
  257 + $this->errorRedirectToMain(_('No such role allocation.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  258 + }
  259 +
  260 +
  261 + $this->oPage->setBreadcrumbDetails(_('Manage Users for Role'));
  262 + $this->oPage->setTitle(sprintf(_('Manage Users for Role')));
  263 +
  264 + $initJS = 'var optGroup = new OptionTransfer("userSelect","chosenUsers"); ' .
  265 + 'function startTrans() { var f = getElement("userroleform"); ' .
  266 + ' optGroup.saveNewRightOptions("userFinal"); ' .
  267 + ' optGroup.init(f); }; ' .
  268 + ' addLoadEvent(startTrans); ';
  269 + $this->oPage->requireJSStandalone($initJS);
  270 +
  271 + $aInitialUsers = $oRoleAllocation->getUsers();
  272 + $aAllUsers = User::getList();
  273 +
  274 +
  275 + // FIXME this is massively non-performant for large userbases..
  276 + $aRoleUsers = array();
  277 + $aFreeUsers = array();
  278 + foreach ($aInitialUsers as $oUser) {
  279 + $aRoleUsers[$oUser->getId()] = $oUser;
  280 + }
  281 + foreach ($aAllUsers as $oUser) {
  282 + if (!array_key_exists($oUser->getId(), $aRoleUsers)) {
  283 + $aFreeUsers[$oUser->getId()] = $oUser;
  284 + }
  285 + }
  286 +
  287 + $oTemplating = new KTTemplating;
  288 + $oTemplate = $oTemplating->loadTemplate("ktcore/folder/roles_manageusers");
  289 + $aTemplateData = array(
  290 + "context" => $this,
  291 + "edit_rolealloc" => $oRoleAllocation,
  292 + 'unused_users' => $aFreeUsers,
  293 + 'role_users' => $aRoleUsers,
  294 + );
  295 + return $oTemplate->render($aTemplateData);
  296 + }
  297 +
  298 + function do_editRoleGroups() {
  299 +
  300 + $role_allocation_id = KTUtil::arrayGet($_REQUEST, 'alloc_id');
  301 + $oRoleAllocation = RoleAllocation::get($role_allocation_id);
  302 + if ((PEAR::isError($oRoleAllocation)) || ($oRoleAllocation=== false)) {
  303 + $this->errorRedirectToMain(_('No such role allocation.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  304 + }
  305 +
  306 +
  307 + $this->oPage->setBreadcrumbDetails(_('Manage Groups for Role'));
  308 + $this->oPage->setTitle(sprintf(_('Manage Groups for Role')));
  309 +
  310 + $initJS = 'var optGroup = new OptionTransfer("groupSelect","chosenGroups"); ' .
  311 + 'function startTrans() { var f = getElement("grouproleform"); ' .
  312 + ' optGroup.saveNewRightOptions("groupFinal"); ' .
  313 + ' optGroup.init(f); }; ' .
  314 + ' addLoadEvent(startTrans); ';
  315 + $this->oPage->requireJSStandalone($initJS);
  316 +
  317 + $aInitialUsers = $oRoleAllocation->getGroups();
  318 + $aAllUsers = Group::getList();
  319 +
  320 +
  321 + // FIXME this is massively non-performant for large userbases..
  322 + $aRoleUsers = array();
  323 + $aFreeUsers = array();
  324 + foreach ($aInitialUsers as $oGroup) {
  325 + $aRoleUsers[$oGroup->getId()] = $oGroup;
  326 + }
  327 + foreach ($aAllUsers as $oGroup) {
  328 + if (!array_key_exists($oGroup->getId(), $aRoleUsers)) {
  329 + $aFreeUsers[$oGroup->getId()] = $oGroup;
  330 + }
  331 + }
  332 +
  333 + $oTemplating = new KTTemplating;
  334 + $oTemplate = $oTemplating->loadTemplate("ktcore/folder/roles_managegroups");
  335 + $aTemplateData = array(
  336 + "context" => $this,
  337 + "edit_rolealloc" => $oRoleAllocation,
  338 + 'unused_groups' => $aFreeUsers,
  339 + 'role_groups' => $aRoleUsers,
  340 + );
  341 + return $oTemplate->render($aTemplateData);
  342 + }
  343 +
  344 + function do_setRoleUsers() {
  345 +
  346 + $role_allocation_id = KTUtil::arrayGet($_REQUEST, 'allocation_id');
  347 + $oRoleAllocation = RoleAllocation::get($role_allocation_id);
  348 + if ((PEAR::isError($oRoleAllocation)) || ($oRoleAllocation=== false)) {
  349 + $this->errorRedirectToMain(_('No such role allocation.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  350 + }
  351 + $users = KTUtil::arrayGet($_REQUEST, 'userFinal', '');
  352 + $aUserIds = explode(',', $users);
  353 +
  354 + // check that its not corrupt..
  355 + $aFinalUserIds = array();
  356 + foreach ($aUserIds as $iUserId) {
  357 + $oUser =& User::get($iUserId);
  358 + if (!(PEAR::isError($oUser) || ($oUser == false))) {
  359 + $aFinalUserIds[] = $iUserId;
  360 + }
  361 + }
  362 + if (empty($aFinalUserIds)) { $aFinalUserIds = null; }
  363 +
  364 + // hack straight in.
  365 + $oPD = $oRoleAllocation->getPermissionDescriptor();
  366 + $aAllowed = $oPD->getAllowed();
  367 +
  368 +
  369 +
  370 + // now, grab the existing allowed and modify.
  371 +
  372 + $aAllowed['user'] = $aFinalUserIds;
  373 +
  374 + $oRoleAllocation->setAllowed($aAllowed);
  375 + $res = $oRoleAllocation->update();
  376 +
  377 + if (PEAR::isError($res) || ($res == false)) {
  378 + $this->errorRedirectToMain(_('Failed to change the role allocation.') . print_r($res, true), sprintf('fFolderId=%d', $this->oFolder->getId()));
  379 + }
  380 +
  381 + $this->renegeratePermissionsForRole($oRoleAllocation->getRoleId());
  382 +
  383 + $this->successRedirectToMain(_('Allocation changed.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  384 + }
  385 +
  386 + function do_setRoleGroups() {
  387 +
  388 + $role_allocation_id = KTUtil::arrayGet($_REQUEST, 'allocation_id');
  389 + $oRoleAllocation = RoleAllocation::get($role_allocation_id);
  390 + if ((PEAR::isError($oRoleAllocation)) || ($oRoleAllocation=== false)) {
  391 + $this->errorRedirectToMain(_('No such role allocation.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  392 + }
  393 + $groups = KTUtil::arrayGet($_REQUEST, 'groupFinal', '');
  394 + $aGroupIds = explode(',', $groups);
  395 +
  396 + // check that its not corrupt..
  397 + $aFinalGroupIds = array();
  398 + foreach ($aGroupIds as $iGroupId) {
  399 + $oGroup =& Group::get($iGroupId);
  400 + if (!(PEAR::isError($oGroup) || ($oGroup == false))) {
  401 + $aFinalGroupIds[] = $iGroupId;
  402 + }
  403 + }
  404 + if (empty($aFinalGroupIds)) { $aFinalGroupIds = null; }
  405 +
  406 + // hack straight in.
  407 + $oPD = $oRoleAllocation->getPermissionDescriptor();
  408 + $aAllowed = $oPD->getAllowed();
  409 +
  410 +
  411 +
  412 + // now, grab the existing allowed and modify.
  413 +
  414 + $aAllowed['group'] = $aFinalGroupIds;
  415 +
  416 + $oRoleAllocation->setAllowed($aAllowed);
  417 + $res = $oRoleAllocation->update();
  418 +
  419 + if (PEAR::isError($res) || ($res == false)) {
  420 + $this->errorRedirectToMain(_('Failed to change the role allocation.') . print_r($res, true), sprintf('fFolderId=%d', $this->oFolder->getId()));
  421 + }
  422 +
  423 + $this->renegeratePermissionsForRole($oRoleAllocation->getRoleId());
  424 +
  425 + $this->successRedirectToMain(_('Allocation changed.'), sprintf('fFolderId=%d',$this->oFolder->getId()));
  426 + }
  427 +
  428 + function renegeratePermissionsForRole($iRoleId) {
  429 + $iStartFolderId = $this->oFolder->getId();
  430 + $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($iStartFolderId, $iRoleId);
  431 + /*
  432 + * 1. find all folders & documents "below" this one which use the role
  433 + * definition _active_ (not necessarily present) at this point.
  434 + * 2. tell permissionutil to regen their permissions.
  435 + *
  436 + * The find algorithm is:
  437 + *
  438 + * folder_queue <- (iStartFolderId)
  439 + * while folder_queue is not empty:
  440 + * active_folder =
  441 + * for each folder in the active_folder:
  442 + * find folders in _this_ folder without a role-allocation on the iRoleId
  443 + * add them to the folder_queue
  444 + * update the folder's permissions.
  445 + * find documents in this folder:
  446 + * update their permissions.
  447 + */
  448 +
  449 + $sQuery = 'SELECT f.id as `id` FROM ' . Folder::_table() . ' AS f LEFT JOIN ' . RoleAllocation::_table() . ' AS ra ON (f.id = ra.folder_id) WHERE f.parent_id = ? AND ra.role_id ';
  450 + if ($oRoleAllocation == null) { // no alloc.
  451 + $sQuery .= ' IS NULL ';
  452 + $hasId = false;
  453 + } else {
  454 + $sQuery .= ' = ? ';
  455 + $aId = $oRoleAllocation->getId();
  456 + $hasId = true;
  457 + }
  458 +
  459 +
  460 + $folder_queue = array($iStartFolderId);
  461 + while (!empty($folder_queue)) {
  462 + $active_folder = array_pop($folder_queue);
  463 +
  464 +
  465 + $aParams = array($active_folder);
  466 + if ($hasId) { $aParams[] = $aId; }
  467 +
  468 +
  469 + $aNewFolders = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'id');
  470 + if (PEAR::isError($aNewFolders)) {
  471 + $this->errorRedirectToMain(_('Failure to generate folderlisting.'));
  472 + }
  473 + $folder_queue = array_merge ($folder_queue, $aNewFolders); // push.
  474 +
  475 +
  476 + // update the folder.
  477 + $oFolder =& Folder::get($active_folder);
  478 + if (PEAR::isError($oFolder) || ($oFolder == false)) {
  479 + $this->errorRedirectToMain(_('Unable to locate folder: ') . $active_folder);
  480 + }
  481 +
  482 + KTPermissionUtil::updatePermissionLookup($oFolder);
  483 + $aDocList =& Document::getList(array('folder_id = ?', $active_folder));
  484 + if (PEAR::isError($aDocList) || ($aDocList == false)) {
  485 + $this->errorRedirectToMain(_('Unable to get documents in folder: ') . $active_folder);
  486 + }
  487 +
  488 + foreach ($aDocList as $oDoc) {
  489 + KTPermissionUtil::updatePermissionLookup($oDoc);
  490 + }
  491 + }
  492 + }
  493 +}
  494 +$oPlugin->registerAction('folderaction', 'KTRoleAllocationPlugin', 'ktcore.actions.folder.roles');
... ...
presentation/lookAndFeel/knowledgeTree/browse.php
... ... @@ -46,7 +46,7 @@ $sectionName = &quot;browse&quot;;
46 46  
47 47 class BrowseDispatcher extends KTStandardDispatcher {
48 48  
49   - var $oFolder = null;
  49 + var $oFolder = null;
50 50 var $sSection = "browse";
51 51 var $browse_mode = null;
52 52 var $query = null;
... ... @@ -79,12 +79,12 @@ class BrowseDispatcher extends KTStandardDispatcher {
79 79  
80 80 // here we need the folder object to do the breadcrumbs.
81 81 $oFolder =& Folder::get($folder_id);
  82 + $this->oFolder =& $oFolder;
82 83 if (PEAR::isError($oFolder)) {
83 84 $this->oPage->addError(_("invalid folder"));
84 85 $folder_id = 1;
85 86 $oFolder =& Folder::get($folder_id);
86 87 }
87   - $this->oFolder =& $oFolder;
88 88  
89 89 // we now have a folder, and need to create the query.
90 90 $this->oQuery = new BrowseQuery($oFolder->getId());
... ...
resources/css/kt-framing.css
... ... @@ -622,6 +622,7 @@ The text will be hidden for screen view. The generic fahrner-ish approach comes
622 622  
623 623 .listing td {
624 624 padding: 0.5em;
  625 + vertical-align: top;
625 626 }
626 627  
627 628 .listing thead th {
... ...
sql/mysql/install/structure.sql
... ... @@ -1008,9 +1008,6 @@ CREATE TABLE `permissions` (
1008 1008 CREATE TABLE `roles` (
1009 1009 `id` int(11) NOT NULL default '0',
1010 1010 `name` char(255) NOT NULL default '',
1011   - `active` tinyint(1) NOT NULL default '0',
1012   - `can_read` tinyint(1) NOT NULL default '0',
1013   - `can_write` tinyint(1) NOT NULL default '0',
1014 1011 UNIQUE KEY `id` (`id`),
1015 1012 UNIQUE KEY `name` (`name`)
1016 1013 ) ENGINE=InnoDB ;
... ... @@ -1018,6 +1015,22 @@ CREATE TABLE `roles` (
1018 1015 -- --------------------------------------------------------
1019 1016  
1020 1017 --
  1018 +-- Table structure for table `role_allocations`
  1019 +--
  1020 +
  1021 +CREATE TABLE `role_allocations` (
  1022 + `id` int(11) NOT NULL default '0',
  1023 + `folder_id` int(11) NOT NULL default '0',
  1024 + `role_id` int(11) NOT NULL default '0',
  1025 + `permission_descriptor_id` int(11) NOT NULL default '0',
  1026 + UNIQUE KEY `id` (`id`),
  1027 + KEY `folder_id` (`folder_id`)
  1028 +) ENGINE=InnoDB ;
  1029 +
  1030 +-- --------------------------------------------------------
  1031 +
  1032 +
  1033 +--
1021 1034 -- Table structure for table `saved_searches`
1022 1035 --
1023 1036  
... ... @@ -1916,6 +1929,19 @@ CREATE TABLE `zseq_roles` (
1916 1929  
1917 1930 -- --------------------------------------------------------
1918 1931  
  1932 +
  1933 +--
  1934 +-- Table structure for table `zseq_role_allocations`
  1935 +--
  1936 +
  1937 +CREATE TABLE `zseq_role_allocations` (
  1938 + `id` int(10) unsigned NOT NULL auto_increment,
  1939 + PRIMARY KEY (`id`)
  1940 +) ENGINE=MyISAM ;
  1941 +
  1942 +-- --------------------------------------------------------
  1943 +
  1944 +
1919 1945 --
1920 1946 -- Table structure for table `zseq_saved_searches`
1921 1947 --
... ...
sql/mysql/upgrade/2.99.5/role_allocations.sql 0 → 100644
  1 +SET FOREIGN_KEY_CHECKS=0;
  2 +
  3 +CREATE TABLE `role_allocations` (
  4 + `id` int(11) NOT NULL default '0',
  5 + `folder_id` int(11) NOT NULL default '0',
  6 + `role_id` int(11) NOT NULL default '0',
  7 + `permission_descriptor_id` int(11) NOT NULL default '0',
  8 + UNIQUE KEY `id` (`id`),
  9 + KEY `folder_id` (`folder_id`)
  10 +) ENGINE=InnoDB ;
  11 +
  12 +CREATE TABLE `zseq_role_allocations` (
  13 + `id` int(10) unsigned NOT NULL auto_increment,
  14 + PRIMARY KEY (`id`)
  15 +) ENGINE=MyISAM ;
  16 +
  17 +
  18 +SET FOREIGN_KEY_CHECKS=1;
... ...
sql/mysql/upgrade/2.99.5/role_changes.sql 0 → 100644
  1 +SET FOREIGN_KEY_CHECKS=0;
  2 +
  3 +ALTER TABLE `roles` DROP `active`;
  4 +ALTER TABLE `roles` DROP `can_read`;
  5 +ALTER TABLE `roles` DROP `can_write`;
  6 +
  7 +SET FOREIGN_KEY_CHECKS=1;
... ...
templates/ktcore/folder/roles.smarty 0 → 100644
  1 +<h2>{i18n}Allocate Roles{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">{i18n}
  4 + In many cases, workflow actions will be assigned to certain <strong>roles</strong>
  5 + (e.g. Manager, Interviewer, Researcher, Journalist). You can assign these roles
  6 + to specific groups in particular areas of the document management system.
  7 +{/i18n}</p>
  8 +
  9 +<div class='ktInfo'><p><strong>{i18n}Warning:{/i18n}</strong>{i18n} Please note that changing
  10 +role allocations can take very long time, depending on the number of folders below this one.{/i18n}</p></div>
  11 +
  12 +<table class="listing">
  13 +<thead>
  14 + <tr>
  15 + <th>{i18n}Role{/i18n}</th>
  16 + <th>{i18n}Allocated users{/i18n}</th>
  17 + <th>{i18n}Edit Users{/i18n}</th>
  18 + <th>{i18n}Edit Groups{/i18n}</th>
  19 + <th>{i18n}Use Parent{/i18n}</th>
  20 + </tr>
  21 +</thead>
  22 +<tbody>
  23 +{foreach item=aRole key=role_id from=$roles}
  24 + <tr class="{cycle values=odd,even}">
  25 + <td>{$aRole.name}</td>
  26 + <td>
  27 + {if ($aRole.allocation_id === null)}
  28 + <strong>{i18n}inherited from parent folder.{/i18n}</strong><br />
  29 + <span class="descriptiveText">
  30 + {/if}
  31 + {if ($aRole.users != null)}<strong>{i18n}Users:{/i18n}</strong> {$aRole.users}<br />{/if}
  32 + {if ($aRole.groups != null)}<strong>{i18n}Groups:{/i18n}</strong> {$aRole.groups}{/if}
  33 + {if ($aRole.allocation_id === null)}
  34 + </span class="descriptiveText">
  35 + {/if}
  36 + </td>
  37 + {if ($aRole.allocation_id === null)}
  38 + <td colspan="3"><a href="{$smarty.server.PHP_SELF}?action=overrideParent&role_id={$role_id}&fFolderId={$context->oFolder->getId()}">{i18n}Override Parent Allocation{/i18n}</a></td>
  39 + {else}
  40 + <td><a href="{$smarty.server.PHP_SELF}?action=editRoleUsers&alloc_id={$aRole.allocation_id}&fFolderId={$context->oFolder->getId()}" class="ktAction ktEdit" title="{i18n}Edit{/i18n}">Edit</a></td>
  41 + <td><a href="{$smarty.server.PHP_SELF}?action=editRoleGroups&alloc_id={$aRole.allocation_id}&fFolderId={$context->oFolder->getId()}" class="ktAction ktEdit" title="{i18n}Edit{/i18n}">Edit</a></td>
  42 + <td><a href="{$smarty.server.PHP_SELF}?action=useParent&role_id={$role_id}&fFolderId={$context->oFolder->getId()}" class="ktAction ktDelete" title="{i18n}Use parent's allocation{/i18n}">{i18n}Use parent's allocation{/i18n}</a></td>
  43 + {/if}
  44 + </tr>
  45 +{/foreach}
  46 +</tbody>
  47 +</table>
0 48 \ No newline at end of file
... ...
templates/ktcore/folder/roles_managegroups.smarty 0 → 100644
  1 +<h2>{i18n}Allocate Groups to Role{/i18n}</h2>
  2 +
  3 +{$context->oPage->requireJSResource('thirdpartyjs/OptionTransfer.js')}
  4 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/Base.js')}
  5 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/Iter.js')}
  6 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/DOM.js')}
  7 +
  8 +<p class="descriptiveText"><strong>FIXME</strong> help text for role-editing. </p>
  9 +
  10 +<form action="{$smarty.server.PHP_SELF}" method="POST" id="grouproleform">
  11 + <input type="hidden" name="action" value="setRoleGroups" />
  12 + <input type="hidden" name="allocation_id" value="{$edit_rolealloc->getId()}" />
  13 + <input type="hidden" name="fFolderId" value="{$context->oFolder->getId()}" />
  14 + <!-- erk. FIXME clean up and remove OptionTransfer.js. -->
  15 +
  16 + <input type="hidden" name="groupFinal" />
  17 +
  18 +
  19 + <fieldset>
  20 + <legend>{i18n}Allocate Groups to Role{/i18n}</legend>
  21 + <p class="descriptiveText">{i18n}Select the groups which should be part of this role.{/i18n} <strong>FIXME</strong> this helptext is v. awkward.</p>
  22 +
  23 +<table border="0" width="600">
  24 + <thead>
  25 + <tr>
  26 + <th>{i18n}Available Groups{/i18n}</th>
  27 + <th>&nbsp;</th>
  28 + <th>{i18n}Member groups{/i18n}</th>
  29 + </tr>
  30 + </thead>
  31 + <tbody>
  32 + <tr>
  33 + <td valign="top" width="1%">
  34 + <select name="groupSelect" size="10" multiple="multiple">
  35 + {foreach item=oGroup from=$unused_groups}
  36 + <option value="{$oGroup->getId()}" ondblclick="optGroup.transferRight()">{$oGroup->getName()}</option>
  37 + {/foreach}
  38 + </select>
  39 + </td>
  40 + <td align="center">
  41 + <input name="right" style="width: 60px;" value="&raquo;" onclick="optGroup.transferRight()" type="button"><br /><br />
  42 + <input name="left" style="width: 60px;" value="&laquo;" onclick="optGroup.transferLeft()" type="button">
  43 + </td>
  44 + <td valign="top" width="1%">
  45 + <select name="chosenGroups" size="10" multiple="multiple">
  46 + {foreach item=oGroup from=$role_groups}
  47 + <option value="{$oGroup->getId()}" ondblclick="optGroup.transferRight()">{$oGroup->getName()}</option>
  48 + {/foreach}
  49 + </select>
  50 + </td>
  51 + </tr>
  52 + <tr>
  53 + <td><label for="ug-filter">{i18n}Filter{/i18n}</label>
  54 + <input name="filterUG" id="ug-filter" onkeyup="optGroup.sortSelectMatch(groupSelect, this.value)" onchange="optGroup.sortSelectMatch(groupSelect, this.value)" type="text">
  55 + </td>
  56 + <td>&nbsp;</td>
  57 + <td><label for="og-filter">{i18n}Filter{/i18n}</label>
  58 + <input name="filterOG" id="og-filter" onkeyup="optGroup.sortSelectMatch(chosenGroups, this.value)" onchange="optGroup.sortSelectMatch(chosenGroups, this.value)" type="text">
  59 + </td>
  60 + </tr>
  61 +</tbody></table>
  62 +
  63 + <div class="form_actions">
  64 + <input type="submit" value="{i18n}save changes{/i18n}" />
  65 + <a href="?action=main" class="ktCancelLink">{i18n}Cancel{/i18n}</a>
  66 + </div>
  67 + </fieldset>
  68 + </form>
... ...
templates/ktcore/folder/roles_manageusers.smarty 0 → 100644
  1 +<h2>{i18n}Allocate User to Role{/i18n}</h2>
  2 +
  3 +{$context->oPage->requireJSResource('thirdpartyjs/OptionTransfer.js')}
  4 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/Base.js')}
  5 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/Iter.js')}
  6 +{$context->oPage->requireJSResource('thirdpartyjs/MochiKit/DOM.js')}
  7 +
  8 +<p class="descriptiveText"><strong>FIXME</strong> help text for role-editing. </p>
  9 +
  10 +<form action="{$smarty.server.PHP_SELF}" method="POST" id="userroleform">
  11 + <input type="hidden" name="action" value="setRoleUsers" />
  12 + <input type="hidden" name="allocation_id" value="{$edit_rolealloc->getId()}" />
  13 + <input type="hidden" name="fFolderId" value="{$context->oFolder->getId()}" />
  14 + <!-- erk. FIXME clean up and remove OptionTransfer.js. -->
  15 +
  16 + <input type="hidden" name="userFinal" />
  17 +
  18 +
  19 + <fieldset>
  20 + <legend>{i18n}Allocate User to Role{/i18n}</legend>
  21 + <p class="descriptiveText">{i18n}Select the users which should be part of this role.{/i18n} <strong>FIXME</strong> this helptext is v. awkward.</p>
  22 +
  23 +<table border="0" width="600">
  24 + <thead>
  25 + <tr>
  26 + <th>{i18n}Available Users{/i18n}</th>
  27 + <th>&nbsp;</th>
  28 + <th>{i18n}Member users{/i18n}</th>
  29 + </tr>
  30 + </thead>
  31 + <tbody>
  32 + <tr>
  33 + <td valign="top" width="1%">
  34 + <select name="userSelect" size="10" multiple="multiple">
  35 + {foreach item=oUser from=$unused_users}
  36 + <option value="{$oUser->getId()}" ondblclick="optGroup.transferRight()">{$oUser->getName()}</option>
  37 + {/foreach}
  38 + </select>
  39 + </td>
  40 + <td align="center">
  41 + <input name="right" style="width: 60px;" value="&raquo;" onclick="optGroup.transferRight()" type="button"><br /><br />
  42 + <input name="left" style="width: 60px;" value="&laquo;" onclick="optGroup.transferLeft()" type="button">
  43 + </td>
  44 + <td valign="top" width="1%">
  45 + <select name="chosenUsers" size="10" multiple="multiple">
  46 + {foreach item=oUser from=$role_users}
  47 + <option value="{$oUser->getId()}" ondblclick="optGroup.transferRight()">{$oUser->getName()}</option>
  48 + {/foreach}
  49 + </select>
  50 + </td>
  51 + </tr>
  52 + <tr>
  53 + <td><label for="ug-filter">{i18n}Filter{/i18n}</label>
  54 + <input name="filterUG" id="ug-filter" onkeyup="optGroup.sortSelectMatch(userSelect, this.value)" onchange="optGroup.sortSelectMatch(groupSelect, this.value)" type="text">
  55 + </td>
  56 + <td>&nbsp;</td>
  57 + <td><label for="og-filter">{i18n}Filter{/i18n}</label>
  58 + <input name="filterOG" id="og-filter" onkeyup="optGroup.sortSelectMatch(chosenUsers, this.value)" onchange="optGroup.sortSelectMatch(chosenGroups, this.value)" type="text">
  59 + </td>
  60 + </tr>
  61 +</tbody></table>
  62 +
  63 + <div class="form_actions">
  64 + <input type="submit" value="{i18n}save changes{/i18n}" />
  65 + <a href="?action=main" class="ktCancelLink">{i18n}Cancel{/i18n}</a>
  66 + </div>
  67 + </fieldset>
  68 + </form>
... ...