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