/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.service.impl;
import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.Property;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.NoSuchResourceActionException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.model.ResourceAction;
import com.liferay.portal.kernel.model.ResourceBlock;
import com.liferay.portal.kernel.model.ResourceBlockConstants;
import com.liferay.portal.kernel.model.ResourceBlockPermissionsContainer;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.model.ResourcePermission;
import com.liferay.portal.kernel.model.ResourceTypePermission;
import com.liferay.portal.kernel.model.RoleConstants;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
import com.liferay.portal.kernel.spring.aop.Skip;
import com.liferay.portal.kernel.transaction.Propagation;
import com.liferay.portal.kernel.transaction.Transactional;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.security.permission.PermissionCacheUtil;
import com.liferay.portal.service.base.ResourceActionLocalServiceBaseImpl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Brian Wing Shun Chan
* @author Shuyang Zhou
*/
public class ResourceActionLocalServiceImpl
extends ResourceActionLocalServiceBaseImpl {
@Override
public ResourceAction addResourceAction(
String name, String actionId, long bitwiseValue) {
ResourceAction resourceAction = resourceActionPersistence.fetchByN_A(
name, actionId);
if (resourceAction == null) {
long resourceActionId = counterLocalService.increment(
ResourceAction.class.getName());
resourceAction = resourceActionPersistence.create(resourceActionId);
resourceAction.setName(name);
resourceAction.setActionId(actionId);
resourceAction.setBitwiseValue(bitwiseValue);
resourceActionPersistence.update(resourceAction);
}
return resourceAction;
}
@Override
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public void checkResourceActions() {
List<ResourceAction> resourceActions =
resourceActionPersistence.findAll();
for (ResourceAction resourceAction : resourceActions) {
String key = encodeKey(
resourceAction.getName(), resourceAction.getActionId());
_resourceActions.put(key, resourceAction);
}
}
@Override
public void checkResourceActions(String name, List<String> actionIds) {
checkResourceActions(name, actionIds, false);
}
@Override
public void checkResourceActions(
String name, List<String> actionIds, boolean addDefaultActions) {
if ((actionIds.size() > Long.SIZE) ||
((actionIds.size() == Long.SIZE) &&
!actionIds.contains(ActionKeys.VIEW))) {
throw new SystemException(
"There are too many actions for resource " + name);
}
long availableBits = -2;
for (ResourceAction resourceAction : getResourceActions(name)) {
availableBits &= ~resourceAction.getBitwiseValue();
}
List<ResourceAction> newResourceActions = null;
for (String actionId : actionIds) {
String key = encodeKey(name, actionId);
ResourceAction resourceAction = _resourceActions.get(key);
if (resourceAction != null) {
continue;
}
resourceAction = resourceActionPersistence.fetchByN_A(
name, actionId);
if (resourceAction == null) {
long bitwiseValue = 1;
if (!actionId.equals(ActionKeys.VIEW)) {
bitwiseValue = Long.lowestOneBit(availableBits);
availableBits ^= bitwiseValue;
}
try {
resourceAction =
resourceActionLocalService.addResourceAction(
name, actionId, bitwiseValue);
}
catch (Throwable t) {
resourceAction =
resourceActionLocalService.addResourceAction(
name, actionId, bitwiseValue);
}
if (newResourceActions == null) {
newResourceActions = new ArrayList<>();
}
newResourceActions.add(resourceAction);
}
_resourceActions.put(key, resourceAction);
}
if (!addDefaultActions || (newResourceActions == null)) {
return;
}
List<String> groupDefaultActions =
ResourceActionsUtil.getModelResourceGroupDefaultActions(name);
List<String> guestDefaultActions =
ResourceActionsUtil.getModelResourceGuestDefaultActions(name);
long guestBitwiseValue = 0;
long ownerBitwiseValue = 0;
long siteMemberBitwiseValue = 0;
for (ResourceAction resourceAction : newResourceActions) {
String actionId = resourceAction.getActionId();
if (guestDefaultActions.contains(actionId)) {
guestBitwiseValue |= resourceAction.getBitwiseValue();
}
ownerBitwiseValue |= resourceAction.getBitwiseValue();
if (groupDefaultActions.contains(actionId)) {
siteMemberBitwiseValue |= resourceAction.getBitwiseValue();
}
}
if (guestBitwiseValue > 0) {
resourcePermissionLocalService.addResourcePermissions(
name, RoleConstants.GUEST, ResourceConstants.SCOPE_INDIVIDUAL,
guestBitwiseValue);
}
if (ownerBitwiseValue > 0) {
resourcePermissionLocalService.addResourcePermissions(
name, RoleConstants.OWNER, ResourceConstants.SCOPE_INDIVIDUAL,
ownerBitwiseValue);
}
if (siteMemberBitwiseValue > 0) {
resourcePermissionLocalService.addResourcePermissions(
name, RoleConstants.SITE_MEMBER,
ResourceConstants.SCOPE_INDIVIDUAL, siteMemberBitwiseValue);
}
}
@Override
public ResourceAction deleteResourceAction(long resourceActionId)
throws PortalException {
return deleteResourceAction(
resourceActionPersistence.findByPrimaryKey(resourceActionId));
}
@Override
public ResourceAction deleteResourceAction(ResourceAction resourceAction) {
final String name = resourceAction.getName();
final long bitwiseValue = resourceAction.getBitwiseValue();
ActionableDynamicQuery.AddCriteriaMethod addCriteriaMethod =
new ActionableDynamicQuery.AddCriteriaMethod() {
@Override
public void addCriteria(DynamicQuery dynamicQuery) {
Property nameProperty = PropertyFactoryUtil.forName("name");
dynamicQuery.add(nameProperty.eq(name));
}
};
for (Company company : companyLocalService.getCompanies()) {
if (resourceBlockLocalService.isSupported(
resourceAction.getName())) {
ActionableDynamicQuery resourceBlockActionableDynamicQuery =
resourceBlockLocalService.getActionableDynamicQuery();
resourceBlockActionableDynamicQuery.setAddCriteriaMethod(
addCriteriaMethod);
resourceBlockActionableDynamicQuery.setCompanyId(
company.getCompanyId());
resourceBlockActionableDynamicQuery.setPerformActionMethod(
new ActionableDynamicQuery.
PerformActionMethod<ResourceBlock>() {
@Override
public void performAction(ResourceBlock resourceBlock) {
ResourceBlockPermissionsContainer
resourceBlockPermissionsContainer =
resourceBlockPermissionLocalService.
getResourceBlockPermissionsContainer(
resourceBlock.getResourceBlockId());
Set<Long> roleIds =
resourceBlockPermissionsContainer.getRoleIds();
for (long roleId : roleIds) {
resourceBlockPermissionsContainer.
removePermission(roleId, bitwiseValue);
resourceBlockPermissionLocalService.
updateResourceBlockPermission(
resourceBlock.getResourceBlockId(),
roleId, bitwiseValue,
ResourceBlockConstants.OPERATOR_REMOVE);
}
resourceBlock.setPermissionsHash(
resourceBlockPermissionsContainer.
getPermissionsHash());
resourceBlockPersistence.update(resourceBlock);
}
});
try {
resourceBlockActionableDynamicQuery.performActions();
}
catch (PortalException pe) {
throw new SystemException(pe);
}
ActionableDynamicQuery resourceTypeActionableDynamicQuery =
resourceTypePermissionLocalService.
getActionableDynamicQuery();
resourceTypeActionableDynamicQuery.setAddCriteriaMethod(
addCriteriaMethod);
resourceTypeActionableDynamicQuery.setCompanyId(
company.getCompanyId());
resourceTypeActionableDynamicQuery.setPerformActionMethod(
new ActionableDynamicQuery.
PerformActionMethod<ResourceTypePermission>() {
@Override
public void performAction(
ResourceTypePermission resourceTypePermission) {
long actionIds =
resourceTypePermission.getActionIds();
if ((actionIds & bitwiseValue) != 0) {
resourceTypePermission.setActionIds(
actionIds & (~bitwiseValue));
resourceTypePermissionPersistence.update(
resourceTypePermission);
}
}
});
try {
resourceTypeActionableDynamicQuery.performActions();
}
catch (PortalException pe) {
throw new SystemException(pe);
}
}
else {
ActionableDynamicQuery actionableDynamicQuery =
resourcePermissionLocalService.getActionableDynamicQuery();
actionableDynamicQuery.setAddCriteriaMethod(addCriteriaMethod);
actionableDynamicQuery.setCompanyId(company.getCompanyId());
actionableDynamicQuery.setPerformActionMethod(
new ActionableDynamicQuery.
PerformActionMethod<ResourcePermission>() {
@Override
public void performAction(
ResourcePermission resourcePermission) {
long actionIds = resourcePermission.getActionIds();
if ((actionIds & bitwiseValue) != 0) {
actionIds &= ~bitwiseValue;
resourcePermission.setActionIds(actionIds);
resourcePermission.setViewActionId(
actionIds % 2 == 1);
resourcePermissionPersistence.update(
resourcePermission);
}
}
});
try {
actionableDynamicQuery.performActions();
}
catch (PortalException pe) {
throw new SystemException(pe);
}
}
}
_resourceActions.remove(
encodeKey(resourceAction.getName(), resourceAction.getActionId()));
resourceActionPersistence.remove(resourceAction);
PermissionCacheUtil.clearCache();
return resourceAction;
}
@Override
@Skip
public ResourceAction fetchResourceAction(String name, String actionId) {
String key = encodeKey(name, actionId);
return _resourceActions.get(key);
}
@Override
@Skip
public ResourceAction getResourceAction(String name, String actionId)
throws PortalException {
String key = encodeKey(name, actionId);
ResourceAction resourceAction = _resourceActions.get(key);
if (resourceAction == null) {
throw new NoSuchResourceActionException(key);
}
return resourceAction;
}
@Override
public List<ResourceAction> getResourceActions(String name) {
return resourceActionPersistence.findByName(name);
}
@Override
public int getResourceActionsCount(String name) {
return resourceActionPersistence.countByName(name);
}
protected String encodeKey(String name, String actionId) {
return name.concat(StringPool.POUND).concat(actionId);
}
private static final Map<String, ResourceAction> _resourceActions =
new ConcurrentHashMap<>();
}