1<?php 2/* 3 * Gallery - a web based photo album viewer and editor 4 * Copyright (C) 2000-2008 Bharat Mediratta 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or (at 9 * your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21/** 22 * This controller will handle the changes in the permission of an item 23 * @package GalleryCore 24 * @subpackage UserInterface 25 * @author Bharat Mediratta <bharat@menalto.com> 26 * @version $Revision: 17580 $ 27 */ 28class ItemPermissionsController extends GalleryController { 29 30 /** 31 * @see GalleryController::handleRequest 32 */ 33 function handleRequest($form) { 34 global $gallery; 35 36 list ($ret, $item) = $this->getItem(); 37 if ($ret) { 38 return array($ret, null); 39 } 40 $itemId = $item->getId(); 41 42 /* Make sure we have permission to change permissions of this item */ 43 $ret = GalleryCoreApi::assertHasItemPermission($itemId, 'core.changePermissions'); 44 if ($ret) { 45 return array($ret, null); 46 } 47 48 $applyToChildren = isset($form['applyToSubItems']); 49 $status = $error = array(); 50 if (isset($form['action']['deleteGroupPermission'])) { 51 /* Figure out which one we're working with */ 52 $deleteGroupPermission = array_keys($form['action']['deleteGroupPermission']); 53 $index = array_pop($deleteGroupPermission); 54 55 /* Handle delete group perm actions */ 56 list ($groupId, $permissionId) = explode(',', $form['group']['delete'][$index]); 57 $ret = GalleryCoreApi::removeGroupPermission($itemId, $groupId, 58 $permissionId, $applyToChildren); 59 if ($ret) { 60 return array($ret, null); 61 } 62 63 /* Figure out where to redirect upon success */ 64 $redirect['view'] = 'core.ItemAdmin'; 65 $redirect['subView'] = 'core.ItemPermissions'; 66 $redirect['itemId'] = $itemId; 67 $status['deletedGroupPermission'] = 1; 68 69 /* Stuff the values back into the form for easy re-adding */ 70 $redirect['form[group][permission]'] = $permissionId; 71 list ($ret, $group) = GalleryCoreApi::loadEntitiesById($groupId, 'GalleryGroup'); 72 if (!$ret) { 73 $redirect['form[group][groupName]'] = $group->getGroupName(); 74 } 75 $verifySelfPermissions = true; 76 } else if (isset($form['action']['deleteUserPermission'])) { 77 /* Figure out which one we're working with */ 78 $deleteUserPermission = array_keys($form['action']['deleteUserPermission']); 79 $index = array_pop($deleteUserPermission); 80 81 /* Handle delete user perm actions */ 82 list ($userId, $permissionId) = explode(',', $form['user']['delete'][$index]); 83 $ret = GalleryCoreApi::removeUserPermission($itemId, $userId, 84 $permissionId, $applyToChildren); 85 if ($ret) { 86 return array($ret, null); 87 } 88 89 /* Figure out where to redirect upon success */ 90 $redirect['view'] = 'core.ItemAdmin'; 91 $redirect['subView'] = 'core.ItemPermissions'; 92 $redirect['itemId'] = $itemId; 93 $status['deletedUserPermission'] = 1; 94 95 /* Stuff the values back into the form for easy re-adding */ 96 $redirect['form[user][permission]'] = $permissionId; 97 list ($ret, $user) = GalleryCoreApi::loadEntitiesById($userId, 'GalleryUser'); 98 if (!$ret) { 99 $redirect['form[user][userName]'] = $user->getUserName(); 100 } 101 if ($userId == $gallery->getActiveUserId()) { 102 $verifySelfPermissions = true; 103 } 104 } else if (isset($form['action']['addUserPermission'])) { 105 106 /* Handle add user permission actions */ 107 if (empty($form['user']['userName'])) { 108 $error[] = 'form[error][user][missingUser]'; 109 } else { 110 /* Validate the user */ 111 list ($ret, $user) = GalleryCoreApi::fetchUserByUserName($form['user']['userName']); 112 if ($ret) { 113 if ($ret->getErrorCode() & ERROR_MISSING_OBJECT) { 114 $error[] = 'form[error][user][invalidUser]'; 115 } else { 116 return array($ret, null); 117 } 118 } 119 } 120 121 /* Validate the permission */ 122 $permission = $form['user']['permission']; 123 list ($ret, $allPermissions) = GalleryCoreApi::getPermissionIds(); 124 if ($ret) { 125 return array($ret, null); 126 } 127 if (empty($allPermissions[$permission])) { 128 $error[] = 'form[error][user][invalidPermission]'; 129 } 130 131 if (empty($error)) { 132 /* Don't add the permission if it already exists */ 133 list ($ret, $hasIt) = 134 GalleryCoreApi::hasPermission($itemId, $user->getId(), $permission); 135 if ($ret) { 136 return array($ret, null); 137 } 138 if ($hasIt) { 139 $error[] = 'form[error][user][alreadyHadPermission]'; 140 } 141 } 142 143 if (empty($error)) { 144 $ret = GalleryCoreApi::addUserPermission($itemId, $user->getId(), 145 $permission, $applyToChildren); 146 if ($ret) { 147 return array($ret, null); 148 } 149 150 /* Figure out where to redirect upon success */ 151 $redirect['view'] = 'core.ItemAdmin'; 152 $redirect['subView'] = 'core.ItemPermissions'; 153 $redirect['itemId'] = $itemId; 154 $redirect['form[user][userName]'] = $user->getUserName(); 155 $status['addedUserPermission'] = 1; 156 } 157 } else if (isset($form['action']['addGroupPermission'])) { 158 159 /* Handle add group permission actions */ 160 if (empty($form['group']['groupName'])) { 161 $error[] = 'form[error][group][missingGroup]'; 162 } else { 163 /* Validate the group */ 164 list ($ret, $group) = 165 GalleryCoreApi::fetchGroupByGroupName($form['group']['groupName']); 166 if ($ret) { 167 if ($ret->getErrorCode() & ERROR_MISSING_OBJECT) { 168 $error[] = 'form[error][group][invalidGroup]'; 169 } else { 170 return array($ret, null); 171 } 172 } 173 } 174 175 /* Validate the permission */ 176 $permission = $form['group']['permission']; 177 list ($ret, $allPermissions) = GalleryCoreApi::getPermissionIds(); 178 if ($ret) { 179 return array($ret, null); 180 } 181 if (empty($allPermissions[$permission])) { 182 $error[] = 'form[error][group][invalidPermission]'; 183 } 184 185 if (empty($error)) { 186 /* Don't add the permission if it already exists */ 187 list ($ret, $hasIt) = 188 GalleryCoreApi::hasPermission($itemId, $group->getId(), $permission); 189 if ($ret) { 190 return array($ret, null); 191 } 192 if ($hasIt) { 193 $error[] = 'form[error][group][alreadyHadPermission]'; 194 } 195 } 196 197 if (empty($error)) { 198 $ret = GalleryCoreApi::addGroupPermission($itemId, $group->getId(), 199 $permission, $applyToChildren); 200 if ($ret) { 201 return array($ret, null); 202 } 203 204 /* Figure out where to redirect upon success */ 205 $redirect['view'] = 'core.ItemAdmin'; 206 $redirect['subView'] = 'core.ItemPermissions'; 207 $redirect['itemId'] = $itemId; 208 $redirect['form[group][groupName]'] = $group->getGroupName(); 209 $status['addedGroupPermission'] = 1; 210 } 211 } else if (isset($form['action']['changeOwner'])) { 212 if (empty($form['owner']['ownerName'])) { 213 $error[] = 'form[error][owner][missingUser]'; 214 } else { 215 $ret = GalleryCoreApi::assertUserIsSiteAdministrator(); 216 if ($ret) { 217 return array($ret, null); 218 } 219 220 /* Validate the user */ 221 list ($ret, $user) = 222 GalleryCoreApi::fetchUserByUserName($form['owner']['ownerName']); 223 if ($ret) { 224 if ($ret->getErrorCode() & ERROR_MISSING_OBJECT) { 225 $error[] = 'form[error][owner][invalidUser]'; 226 } else { 227 return array($ret, null); 228 } 229 } 230 } 231 232 if (empty($error)) { 233 list ($ret, $permissions) = 234 GalleryCoreApi::fetchPermissionsForItems(array($itemId), $item->getOwnerId()); 235 if ($ret) { 236 return array($ret, null); 237 } 238 239 list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($itemId); 240 if ($ret) { 241 return array($ret, null); 242 } 243 244 list ($ret, $item) = $item->refresh(); 245 if ($ret) { 246 return array($ret, null); 247 } 248 249 $userId = $user->getId(); 250 $item->setOwnerId($userId); 251 $item->setSerialNumber($form['serialNumber']); 252 $ret = $item->save(); 253 if ($ret) { 254 GalleryCoreApi::releaseLocks($lockId); 255 return array($ret, null); 256 } 257 258 $ret = GalleryCoreApi::releaseLocks($lockId); 259 if ($ret) { 260 return array($ret, null); 261 } 262 263 $applyOwnerToChildren = isset($form['applyOwnerToSubItems']); 264 foreach ($permissions[$itemId] as $permission => $unused) { 265 $ret = GalleryCoreApi::addUserPermission($itemId, $userId, 266 $permission, $applyOwnerToChildren); 267 if ($ret) { 268 return array($ret, null); 269 } 270 } 271 272 /* change the owner recursively for the descendents */ 273 if ($applyOwnerToChildren) { 274 list ($ret, $descendentIds) = 275 GalleryCoreApi::fetchDescendentItemIds($item, null, null, 'core.all'); 276 277 /* 278 * Process these descendents in chunks since we may have thousands of 279 * items and we don't want to give the database a heart attack. 280 */ 281 $chunkSize = 200; 282 while (!empty($descendentIds)) { 283 $chunk = array_splice($descendentIds, 0, $chunkSize); 284 $gallery->guaranteeTimeLimit(60); 285 286 list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($chunk); 287 if ($ret) { 288 return array($ret, null); 289 } 290 291 list ($ret, $descendents) = 292 GalleryCoreApi::loadEntitiesById($chunk, 'GalleryItem'); 293 if ($ret) { 294 return array($ret, null); 295 } 296 foreach ($descendents as $item) { 297 $item->setOwnerId($userId); 298 $ret = $item->save(); 299 if ($ret) { 300 GalleryCoreApi::releaseLocks($lockId); 301 return array($ret, null); 302 } 303 } 304 $ret = GalleryCoreApi::releaseLocks($lockId); 305 if ($ret) { 306 return array($ret, null); 307 } 308 } 309 } 310 311 /* Figure out where to redirect upon success */ 312 $redirect['view'] = 'core.ItemAdmin'; 313 $redirect['subView'] = 'core.ItemPermissions'; 314 $redirect['itemId'] = $itemId; 315 $status['changedOwner'] = 1; 316 } 317 } 318 319 if (isset($verifySelfPermissions)) { 320 /* 321 * Make sure we don't remove our own ability to change permissions on this item. 322 * If this was a recursive remove we may lose permissions on subitems. 323 */ 324 list ($ret, $canEdit) = GalleryCoreApi::hasItemPermission($itemId, 'core.edit'); 325 if ($ret) { 326 return array($ret, null); 327 } 328 if (!$canEdit) { 329 $ret = GalleryCoreApi::addUserPermission($itemId, $gallery->getActiveUserId(), 330 'core.edit', false); 331 if ($ret) { 332 return array($ret, null); 333 } 334 $status['addedBackSelfPermission'] = 1; 335 } 336 list ($ret, $canChange) = 337 GalleryCoreApi::hasItemPermission($itemId, 'core.changePermissions'); 338 if ($ret) { 339 return array($ret, null); 340 } 341 if (!$canChange) { 342 $ret = GalleryCoreApi::addUserPermission($itemId, $gallery->getActiveUserId(), 343 'core.changePermissions', false); 344 if ($ret) { 345 return array($ret, null); 346 } 347 $status['addedBackSelfPermission'] = 1; 348 } 349 } 350 351 if (empty($error)) { 352 /* 353 * Try compacting. Ignore lock timeouts here; if we failed this time we'll try 354 * again next time. 355 */ 356 $ret = GalleryCoreApi::maybeCompactAccessLists(); 357 if ($ret && !($ret->getErrorCode() & ERROR_LOCK_TIMEOUT)) { 358 return array($ret, null); 359 } 360 } 361 362 if (!empty($redirect)) { 363 $results['redirect'] = $redirect; 364 } else { 365 $results['delegate']['view'] = 'core.ItemAdmin'; 366 $results['delegate']['subView'] = 'core.ItemPermissions'; 367 } 368 $results['status'] = $status; 369 $results['error'] = $error; 370 371 return array(null, $results); 372 } 373} 374 375/** 376 * This view will prompt for permission settings of an item 377 */ 378class ItemPermissionsView extends GalleryView { 379 380 /** 381 * @see GalleryView::loadTemplate 382 */ 383 function loadTemplate(&$template, &$form) { 384 global $gallery; 385 386 list ($ret, $item) = $this->getItem(); 387 if ($ret) { 388 return array($ret, null); 389 } 390 $itemId = $item->getId(); 391 392 /* Make sure we have permission to edit this item */ 393 $ret = GalleryCoreApi::assertHasItemPermission($itemId, 'core.edit'); 394 if ($ret) { 395 return array($ret, null); 396 } 397 list ($ret, $canChange) = 398 GalleryCoreApi::hasItemPermission($itemId, 'core.changePermissions'); 399 if ($ret) { 400 return array($ret, null); 401 } 402 403 $form['serialNumber'] = $item->getSerialNumber(); 404 405 if ($form['formName'] == 'ItemPermissions') { 406 /* Complain if we have any invalid data */ 407 } else { 408 /* 409 * First time around, load the form with item data. Note that 410 * userName and groupName can be passed in to this form so don't 411 * initialize them unless they don't exist. 412 */ 413 if (empty($form['user']['userName'])) { 414 $form['user']['userName'] = ''; 415 } 416 417 if (empty($form['user']['permission'])) { 418 $form['user']['permission'] = ''; 419 } 420 421 if (empty($form['group']['groupName'])) { 422 $form['group']['groupName'] = ''; 423 } 424 425 if (empty($form['group']['permission'])) { 426 $form['group']['permission'] = ''; 427 } 428 429 $form['owner']['ownerName'] = ''; 430 $form['formName'] = 'ItemPermissions'; 431 } 432 433 /* Get all available permissions */ 434 list ($ret, $allPermissions) = GalleryCoreApi::getPermissionIds(); 435 if ($ret) { 436 return array($ret, null); 437 } 438 ksort($allPermissions); 439 440 /* Get all permissions for the item. */ 441 list ($ret, $permissions) = 442 GalleryCoreApi::fetchAllPermissionsForItem($itemId, true); 443 if ($ret) { 444 return array($ret, null); 445 } 446 447 /* Figure out all the unique user/group ids and load those */ 448 $userAndGroupEntityIds = array(); 449 foreach ($permissions as $permission) { 450 if (!empty($permission['userId'])) { 451 $userAndGroupEntityIds[$permission['userId']] = 1; 452 } 453 if (!empty($permission['groupId'])) { 454 $userAndGroupEntityIds[$permission['groupId']] = 1; 455 } 456 } 457 458 list ($ret, $userAndGroupEntities) = GalleryCoreApi::loadEntitiesById( 459 array_keys($userAndGroupEntityIds), array('GalleryUser', 'GalleryGroup')); 460 if ($ret) { 461 return array($ret, null); 462 } 463 464 /* Convert them into a hash map by entity id */ 465 foreach ($userAndGroupEntities as $entity) { 466 $userAndGroupEntityMap[$entity->getId()] = (array)$entity; 467 } 468 469 /* Figure out the admin group id */ 470 list ($ret, $adminGroupId) = 471 GalleryCoreApi::getPluginParameter('module', 'core', 'id.adminGroup'); 472 if ($ret) { 473 return array($ret, null); 474 } 475 476 /* 477 * Now create the separate user and group permission maps. 478 * 479 * Silently ignore any permissions that we come across that aren't part 480 * of the permission registry. They may be permission associated with 481 * modules that are not currently active. 482 */ 483 $userPermissions = $groupPermissions = array(); 484 foreach ($permissions as $permission) { 485 $permissionId = $permission['permission']; 486 if (!empty($permission['userId']) && isset($allPermissions[$permissionId])) { 487 list ($ret, $subPermissions) = GalleryCoreApi::getSubPermissions($permissionId); 488 if ($ret) { 489 return array($ret, null); 490 } 491 492 $userPermissions[] = array( 493 'permission' => array('id' => $permissionId, 494 'description' => $allPermissions[$permissionId]), 495 'user' => $userAndGroupEntityMap[$permission['userId']], 496 'deleteList' => $subPermissions); 497 } 498 499 if (!empty($permission['groupId']) && isset($allPermissions[$permissionId])) { 500 if ($permission['groupId'] != $adminGroupId) { 501 list ($ret, $subPermissions) = GalleryCoreApi::getSubPermissions($permissionId); 502 if ($ret) { 503 return array($ret, null); 504 } 505 } else { 506 $subPermissions = array(); 507 } 508 509 $groupPermissions[] = 510 array('permission' => array('id' => $permissionId, 511 'description' => $allPermissions[$permissionId]), 512 'group' => $userAndGroupEntityMap[$permission['groupId']], 513 'deleteList' => $subPermissions); 514 } 515 } 516 517 /* Figure out the owner */ 518 list ($ret, $owner) = GalleryCoreApi::loadEntitiesById($item->getOwnerId(), 'GalleryUser'); 519 if ($ret) { 520 return array($ret, null); 521 } 522 523 list ($ret, $isAdmin) = GalleryCoreApi::isUserInSiteAdminGroup(); 524 if ($ret) { 525 return array($ret, null); 526 } 527 528 /* Figure out what we can display on the form */ 529 $can['changePermissions'] = $canChange; 530 $can['changeOwner'] = $isAdmin; 531 $can['applyToSubItems'] = $item->getCanContainChildren(); 532 533 $ItemPermissions['owner'] = (array)$owner; 534 $ItemPermissions['can'] = $can; 535 $ItemPermissions['userPermissions'] = $userPermissions; 536 $ItemPermissions['groupPermissions'] = $groupPermissions; 537 $ItemPermissions['allPermissions'] = $allPermissions; 538 539 $template->setVariable('ItemPermissions', $ItemPermissions); 540 $template->setVariable('controller', 'core.ItemPermissions'); 541 return array(null, array('body' => 'modules/core/templates/ItemPermissions.tpl')); 542 } 543 544 /** 545 * @see GalleryView::getViewDescription 546 */ 547 function getViewDescription() { 548 list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core'); 549 if ($ret) { 550 return array($ret, null); 551 } 552 553 list ($ret, $item) = $this->getItem(); 554 if ($ret) { 555 return array($ret, null); 556 } 557 558 $itemTypeNames = $item->itemTypeName(true); 559 560 return array(null, $core->translate(array('text' => 'edit %s permissions', 561 'arg1' => $itemTypeNames[1]))); 562 } 563} 564?> 565