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