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