001 /** 002 * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved. 003 * 004 * The contents of this file are subject to the terms of the Liferay Enterprise 005 * Subscription License ("License"). You may not use this file except in 006 * compliance with the License. You can obtain a copy of the License by 007 * contacting Liferay, Inc. See the License for the specific language governing 008 * permissions and limitations under the License, including but not limited to 009 * distribution rights of the Software. 010 * 011 * 012 * 013 */ 014 015 package com.liferay.portal.service.impl; 016 017 import com.liferay.portal.NoSuchResourcePermissionException; 018 import com.liferay.portal.kernel.concurrent.LockRegistry; 019 import com.liferay.portal.kernel.dao.db.DB; 020 import com.liferay.portal.kernel.dao.db.DBFactoryUtil; 021 import com.liferay.portal.kernel.exception.PortalException; 022 import com.liferay.portal.kernel.exception.SystemException; 023 import com.liferay.portal.kernel.search.SearchEngineUtil; 024 import com.liferay.portal.kernel.util.StringBundler; 025 import com.liferay.portal.kernel.util.StringPool; 026 import com.liferay.portal.kernel.util.StringUtil; 027 import com.liferay.portal.model.Resource; 028 import com.liferay.portal.model.ResourceAction; 029 import com.liferay.portal.model.ResourceConstants; 030 import com.liferay.portal.model.ResourcePermission; 031 import com.liferay.portal.model.ResourcePermissionConstants; 032 import com.liferay.portal.model.Role; 033 import com.liferay.portal.model.RoleConstants; 034 import com.liferay.portal.security.permission.PermissionCacheUtil; 035 import com.liferay.portal.security.permission.PermissionThreadLocal; 036 import com.liferay.portal.security.permission.ResourceActionsUtil; 037 import com.liferay.portal.service.base.ResourcePermissionLocalServiceBaseImpl; 038 import com.liferay.portal.util.PortalUtil; 039 import com.liferay.portal.util.PropsValues; 040 import com.liferay.portal.util.ResourcePermissionsThreadLocal; 041 042 import java.util.ArrayList; 043 import java.util.Collection; 044 import java.util.Collections; 045 import java.util.HashMap; 046 import java.util.HashSet; 047 import java.util.List; 048 import java.util.Map; 049 import java.util.Set; 050 import java.util.concurrent.locks.Lock; 051 052 /** 053 * Manages the creation and upkeep of resource permissions, and provides 054 * methods for granting, revoking, and checking permissions. 055 * 056 * <p> 057 * Before attempting to read any of the documentation for this class, first 058 * read {@link com.liferay.portal.model.impl.ResourcePermissionImpl} for an 059 * explanation of scoping. 060 * </p> 061 * 062 * @author Brian Wing Shun Chan 063 * @author Raymond Augé 064 * @author Connor McKay 065 */ 066 public class ResourcePermissionLocalServiceImpl 067 extends ResourcePermissionLocalServiceBaseImpl { 068 069 /** 070 * Grants the role permission at the scope to perform the action on 071 * resources of the type. Existing actions are retained. 072 * 073 * <p> 074 * This method cannot be used to grant individual scope permissions, but is 075 * only intended for adding permissions at the company, group, and 076 * group-template scopes. For example, this method could be used to grant a 077 * company scope permission to edit message board posts. 078 * </p> 079 * 080 * <p> 081 * If a company scope permission is granted to resources that the role 082 * already had group scope permissions to, the group scope permissions are 083 * deleted. Likewise, if a group scope permission is granted to resources 084 * that the role already had company scope permissions to, the company 085 * scope permissions are deleted. Be aware that this latter behavior can 086 * result in an overall reduction in permissions for the role. 087 * </p> 088 * 089 * <p> 090 * Depending on the scope, the value of <code>primKey</code> will have 091 * different meanings. For more information, see {@link 092 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 093 * </p> 094 * 095 * @param companyId the primary key of the company 096 * @param name the resource's name, which can be either a class name or a 097 * portlet ID 098 * @param scope the scope. This method only supports company, group, and 099 * group-template scope. 100 * @param primKey the primary key 101 * @param roleId the primary key of the role 102 * @param actionId the action ID 103 * @throws PortalException if scope was set to individual scope or if a 104 * role with the primary key or a resource action with the name and 105 * action ID could not be found 106 * @throws SystemException if a system exception occurred 107 */ 108 public void addResourcePermission( 109 long companyId, String name, int scope, String primKey, long roleId, 110 String actionId) 111 throws PortalException, SystemException { 112 113 if (scope == ResourceConstants.SCOPE_COMPANY) { 114 115 // Remove group permission 116 117 removeResourcePermissions( 118 companyId, name, ResourceConstants.SCOPE_GROUP, roleId, 119 actionId); 120 } 121 else if (scope == ResourceConstants.SCOPE_GROUP) { 122 123 // Remove company permission 124 125 removeResourcePermissions( 126 companyId, name, ResourceConstants.SCOPE_COMPANY, roleId, 127 actionId); 128 } 129 else if (scope == ResourceConstants.SCOPE_INDIVIDUAL) { 130 throw new NoSuchResourcePermissionException(); 131 } 132 133 updateResourcePermission( 134 companyId, name, scope, primKey, roleId, 0, new String[] {actionId}, 135 ResourcePermissionConstants.OPERATOR_ADD); 136 137 PermissionCacheUtil.clearCache(); 138 } 139 140 /** 141 * Grants the role permissions at the scope to perform the actions on all 142 * resources of the type. Existing actions are retained. 143 * 144 * <p> 145 * This method should only be used to add default permissions to existing 146 * resources en masse during upgrades or while verifying permissions. For 147 * example, this method could be used to grant site members individual 148 * scope permissions to view all blog posts. 149 * </p> 150 * 151 * @param resourceName the resource's name, which can be either a class 152 * name or a portlet ID 153 * @param roleName the role's name 154 * @param scope the scope 155 * @param resourceActionBitwiseValue the bitwise IDs of the actions 156 * @throws SystemException if a system exception occurred 157 */ 158 public void addResourcePermissions( 159 String resourceName, String roleName, int scope, 160 long resourceActionBitwiseValue) 161 throws SystemException { 162 163 List<Role> roles = rolePersistence.findByName(roleName); 164 165 for (Role role : roles) { 166 List<String> primKeys = resourcePermissionFinder.findByC_N_S( 167 role.getCompanyId(), resourceName, scope); 168 169 for (String primKey : primKeys) { 170 List<ResourcePermission> resourcePermissions = 171 resourcePermissionPersistence.findByC_N_S_P_R( 172 role.getCompanyId(), resourceName, scope, primKey, 173 role.getRoleId()); 174 175 ResourcePermission resourcePermission = null; 176 177 if (resourcePermissions.isEmpty()) { 178 long resourcePermissionId = counterLocalService.increment( 179 ResourcePermission.class.getName()); 180 181 resourcePermission = resourcePermissionPersistence.create( 182 resourcePermissionId); 183 184 resourcePermission.setCompanyId(role.getCompanyId()); 185 resourcePermission.setName(resourceName); 186 resourcePermission.setScope(scope); 187 resourcePermission.setPrimKey(primKey); 188 resourcePermission.setRoleId(role.getRoleId()); 189 } 190 else { 191 resourcePermission = resourcePermissions.get(0); 192 } 193 194 long actionIdsLong = resourcePermission.getActionIds(); 195 196 actionIdsLong |= resourceActionBitwiseValue; 197 198 resourcePermission.setActionIds(actionIdsLong); 199 200 resourcePermissionPersistence.update(resourcePermission, false); 201 } 202 } 203 } 204 205 /** 206 * Deletes the resource permission. This method should not be confused with 207 * any of the <code>removeResourcePermission</code> methods, as its purpose 208 * is very different. This method should only be used for deleting a 209 * resource permission that refers to a resource when that resource is 210 * deleted. For example this method could be used to delete a permission to 211 * a blog post when it is deleted. 212 * 213 * @param resourcePermissionId the primary key of the resource permission 214 * @throws PortalException if a portal exceptional occurred 215 * @throws SystemException if a system exception occurred 216 */ 217 @Override 218 public void deleteResourcePermission(long resourcePermissionId) 219 throws PortalException, SystemException { 220 221 resourcePermissionPersistence.remove(resourcePermissionId); 222 } 223 224 /** 225 * Deletes all resource permissions at the scope to resources of the type. 226 * This method should not be confused with any of the 227 * <code>removeResourcePermission</code> methods, as its purpose is very 228 * different. This method should only be used for deleting resource 229 * permissions that refer to a resource when that resource is deleted. For 230 * example this method could be used to delete all individual scope 231 * permissions to a blog post when it is deleted. 232 * 233 * <p> 234 * Depending on the scope, the value of <code>primKey</code> will have 235 * different meanings. For more information, see {@link 236 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 237 * </p> 238 * 239 * @param companyId the primary key of the company 240 * @param name the resource's name, which can be either a class name or a 241 * portlet ID 242 * @param scope the scope 243 * @param primKey the primary key 244 * @throws PortalException if a portal exception occurred 245 * @throws SystemException if a system exception occurred 246 */ 247 public void deleteResourcePermissions( 248 long companyId, String name, int scope, long primKey) 249 throws PortalException, SystemException { 250 251 deleteResourcePermissions( 252 companyId, name, scope, String.valueOf(primKey)); 253 } 254 255 /** 256 * Deletes all resource permissions at the scope to resources of the type. 257 * This method should not be confused with any of the 258 * <code>removeResourcePermission</code> methods, as its purpose is very 259 * different. This method should only be used for deleting resource 260 * permissions that refer to a resource when that resource is deleted. For 261 * example this method could be used to delete all individual scope 262 * permissions to a blog post when it is deleted. 263 * 264 * <p> 265 * Depending on the scope, the value of <code>primKey</code> will have 266 * different meanings. For more information, see {@link 267 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 268 * </p> 269 * 270 * @param companyId the primary key of the company 271 * @param name the resource's name, which can be either a class name or a 272 * portlet ID 273 * @param scope the scope 274 * @param primKey the primary key 275 * @throws PortalException if a portal exception occurred 276 * @throws SystemException if a system exception occurred 277 */ 278 public void deleteResourcePermissions( 279 long companyId, String name, int scope, String primKey) 280 throws PortalException, SystemException { 281 282 List<ResourcePermission> resourcePermissions = 283 resourcePermissionPersistence.findByC_N_S_P( 284 companyId, name, scope, primKey); 285 286 for (ResourcePermission resourcePermission : resourcePermissions) { 287 deleteResourcePermission( 288 resourcePermission.getResourcePermissionId()); 289 } 290 } 291 292 /** 293 * Returns the intersection of action IDs the role has permission at the 294 * scope to perform on resources of the type. 295 * 296 * @param companyId he primary key of the company 297 * @param name the resource's name, which can be either a class name or a 298 * portlet ID 299 * @param scope the scope 300 * @param primKey the primary key 301 * @param roleId the primary key of the role 302 * @param actionIds the action IDs 303 * @return the intersection of action IDs the role has permission at the 304 * scope to perform on resources of the type 305 * @throws PortalException if a resouce action could not be found for any 306 * one of the actions on the resource 307 * @throws SystemException if a system exception occurred 308 */ 309 public List<String> getAvailableResourcePermissionActionIds( 310 long companyId, String name, int scope, String primKey, long roleId, 311 Collection<String> actionIds) 312 throws PortalException, SystemException { 313 314 List<ResourcePermission> resourcePermissions = 315 resourcePermissionPersistence.findByC_N_S_P_R( 316 companyId, name, scope, primKey, roleId); 317 318 if (resourcePermissions.isEmpty()) { 319 return Collections.emptyList(); 320 } 321 322 ResourcePermission resourcePermission = resourcePermissions.get(0); 323 324 List<String> availableActionIds = new ArrayList<String>( 325 actionIds.size()); 326 327 for (String actionId : actionIds) { 328 ResourceAction resourceAction = 329 resourceActionLocalService.getResourceAction(name, actionId); 330 331 if (hasActionId(resourcePermission, resourceAction)) { 332 availableActionIds.add(actionId); 333 } 334 } 335 336 return availableActionIds; 337 } 338 339 public Map<Long, Set<String>> getAvailableResourcePermissionActionIds( 340 long companyId, String name, int scope, String primKey, 341 long[] roleIds, Collection<String> actionIds) 342 throws PortalException, SystemException { 343 344 List<ResourcePermission> resourcePermissions = 345 resourcePermissionPersistence.findByC_N_S_P_R( 346 companyId, name, scope, primKey, roleIds); 347 348 if (resourcePermissions.isEmpty()) { 349 return Collections.emptyMap(); 350 } 351 352 Map<Long, Set<String>> roleIdsToActionIds = 353 new HashMap<Long, Set<String>>(); 354 355 for (ResourcePermission resourcePermission : resourcePermissions) { 356 long roleId = resourcePermission.getRoleId(); 357 358 Set<String> availableActionIds = roleIdsToActionIds.get(roleId); 359 360 if (availableActionIds != null) { 361 continue; 362 } 363 364 availableActionIds = new HashSet<String>(); 365 366 roleIdsToActionIds.put(roleId, availableActionIds); 367 368 for (String actionId : actionIds) { 369 ResourceAction resourceAction = 370 resourceActionLocalService.getResourceAction( 371 name, actionId); 372 373 if (hasActionId(resourcePermission, resourceAction)) { 374 availableActionIds.add(actionId); 375 } 376 } 377 } 378 379 return roleIdsToActionIds; 380 } 381 382 /** 383 * Returns the resource permission for the role at the scope to perform the 384 * actions on resources of the type. 385 * 386 * @param companyId the primary key of the company 387 * @param name the resource's name, which can be either a class name or a 388 * portlet ID 389 * @param scope the scope 390 * @param primKey the primary key 391 * @param roleId the primary key of the role 392 * @return the resource permission for the role at the scope to perform the 393 * actions on resources of the type 394 * @throws PortalException if no matching resources could be found 395 * @throws SystemException if a system exception occurred 396 */ 397 public ResourcePermission getResourcePermission( 398 long companyId, String name, int scope, String primKey, long roleId) 399 throws PortalException, SystemException { 400 401 List<ResourcePermission> resourcePermissions = 402 resourcePermissionPersistence.findByC_N_S_P_R( 403 companyId, name, scope, primKey, roleId); 404 405 if (!resourcePermissions.isEmpty()) { 406 return resourcePermissions.get(0); 407 } 408 409 StringBundler sb = new StringBundler(11); 410 411 sb.append("No ResourcePermission exists with the key {companyId="); 412 sb.append(companyId); 413 sb.append(", name="); 414 sb.append(name); 415 sb.append(", scope="); 416 sb.append(scope); 417 sb.append(", primKey="); 418 sb.append(primKey); 419 sb.append(", roleId="); 420 sb.append(roleId); 421 sb.append("}"); 422 423 throw new NoSuchResourcePermissionException(sb.toString()); 424 } 425 426 /** 427 * Returns all the resource permissions at the scope of the type. 428 * 429 * @param companyId the primary key of the company 430 * @param name the resource's name, which can be either a class name or a 431 * portlet ID 432 * @param scope the scope 433 * @param primKey the primary key 434 * @return the resource permissions at the scope of the type 435 * @throws SystemException if a system exception occurred 436 */ 437 public List<ResourcePermission> getResourcePermissions( 438 long companyId, String name, int scope, String primKey) 439 throws SystemException { 440 441 return resourcePermissionPersistence.findByC_N_S_P( 442 companyId, name, scope, primKey); 443 } 444 445 /** 446 * Returns the number of resource permissions at the scope of the type. 447 * 448 * @param companyId the primary key of the company 449 * @param name the resource's name, which can be either a class name or a 450 * portlet ID 451 * @param scope the scope 452 * @param primKey the primary key 453 * @return the number of resource permissions at the scope of the type 454 * @throws SystemException if a system exception occurred 455 */ 456 public int getResourcePermissionsCount( 457 long companyId, String name, int scope, String primKey) 458 throws SystemException { 459 460 return resourcePermissionPersistence.countByC_N_S_P( 461 companyId, name, scope, primKey); 462 } 463 464 /** 465 * Returns the resource permissions that apply to the resource. 466 * 467 * @param companyId the primary key of the resource's company 468 * @param groupId the primary key of the resource's group 469 * @param name the resource's name, which can be either a class name or a 470 * portlet ID 471 * @param primKey the primary key of the resource 472 * @return the resource permissions associated with the resource 473 * @throws SystemException if a system exception occurred 474 */ 475 public List<ResourcePermission> getResourceResourcePermissions( 476 long companyId, long groupId, String name, String primKey) 477 throws SystemException { 478 479 return resourcePermissionFinder.findByResource( 480 companyId, groupId, name, primKey); 481 } 482 483 /** 484 * Returns all the resource permissions for the role. 485 * 486 * @param roleId the primary key of the role 487 * @return the resource permissions for the role 488 * @throws SystemException if a system exception occurred 489 */ 490 public List<ResourcePermission> getRoleResourcePermissions(long roleId) 491 throws SystemException { 492 493 return resourcePermissionPersistence.findByRoleId(roleId); 494 } 495 496 /** 497 * Returns a range of all the resource permissions for the role at the 498 * scopes. 499 * 500 * <p> 501 * Useful when paginating results. Returns a maximum of <code>end - 502 * start</code> instances. <code>start</code> and <code>end</code> are not 503 * primary keys, they are indexes in the result set. Thus, <code>0</code> 504 * refers to the first result in the set. Setting both <code>start</code> 505 * and <code>end</code> to {@link 506 * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the 507 * full result set. 508 * </p> 509 * 510 * @param roleId the primary key of the role 511 * @param scopes the scopes 512 * @param start the lower bound of the range of results 513 * @param end the upper bound of the range of results (not inclusive) 514 * @return the range of resource permissions for the role at the scopes 515 * @throws SystemException if a system exception occurred 516 */ 517 public List<ResourcePermission> getRoleResourcePermissions( 518 long roleId, int[] scopes, int start, int end) 519 throws SystemException { 520 521 return resourcePermissionFinder.findByR_S(roleId, scopes, start, end); 522 } 523 524 /** 525 * Returns all the resource permissions where scope = any ?. 526 * 527 * <p> 528 * Useful when paginating results. Returns a maximum of <code>end - 529 * start</code> instances. <code>start</code> and <code>end</code> are not 530 * primary keys, they are indexes in the result set. Thus, <code>0</code> 531 * refers to the first result in the set. Setting both <code>start</code> 532 * and <code>end</code> to {@link 533 * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the 534 * full result set. 535 * </p> 536 * 537 * @param scopes the scopes 538 * @return the resource permissions where scope = any ? 539 * @throws SystemException if a system exception occurred 540 */ 541 public List<ResourcePermission> getScopeResourcePermissions(int[] scopes) 542 throws SystemException { 543 544 return resourcePermissionPersistence.findByScope(scopes); 545 } 546 547 /** 548 * Returns <code>true</code> if the resource permission grants permission 549 * to perform the resource action. Note that this method does not ensure 550 * that the resource permission refers to the same type of resource as the 551 * resource action. 552 * 553 * @param resourcePermission the resource permission 554 * @param resourceAction the resource action 555 * @return <code>true</code> if the resource permission grants permission 556 * to perform the resource action 557 */ 558 public boolean hasActionId( 559 ResourcePermission resourcePermission, ResourceAction resourceAction) { 560 561 long actionIds = resourcePermission.getActionIds(); 562 long bitwiseValue = resourceAction.getBitwiseValue(); 563 564 if ((actionIds & bitwiseValue) == bitwiseValue) { 565 return true; 566 } 567 else { 568 return false; 569 } 570 } 571 572 /** 573 * Returns <code>true</code> if the roles have permission at the scope to 574 * perform the action on the resources. 575 * 576 * <p> 577 * Depending on the scope, the value of <code>primKey</code> will have 578 * different meanings. For more information, see {@link 579 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 580 * </p> 581 * 582 * @param resources the resources 583 * @param roleIds the primary keys of the roles 584 * @param actionId the action ID 585 * @return <code>true</code> if any one of the roles has permission to 586 * perform the action on any one of the resources; 587 * <code>false</code> otherwise 588 * @throws PortalException if any one of the roles with the primary keys 589 * could not be found or if a resource action with the name and 590 * action ID could not be found 591 * @throws SystemException if a system exception occurred 592 */ 593 public boolean hasResourcePermission( 594 List<Resource> resources, long[] roleIds, String actionId) 595 throws PortalException, SystemException { 596 597 // Iterate the list of resources in reverse order to test permissions 598 // from company scope to individual scope because it is more likely that 599 // a permission is assigned at a higher scope. Optimizing this method 600 // to one SQL call may actually slow things down since most of the calls 601 // will pull from the cache after the first request. 602 603 for (int i = resources.size() - 1; i >= 0; i--) { 604 Resource resource = resources.get(i); 605 606 if (hasResourcePermission( 607 resource.getCompanyId(), resource.getName(), 608 resource.getScope(), resource.getPrimKey(), roleIds, 609 actionId)) { 610 611 return true; 612 } 613 } 614 615 return false; 616 } 617 618 /** 619 * Returns <code>true</code> if the role has permission at the scope to 620 * perform the action on resources of the type. 621 * 622 * <p> 623 * Depending on the scope, the value of <code>primKey</code> will have 624 * different meanings. For more information, see {@link 625 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 626 * </p> 627 * 628 * @param companyId the primary key of the company 629 * @param name the resource's name, which can be either a class name or a 630 * portlet ID 631 * @param scope the scope 632 * @param primKey the primary key 633 * @param roleId the primary key of the role 634 * @param actionId the action ID 635 * @return <code>true</code> if the role has permission to perform the 636 * action on the resource; <code>false</code> otherwise 637 * @throws PortalException if a role with the primary key or a resource 638 * action with the name and action ID could not be found 639 * @throws SystemException if a system exception occurred 640 */ 641 public boolean hasResourcePermission( 642 long companyId, String name, int scope, String primKey, long roleId, 643 String actionId) 644 throws PortalException, SystemException { 645 646 return hasResourcePermission( 647 companyId, name, scope, primKey, new long[] {roleId}, actionId); 648 } 649 650 /** 651 * Returns <code>true</code> if the roles have permission at the scope to 652 * perform the action on resources of the type. 653 * 654 * <p> 655 * Depending on the scope, the value of <code>primKey</code> will have 656 * different meanings. For more information, see {@link 657 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 658 * </p> 659 * 660 * @param companyId the primary key of the company 661 * @param name the resource's name, which can be either a class name or a 662 * portlet ID 663 * @param scope the scope 664 * @param primKey the primary key 665 * @param roleIds the primary keys of the roles 666 * @param actionId the action ID 667 * @return <code>true</code> if any one of the roles has permission to 668 * perform the action on the resource; <code>false</code> otherwise 669 * @throws PortalException if any one of the roles with the primary keys 670 * could not be found or if a resource action with the name and 671 * action ID could not be found 672 * @throws SystemException if a system exception occurred 673 */ 674 public boolean hasResourcePermission( 675 long companyId, String name, int scope, String primKey, 676 long[] roleIds, String actionId) 677 throws PortalException, SystemException { 678 679 ResourceAction resourceAction = 680 resourceActionLocalService.getResourceAction(name, actionId); 681 682 DB db = DBFactoryUtil.getDB(); 683 684 String dbType = db.getType(); 685 686 if ((roleIds.length > 687 PropsValues. 688 PERMISSIONS_ROLE_RESOURCE_PERMISSION_QUERY_THRESHOLD) && 689 !dbType.equals(DB.TYPE_DERBY) && 690 !dbType.equals(DB.TYPE_JDATASTORE) && 691 !dbType.equals(DB.TYPE_SAP)) { 692 693 int count = resourcePermissionFinder.countByC_N_S_P_R_A( 694 companyId, name, scope, primKey, roleIds, 695 resourceAction.getBitwiseValue()); 696 697 if (count > 0) { 698 return true; 699 } 700 } 701 else { 702 List<ResourcePermission> resourcePermissions = 703 resourcePermissionPersistence.findByC_N_S_P_R( 704 companyId, name, scope, primKey, roleIds); 705 706 if (resourcePermissions.isEmpty()) { 707 return false; 708 } 709 710 for (ResourcePermission resourcePermission : resourcePermissions) { 711 if (hasActionId(resourcePermission, resourceAction)) { 712 return true; 713 } 714 } 715 716 } 717 718 return false; 719 } 720 721 /** 722 * Returns <code>true</code> if the role has permission at the scope to 723 * perform the action on the resource. 724 * 725 * <p> 726 * Depending on the scope, the value of <code>primKey</code> will have 727 * different meanings. For more information, see {@link 728 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 729 * </p> 730 * 731 * @param companyId the primary key of the company 732 * @param name the resource's name, which can be either a class name or a 733 * portlet ID 734 * @param scope the scope 735 * @param roleId the primary key of the role 736 * @param actionId the action ID 737 * @return <code>true</code> if the role has permission to perform the 738 * action on the resource; <code>false</code> otherwise 739 * @throws PortalException if a role with the primary key or a resource 740 * action with the name and action ID could not be found 741 * @throws SystemException if a system exception occurred 742 */ 743 public boolean hasScopeResourcePermission( 744 long companyId, String name, int scope, long roleId, 745 String actionId) 746 throws PortalException, SystemException { 747 748 List<ResourcePermission> resourcePermissions = 749 resourcePermissionPersistence.findByC_N_S(companyId, name, scope); 750 751 for (ResourcePermission resourcePermission : resourcePermissions) { 752 if (hasResourcePermission( 753 companyId, name, scope, resourcePermission.getPrimKey(), 754 roleId, actionId)) { 755 756 return true; 757 } 758 } 759 760 return false; 761 } 762 763 /** 764 * Reassigns all the resource permissions from the source role to the 765 * destination role, and deletes the source role. 766 * 767 * @param fromRoleId the primary key of the source role 768 * @param toRoleId the primary key of the destination role 769 * @throws PortalException if a role with the primary key could not be 770 * found 771 * @throws SystemException if a system exception occurred 772 */ 773 public void mergePermissions(long fromRoleId, long toRoleId) 774 throws PortalException, SystemException { 775 776 Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId); 777 Role toRole = rolePersistence.findByPrimaryKey(toRoleId); 778 779 if (fromRole.getType() != toRole.getType()) { 780 throw new PortalException("Role types are mismatched"); 781 } 782 else if (PortalUtil.isSystemRole(toRole.getName())) { 783 throw new PortalException("Cannot move permissions to system role"); 784 } 785 else if (PortalUtil.isSystemRole(fromRole.getName())) { 786 throw new PortalException( 787 "Cannot move permissions from system role"); 788 } 789 790 List<ResourcePermission> resourcePermissions = 791 getRoleResourcePermissions(fromRoleId); 792 793 for (ResourcePermission resourcePermission : resourcePermissions) { 794 resourcePermission.setRoleId(toRoleId); 795 796 resourcePermissionPersistence.update(resourcePermission, false); 797 } 798 799 roleLocalService.deleteRole(fromRoleId); 800 801 PermissionCacheUtil.clearCache(); 802 } 803 804 /** 805 * Grants the role default permissions to all the resources of the type and 806 * at the scope stored in the resource permission, deletes the resource 807 * permission, and deletes the resource permission's role if it has no 808 * permissions remaining. 809 * 810 * @param resourcePermissionId the primary key of the resource permission 811 * @param toRoleId the primary key of the role 812 * @throws PortalException if a resource permission or role with the 813 * primary key could not be found 814 * @throws SystemException if a system exception occurred 815 */ 816 public void reassignPermissions(long resourcePermissionId, long toRoleId) 817 throws PortalException, SystemException { 818 819 ResourcePermission resourcePermission = getResourcePermission( 820 resourcePermissionId); 821 822 long companyId = resourcePermission.getCompanyId(); 823 String name = resourcePermission.getName(); 824 int scope = resourcePermission.getScope(); 825 String primKey = resourcePermission.getPrimKey(); 826 long fromRoleId = resourcePermission.getRoleId(); 827 828 Role toRole = roleLocalService.getRole(toRoleId); 829 830 List<String> actionIds = null; 831 832 if (toRole.getType() == RoleConstants.TYPE_REGULAR) { 833 actionIds = ResourceActionsUtil.getModelResourceActions(name); 834 } 835 else { 836 actionIds = ResourceActionsUtil.getModelResourceGroupDefaultActions( 837 name); 838 } 839 840 setResourcePermissions( 841 companyId, name, scope, primKey, toRoleId, 842 actionIds.toArray(new String[actionIds.size()])); 843 844 resourcePermissionPersistence.remove(resourcePermissionId); 845 846 List<ResourcePermission> resourcePermissions = 847 getRoleResourcePermissions(fromRoleId); 848 849 if (resourcePermissions.isEmpty()) { 850 roleLocalService.deleteRole(fromRoleId); 851 } 852 } 853 854 /** 855 * Revokes permission at the scope from the role to perform the action on 856 * resources of the type. For example, this method could be used to revoke 857 * a group scope permission to edit blog posts. 858 * 859 * <p> 860 * Depending on the scope, the value of <code>primKey</code> will have 861 * different meanings. For more information, see {@link 862 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 863 * </p> 864 * 865 * @param companyId the primary key of the company 866 * @param name the resource's name, which can be either a class name or a 867 * portlet ID 868 * @param scope the scope 869 * @param primKey the primary key 870 * @param roleId the primary key of the role 871 * @param actionId the action ID 872 * @throws PortalException if a role with the primary key or a resource 873 * action with the name and action ID could not be found 874 * @throws SystemException if a system exception occurred 875 */ 876 public void removeResourcePermission( 877 long companyId, String name, int scope, String primKey, long roleId, 878 String actionId) 879 throws PortalException, SystemException { 880 881 updateResourcePermission( 882 companyId, name, scope, primKey, roleId, 0, new String[] {actionId}, 883 ResourcePermissionConstants.OPERATOR_REMOVE); 884 885 PermissionCacheUtil.clearCache(); 886 } 887 888 /** 889 * Revokes all permissions at the scope from the role to perform the action 890 * on resources of the type. For example, this method could be used to 891 * revoke all individual scope permissions to edit blog posts from site 892 * members. 893 * 894 * @param companyId the primary key of the company 895 * @param name the resource's name, which can be either a class name or a 896 * portlet ID 897 * @param scope the scope 898 * @param roleId the primary key of the role 899 * @param actionId the action ID 900 * @throws PortalException if a role with the primary key or a resource 901 * action with the name and action ID could not be found 902 * @throws SystemException if a system exception occurred 903 */ 904 public void removeResourcePermissions( 905 long companyId, String name, int scope, long roleId, 906 String actionId) 907 throws PortalException, SystemException { 908 909 List<ResourcePermission> resourcePermissions = 910 resourcePermissionPersistence.findByC_N_S(companyId, name, scope); 911 912 for (ResourcePermission resourcePermission : resourcePermissions) { 913 updateResourcePermission( 914 companyId, name, scope, resourcePermission.getPrimKey(), roleId, 915 0, new String[] {actionId}, 916 ResourcePermissionConstants.OPERATOR_REMOVE); 917 } 918 919 PermissionCacheUtil.clearCache(); 920 } 921 922 /** 923 * Updates the role's permissions at the scope, setting the actions that 924 * can be performed on resources of the type, also setting the owner of any 925 * newly created resource permissions. Existing actions are replaced. 926 * 927 * <p> 928 * This method can be used to set permissions at any scope, but it is 929 * generally only used at the individual scope. For example, it could be 930 * used to set the guest permissions on a blog post. 931 * </p> 932 * 933 * <p> 934 * Depending on the scope, the value of <code>primKey</code> will have 935 * different meanings. For more information, see {@link 936 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 937 * </p> 938 * 939 * @param companyId the primary key of the company 940 * @param name the resource's name, which can be either a class name or a 941 * portlet ID 942 * @param scope the scope 943 * @param primKey the primary key 944 * @param roleId the primary key of the role 945 * @param ownerId the primary key of the owner (generally the user that 946 * created the resource) 947 * @param actionIds the action IDs of the actions 948 * @throws PortalException if a role with the primary key or a resource 949 * action with the name and action ID could not be found 950 * @throws SystemException if a system exception occurred 951 */ 952 public void setOwnerResourcePermissions( 953 long companyId, String name, int scope, String primKey, long roleId, 954 long ownerId, String[] actionIds) 955 throws PortalException, SystemException { 956 957 updateResourcePermission( 958 companyId, name, scope, primKey, roleId, ownerId, actionIds, 959 ResourcePermissionConstants.OPERATOR_SET); 960 } 961 962 /** 963 * Updates the role's permissions at the scope, setting the actions that 964 * can be performed on resources of the type. Existing actions are 965 * replaced. 966 * 967 * <p> 968 * This method can be used to set permissions at any scope, but it is 969 * generally only used at the individual scope. For example, it could be 970 * used to set the guest permissions on a blog post. 971 * </p> 972 * 973 * <p> 974 * Depending on the scope, the value of <code>primKey</code> will have 975 * different meanings. For more information, see {@link 976 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 977 * </p> 978 * 979 * @param companyId the primary key of the company 980 * @param name the resource's name, which can be either a class name or a 981 * portlet ID 982 * @param scope the scope 983 * @param primKey the primary key 984 * @param roleId the primary key of the role 985 * @param actionIds the action IDs of the actions 986 * @throws PortalException if a role with the primary key or a resource 987 * action with the name and action ID could not be found 988 * @throws SystemException if a system exception occurred 989 */ 990 public void setResourcePermissions( 991 long companyId, String name, int scope, String primKey, long roleId, 992 String[] actionIds) 993 throws PortalException, SystemException { 994 995 updateResourcePermission( 996 companyId, name, scope, primKey, roleId, 0, actionIds, 997 ResourcePermissionConstants.OPERATOR_SET); 998 } 999 1000 /** 1001 * Updates the role's permissions at the scope, setting the actions that can 1002 * be performed on resources of the type. Existing actions are replaced. 1003 * 1004 * <p> 1005 * This method can be used to set permissions at any scope, but it is 1006 * generally only used at the individual scope. For example, it could be 1007 * used to set the guest permissions on a blog post. 1008 * </p> 1009 * 1010 * <p> 1011 * Depending on the scope, the value of <code>primKey</code> will have 1012 * different meanings. For more information, see {@link 1013 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 1014 * </p> 1015 * 1016 * @param companyId the primary key of the company 1017 * @param name the resource's name, which can be either a class name or a 1018 * portlet ID 1019 * @param scope the scope 1020 * @param primKey the primary key 1021 * @param roleIdsToActionIds a map of role IDs to action IDs of the actions 1022 * @throws PortalException if a role with the primary key or a resource 1023 * action with the name and action ID could not be found 1024 * @throws SystemException if a system exception occurred 1025 */ 1026 public void setResourcePermissions( 1027 long companyId, String name, int scope, String primKey, 1028 Map<Long, String[]> roleIdsToActionIds) 1029 throws PortalException, SystemException { 1030 1031 updateResourcePermission( 1032 companyId, name, scope, primKey, 0, roleIdsToActionIds, 1033 ResourcePermissionConstants.OPERATOR_SET); 1034 } 1035 1036 protected void doUpdateResourcePermission( 1037 long companyId, String name, int scope, String primKey, 1038 long ownerId, long roleId, String[] actionIds, int operator) 1039 throws PortalException, SystemException { 1040 1041 ResourcePermission resourcePermission = null; 1042 1043 Map<Long, ResourcePermission> resourcePermissionsMap = 1044 ResourcePermissionsThreadLocal.getResourcePermissions(); 1045 1046 if (resourcePermissionsMap != null) { 1047 resourcePermission = resourcePermissionsMap.get(roleId); 1048 } 1049 else { 1050 List<ResourcePermission> resourcePermissions = 1051 resourcePermissionPersistence.findByC_N_S_P_R( 1052 companyId, name, scope, primKey, roleId); 1053 1054 if (!resourcePermissions.isEmpty()) { 1055 resourcePermission = resourcePermissions.get(0); 1056 } 1057 } 1058 1059 if (resourcePermission == null) { 1060 if (((operator == ResourcePermissionConstants.OPERATOR_ADD) || 1061 (operator == ResourcePermissionConstants.OPERATOR_SET)) && 1062 (actionIds.length == 0)) { 1063 1064 return; 1065 } 1066 1067 if (operator == ResourcePermissionConstants.OPERATOR_REMOVE) { 1068 return; 1069 } 1070 1071 long resourcePermissionId = counterLocalService.increment( 1072 ResourcePermission.class.getName()); 1073 1074 resourcePermission = resourcePermissionPersistence.create( 1075 resourcePermissionId); 1076 1077 resourcePermission.setCompanyId(companyId); 1078 resourcePermission.setName(name); 1079 resourcePermission.setScope(scope); 1080 resourcePermission.setPrimKey(primKey); 1081 resourcePermission.setRoleId(roleId); 1082 resourcePermission.setOwnerId(ownerId); 1083 } 1084 1085 long actionIdsLong = resourcePermission.getActionIds(); 1086 1087 if (operator == ResourcePermissionConstants.OPERATOR_SET) { 1088 actionIdsLong = 0; 1089 } 1090 1091 for (String actionId : actionIds) { 1092 ResourceAction resourceAction = 1093 resourceActionLocalService.getResourceAction(name, actionId); 1094 1095 if ((operator == ResourcePermissionConstants.OPERATOR_ADD) || 1096 (operator == ResourcePermissionConstants.OPERATOR_SET)) { 1097 1098 actionIdsLong |= resourceAction.getBitwiseValue(); 1099 } 1100 else { 1101 actionIdsLong = 1102 actionIdsLong & (~resourceAction.getBitwiseValue()); 1103 } 1104 } 1105 1106 resourcePermission.setActionIds(actionIdsLong); 1107 1108 resourcePermissionPersistence.update(resourcePermission, false); 1109 1110 PermissionCacheUtil.clearCache(); 1111 1112 SearchEngineUtil.updatePermissionFields(name, primKey); 1113 } 1114 1115 protected void doUpdateResourcePermission( 1116 long companyId, String name, int scope, String primKey, 1117 long ownerId, Map<Long, String[]> roleIdsToActionIds, int operator) 1118 throws PortalException, SystemException { 1119 1120 boolean flushEnabled = PermissionThreadLocal.isFlushEnabled(); 1121 1122 PermissionThreadLocal.setIndexEnabled(false); 1123 1124 try { 1125 for (Map.Entry<Long, String[]> entry : 1126 roleIdsToActionIds.entrySet()) { 1127 1128 long roleId = entry.getKey(); 1129 String[] actionIds = entry.getValue(); 1130 1131 doUpdateResourcePermission( 1132 companyId, name, scope, primKey, ownerId, roleId, actionIds, 1133 operator); 1134 } 1135 } 1136 finally { 1137 PermissionThreadLocal.setIndexEnabled(flushEnabled); 1138 1139 PermissionCacheUtil.clearCache(); 1140 1141 SearchEngineUtil.updatePermissionFields(name, primKey); 1142 } 1143 } 1144 1145 /** 1146 * Updates the role's permissions at the scope, either adding to, removing 1147 * from, or setting the actions that can be performed on resources of the 1148 * type. Automatically creates a new resource permission if none exists, or 1149 * deletes the existing resource permission if it no longer grants 1150 * permissions to perform any action. 1151 * 1152 * <p> 1153 * Depending on the scope, the value of <code>primKey</code> will have 1154 * different meanings. For more information, see {@link 1155 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 1156 * </p> 1157 * 1158 * @param companyId the primary key of the company 1159 * @param name the resource's name, which can be either a class name or a 1160 * portlet ID 1161 * @param scope the scope 1162 * @param primKey the primary key 1163 * @param roleId the primary key of the role 1164 * @param ownerId the primary key of the owner 1165 * @param actionIds the action IDs of the actions 1166 * @param operator whether to add to, remove from, or set/replace the 1167 * existing actions. Possible values can be found in {@link 1168 * ResourcePermissionConstants}. 1169 * @throws PortalException if a role with the primary key or a resource 1170 * action with the name and action ID could not be found 1171 * @throws SystemException if a system exception occurred 1172 */ 1173 protected void updateResourcePermission( 1174 long companyId, String name, int scope, String primKey, long roleId, 1175 long ownerId, String[] actionIds, int operator) 1176 throws PortalException, SystemException { 1177 1178 DB db = DBFactoryUtil.getDB(); 1179 1180 String dbType = db.getType(); 1181 1182 if (!dbType.equals(DB.TYPE_HYPERSONIC)) { 1183 doUpdateResourcePermission( 1184 companyId, name, scope, primKey, ownerId, roleId, actionIds, 1185 operator); 1186 1187 return; 1188 } 1189 1190 StringBundler sb = new StringBundler(9); 1191 1192 sb.append(companyId); 1193 sb.append(StringPool.POUND); 1194 sb.append(name); 1195 sb.append(StringPool.POUND); 1196 sb.append(scope); 1197 sb.append(StringPool.POUND); 1198 sb.append(primKey); 1199 sb.append(StringPool.POUND); 1200 sb.append(roleId); 1201 1202 Class<?> clazz = getClass(); 1203 1204 String groupName = clazz.getName(); 1205 1206 String key = sb.toString(); 1207 1208 Lock lock = LockRegistry.allocateLock(groupName, key); 1209 1210 lock.lock(); 1211 1212 try { 1213 doUpdateResourcePermission( 1214 companyId, name, scope, primKey, ownerId, roleId, actionIds, 1215 operator); 1216 } 1217 finally { 1218 lock.unlock(); 1219 1220 LockRegistry.freeLock(groupName, key); 1221 } 1222 } 1223 1224 /** 1225 * Updates the role's permissions at the scope, either adding to, removing 1226 * from, or setting the actions that can be performed on resources of the 1227 * type. Automatically creates a new resource permission if none exists, or 1228 * deletes the existing resource permission if it no longer grants 1229 * permissions to perform any action. 1230 * 1231 * <p> 1232 * Depending on the scope, the value of <code>primKey</code> will have 1233 * different meanings. For more information, see {@link 1234 * com.liferay.portal.model.impl.ResourcePermissionImpl}. 1235 * </p> 1236 * 1237 * @param companyId the primary key of the company 1238 * @param name the resource's name, which can be either a class name or a 1239 * portlet ID 1240 * @param scope the scope 1241 * @param primKey the primary key 1242 * @param roleId the primary key of the role 1243 * @param ownerId the primary key of the owner 1244 * @param actionIds the action IDs of the actions 1245 * @param operator whether to add to, remove from, or set/replace the 1246 * existing actions. Possible values can be found in {@link 1247 * ResourcePermissionConstants}. 1248 * @throws PortalException if a role with the primary key or a resource 1249 * action with the name and action ID could not be found 1250 * @throws SystemException if a system exception occurred 1251 */ 1252 protected void updateResourcePermission( 1253 long companyId, String name, int scope, String primKey, 1254 long ownerId, Map<Long, String[]> roleIdsToActionIds, int operator) 1255 throws PortalException, SystemException { 1256 1257 DB db = DBFactoryUtil.getDB(); 1258 1259 String dbType = db.getType(); 1260 1261 if (!dbType.equals(DB.TYPE_HYPERSONIC)) { 1262 doUpdateResourcePermission( 1263 companyId, name, scope, primKey, ownerId, roleIdsToActionIds, 1264 operator); 1265 1266 return; 1267 } 1268 1269 StringBundler sb = new StringBundler(9); 1270 1271 sb.append(companyId); 1272 sb.append(StringPool.POUND); 1273 sb.append(name); 1274 sb.append(StringPool.POUND); 1275 sb.append(scope); 1276 sb.append(StringPool.POUND); 1277 sb.append(primKey); 1278 sb.append(StringPool.POUND); 1279 sb.append(StringUtil.merge(roleIdsToActionIds.keySet())); 1280 1281 Class<?> clazz = getClass(); 1282 1283 String groupName = clazz.getName(); 1284 1285 String key = sb.toString(); 1286 1287 Lock lock = LockRegistry.allocateLock(groupName, key); 1288 1289 lock.lock(); 1290 1291 try { 1292 doUpdateResourcePermission( 1293 companyId, name, scope, primKey, ownerId, roleIdsToActionIds, 1294 operator); 1295 } 1296 finally { 1297 lock.unlock(); 1298 1299 LockRegistry.freeLock(groupName, key); 1300 } 1301 } 1302 1303 }