/**
* 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.roles.admin.web.internal.portlet;
import com.liferay.application.list.PanelAppRegistry;
import com.liferay.application.list.PanelCategoryRegistry;
import com.liferay.application.list.constants.ApplicationListWebKeys;
import com.liferay.application.list.constants.PanelCategoryKeys;
import com.liferay.application.list.display.context.logic.PanelCategoryHelper;
import com.liferay.portal.kernel.exception.DuplicateRoleException;
import com.liferay.portal.kernel.exception.NoSuchRoleException;
import com.liferay.portal.kernel.exception.RequiredRoleException;
import com.liferay.portal.kernel.exception.RoleAssignmentException;
import com.liferay.portal.kernel.exception.RoleNameException;
import com.liferay.portal.kernel.exception.RolePermissionsException;
import com.liferay.portal.kernel.messaging.proxy.ProxyModeThreadLocal;
import com.liferay.portal.kernel.messaging.proxy.ProxyModeThreadLocalCloseable;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.GroupConstants;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.model.Role;
import com.liferay.portal.kernel.model.RoleConstants;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.security.auth.PrincipalException;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
import com.liferay.portal.kernel.security.permission.comparator.ActionComparator;
import com.liferay.portal.kernel.service.GroupService;
import com.liferay.portal.kernel.service.ResourceBlockLocalService;
import com.liferay.portal.kernel.service.ResourceBlockService;
import com.liferay.portal.kernel.service.ResourcePermissionService;
import com.liferay.portal.kernel.service.RoleLocalService;
import com.liferay.portal.kernel.service.RoleService;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.ServiceContextFactory;
import com.liferay.portal.kernel.service.UserService;
import com.liferay.portal.kernel.servlet.SessionErrors;
import com.liferay.portal.kernel.servlet.SessionMessages;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.Http;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocalizationUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.PortletKeys;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.roles.admin.constants.RolesAdminPortletKeys;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Brian Wing Shun Chan
* @author Jorge Ferrer
* @author Connor McKay
* @author Drew Brokke
*/
@Component(
immediate = true,
property = {
"com.liferay.portlet.css-class-wrapper=portlet-users-admin",
"com.liferay.portlet.display-category=category.hidden",
"com.liferay.portlet.header-portlet-css=/css/main.css",
"com.liferay.portlet.icon=/icons/roles_admin.png",
"com.liferay.portlet.preferences-owned-by-group=true",
"com.liferay.portlet.private-request-attributes=false",
"com.liferay.portlet.private-session-attributes=false",
"com.liferay.portlet.render-weight=50",
"com.liferay.portlet.use-default-template=true",
"javax.portlet.display-name=Roles Admin",
"javax.portlet.expiration-cache=0",
"javax.portlet.init-param.template-path=/",
"javax.portlet.init-param.view-template=/view.jsp",
"javax.portlet.name=" + RolesAdminPortletKeys.ROLES_ADMIN,
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=administrator",
"javax.portlet.supports.mime-type=text/html"
},
service = javax.portlet.Portlet.class
)
public class RolesAdminPortlet extends MVCPortlet {
public void deletePermission(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
long roleId = ParamUtil.getLong(actionRequest, "roleId");
String name = ParamUtil.getString(actionRequest, "name");
int scope = ParamUtil.getInteger(actionRequest, "scope");
String primKey = ParamUtil.getString(actionRequest, "primKey");
String actionId = ParamUtil.getString(actionRequest, "actionId");
Role role = _roleLocalService.getRole(roleId);
String roleName = role.getName();
if (roleName.equals(RoleConstants.ADMINISTRATOR) ||
roleName.equals(RoleConstants.ORGANIZATION_ADMINISTRATOR) ||
roleName.equals(RoleConstants.ORGANIZATION_OWNER) ||
roleName.equals(RoleConstants.OWNER) ||
roleName.equals(RoleConstants.SITE_ADMINISTRATOR) ||
roleName.equals(RoleConstants.SITE_OWNER)) {
throw new RolePermissionsException(roleName);
}
if (_resourceBlockLocalService.isSupported(name)) {
if (scope == ResourceConstants.SCOPE_GROUP) {
_resourceBlockService.removeGroupScopePermission(
themeDisplay.getScopeGroupId(), themeDisplay.getCompanyId(),
GetterUtil.getLong(primKey), name, roleId, actionId);
}
else {
_resourceBlockService.removeCompanyScopePermission(
themeDisplay.getScopeGroupId(), themeDisplay.getCompanyId(),
name, roleId, actionId);
}
}
else {
_resourcePermissionService.removeResourcePermission(
themeDisplay.getScopeGroupId(), themeDisplay.getCompanyId(),
name, scope, primKey, roleId, actionId);
}
// Send redirect
SessionMessages.add(actionRequest, "permissionDeleted");
String redirect = _portal.escapeRedirect(
ParamUtil.getString(actionRequest, "redirect"));
if (Validator.isNotNull(redirect)) {
actionResponse.sendRedirect(redirect);
}
}
public void deleteRole(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
long roleId = ParamUtil.getLong(actionRequest, "roleId");
_roleService.deleteRole(roleId);
}
public void deleteRoles(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
long[] deleteRoleIds = StringUtil.split(
ParamUtil.getString(actionRequest, "deleteRoleIds"), 0L);
for (long roleId : deleteRoleIds) {
_roleService.deleteRole(roleId);
}
}
public Role editRole(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
long roleId = ParamUtil.getLong(actionRequest, "roleId");
String name = ParamUtil.getString(actionRequest, "name");
Map<Locale, String> titleMap = LocalizationUtil.getLocalizationMap(
actionRequest, "title");
Map<Locale, String> descriptionMap =
LocalizationUtil.getLocalizationMap(actionRequest, "description");
int type = ParamUtil.getInteger(
actionRequest, "type", RoleConstants.TYPE_REGULAR);
String subtype = ParamUtil.getString(actionRequest, "subtype");
ServiceContext serviceContext = ServiceContextFactory.getInstance(
Role.class.getName(), actionRequest);
if (roleId <= 0) {
// Add role
Role role = _roleService.addRole(
null, 0, name, titleMap, descriptionMap, type, subtype,
serviceContext);
String redirect = ParamUtil.getString(actionRequest, "redirect");
redirect = _http.setParameter(
redirect, actionResponse.getNamespace() + "roleId",
role.getRoleId());
actionRequest.setAttribute(WebKeys.REDIRECT, redirect);
SessionMessages.add(actionRequest, "roleCreated");
actionResponse.sendRedirect(redirect);
return role;
}
else {
// Update role
if (name.equals(RoleConstants.SITE_ADMINISTRATOR)) {
Role role = _roleLocalService.getRole(roleId);
ThemeDisplay themeDisplay =
(ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
boolean manageSubgroups = ParamUtil.getBoolean(
actionRequest, "manageSubgroups");
updateAction(
role, themeDisplay.getScopeGroupId(), Group.class.getName(),
ActionKeys.MANAGE_SUBGROUPS, manageSubgroups,
ResourceConstants.SCOPE_GROUP_TEMPLATE, new String[0]);
}
return _roleService.updateRole(
roleId, name, titleMap, descriptionMap, subtype,
serviceContext);
}
}
public void editRoleAssignments(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
long roleId = ParamUtil.getLong(actionRequest, "roleId");
Role role = _roleLocalService.getRole(roleId);
if (role.getName().equals(RoleConstants.OWNER)) {
throw new RoleAssignmentException(role.getName());
}
long[] addUserIds = StringUtil.split(
ParamUtil.getString(actionRequest, "addUserIds"), 0L);
long[] removeUserIds = StringUtil.split(
ParamUtil.getString(actionRequest, "removeUserIds"), 0L);
if (!ArrayUtil.isEmpty(addUserIds) ||
!ArrayUtil.isEmpty(removeUserIds)) {
try (ProxyModeThreadLocalCloseable proxyModeThreadLocalCloseable =
new ProxyModeThreadLocalCloseable()) {
ProxyModeThreadLocal.setForceSync(true);
_userService.addRoleUsers(roleId, addUserIds);
_userService.unsetRoleUsers(roleId, removeUserIds);
}
}
long[] addGroupIds = StringUtil.split(
ParamUtil.getString(actionRequest, "addGroupIds"), 0L);
long[] removeGroupIds = StringUtil.split(
ParamUtil.getString(actionRequest, "removeGroupIds"), 0L);
if (!ArrayUtil.isEmpty(addGroupIds) ||
!ArrayUtil.isEmpty(removeGroupIds)) {
_groupService.addRoleGroups(roleId, addGroupIds);
_groupService.unsetRoleGroups(roleId, removeGroupIds);
}
}
@Override
public void serveResource(
ResourceRequest resourceRequest, ResourceResponse resourceResponse)
throws IOException, PortletException {
setAttributes(resourceRequest);
super.serveResource(resourceRequest, resourceResponse);
}
public void updateActions(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
long roleId = ParamUtil.getLong(actionRequest, "roleId");
Role role = _roleLocalService.getRole(roleId);
String roleName = role.getName();
if (roleName.equals(RoleConstants.ADMINISTRATOR) ||
roleName.equals(RoleConstants.ORGANIZATION_ADMINISTRATOR) ||
roleName.equals(RoleConstants.ORGANIZATION_OWNER) ||
roleName.equals(RoleConstants.OWNER) ||
roleName.equals(RoleConstants.SITE_ADMINISTRATOR) ||
roleName.equals(RoleConstants.SITE_OWNER)) {
throw new RolePermissionsException(roleName);
}
String portletResource = ParamUtil.getString(
actionRequest, "portletResource");
String[] relatedPortletResources = StringUtil.split(
ParamUtil.getString(actionRequest, "relatedPortletResources"));
String[] modelResources = StringUtil.split(
ParamUtil.getString(actionRequest, "modelResources"));
Map<String, List<String>> resourceActionsMap = new HashMap<>();
if (Validator.isNotNull(portletResource)) {
resourceActionsMap.put(
portletResource,
ResourceActionsUtil.getResourceActions(portletResource, null));
}
for (String relatedPortletResource : relatedPortletResources) {
resourceActionsMap.put(
relatedPortletResource,
ResourceActionsUtil.getResourceActions(
relatedPortletResource, null));
}
for (String modelResource : modelResources) {
resourceActionsMap.put(
modelResource,
ResourceActionsUtil.getResourceActions(null, modelResource));
}
int rootResourceScope = ResourceConstants.SCOPE_COMPANY;
String[] rootResourceGroupIds = null;
String[] selectedTargets = StringUtil.split(
ParamUtil.getString(actionRequest, "selectedTargets"));
String[] unselectedTargets = StringUtil.split(
ParamUtil.getString(actionRequest, "unselectedTargets"));
for (Map.Entry<String, List<String>> entry :
resourceActionsMap.entrySet()) {
String selResource = entry.getKey();
List<String> actions = entry.getValue();
actions = ListUtil.sort(
actions, new ActionComparator(themeDisplay.getLocale()));
for (String actionId : actions) {
String target = selResource + actionId;
boolean selected = ArrayUtil.contains(selectedTargets, target);
if (!selected &&
!ArrayUtil.contains(unselectedTargets, target)) {
continue;
}
String[] groupIds = StringUtil.split(
ParamUtil.getString(actionRequest, "groupIds" + target));
groupIds = ArrayUtil.distinct(groupIds);
int scope = ResourceConstants.SCOPE_COMPANY;
if ((role.getType() == RoleConstants.TYPE_ORGANIZATION) ||
(role.getType() == RoleConstants.TYPE_PROVIDER) ||
(role.getType() == RoleConstants.TYPE_SITE)) {
scope = ResourceConstants.SCOPE_GROUP_TEMPLATE;
}
else {
if (groupIds.length > 0) {
scope = ResourceConstants.SCOPE_GROUP;
}
}
if (_resourceBlockLocalService.isSupported(selResource)) {
updateActions_Blocks(
role, themeDisplay.getScopeGroupId(), selResource,
actionId, selected, scope, groupIds);
}
else {
updateAction(
role, themeDisplay.getScopeGroupId(), selResource,
actionId, selected, scope, groupIds);
}
if (selected &&
actionId.equals(ActionKeys.ACCESS_IN_CONTROL_PANEL)) {
updateViewControlPanelPermission(
role, themeDisplay.getScopeGroupId(), selResource,
scope, groupIds);
rootResourceScope = scope;
rootResourceGroupIds = groupIds;
}
}
}
// LPS-38031
if (rootResourceGroupIds != null) {
updateViewRootResourcePermission(
role, themeDisplay.getScopeGroupId(), portletResource,
rootResourceScope, rootResourceGroupIds);
}
// Send redirect
SessionMessages.add(actionRequest, "permissionsUpdated");
String redirect = _portal.escapeRedirect(
ParamUtil.getString(actionRequest, "redirect"));
if (Validator.isNotNull(redirect)) {
actionResponse.sendRedirect(redirect);
}
}
@Override
protected void doDispatch(
RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
setAttributes(renderRequest);
long roleId = ParamUtil.getLong(renderRequest, "roleId");
if (SessionErrors.contains(
renderRequest, RequiredRoleException.class.getName()) &&
(roleId < 1)) {
include("/view.jsp", renderRequest, renderResponse);
}
else if (SessionErrors.contains(
renderRequest, DuplicateRoleException.class.getName()) ||
SessionErrors.contains(
renderRequest, RequiredRoleException.class.getName()) ||
SessionErrors.contains(
renderRequest, RoleNameException.class.getName())) {
include("/edit_role.jsp", renderRequest, renderResponse);
}
else if (SessionErrors.contains(
renderRequest, NoSuchRoleException.class.getName()) ||
SessionErrors.contains(
renderRequest, PrincipalException.getNestedClasses()) ||
SessionErrors.contains(
renderRequest, RoleAssignmentException.class.getName()) ||
SessionErrors.contains(
renderRequest, RolePermissionsException.class.getName())) {
include("/error.jsp", renderRequest, renderResponse);
}
else {
super.doDispatch(renderRequest, renderResponse);
}
}
@Override
protected boolean isSessionErrorException(Throwable cause) {
if (cause instanceof DuplicateRoleException ||
cause instanceof NoSuchRoleException ||
cause instanceof PrincipalException ||
cause instanceof RequiredRoleException ||
cause instanceof RoleAssignmentException ||
cause instanceof RoleNameException ||
cause instanceof RolePermissionsException) {
return true;
}
return false;
}
protected void setAttributes(PortletRequest portletRequest) {
portletRequest.setAttribute(
ApplicationListWebKeys.PANEL_APP_REGISTRY, _panelAppRegistry);
PanelCategoryHelper panelCategoryHelper = new PanelCategoryHelper(
_panelAppRegistry, _panelCategoryRegistry);
portletRequest.setAttribute(
ApplicationListWebKeys.PANEL_CATEGORY_HELPER, panelCategoryHelper);
portletRequest.setAttribute(
ApplicationListWebKeys.PANEL_CATEGORY_REGISTRY,
_panelCategoryRegistry);
}
@Reference(unbind = "-")
protected void setGroupService(GroupService groupService) {
_groupService = groupService;
}
@Reference(unbind = "-")
protected void setPanelAppRegistry(PanelAppRegistry panelAppRegistry) {
_panelAppRegistry = panelAppRegistry;
}
@Reference(unbind = "-")
protected void setPanelCategoryRegistry(
PanelCategoryRegistry panelCategoryRegistry) {
_panelCategoryRegistry = panelCategoryRegistry;
}
@Reference(unbind = "-")
protected void setResourceBlockLocalService(
ResourceBlockLocalService resourceBlockLocalService) {
_resourceBlockLocalService = resourceBlockLocalService;
}
@Reference(unbind = "-")
protected void setResourceBlockService(
ResourceBlockService resourceBlockService) {
_resourceBlockService = resourceBlockService;
}
@Reference(unbind = "-")
protected void setResourcePermissionService(
ResourcePermissionService resourcePermissionService) {
_resourcePermissionService = resourcePermissionService;
}
@Reference(unbind = "-")
protected void setRoleLocalService(RoleLocalService roleLocalService) {
_roleLocalService = roleLocalService;
}
@Reference(unbind = "-")
protected void setRoleService(RoleService roleService) {
_roleService = roleService;
}
@Reference(unbind = "-")
protected void setUserService(UserService userService) {
_userService = userService;
}
protected void updateAction(
Role role, long groupId, String selResource, String actionId,
boolean selected, int scope, String[] groupIds)
throws Exception {
long companyId = role.getCompanyId();
long roleId = role.getRoleId();
if (selected) {
if (scope == ResourceConstants.SCOPE_COMPANY) {
_resourcePermissionService.addResourcePermission(
groupId, companyId, selResource, scope,
String.valueOf(role.getCompanyId()), roleId, actionId);
}
else if (scope == ResourceConstants.SCOPE_GROUP_TEMPLATE) {
_resourcePermissionService.addResourcePermission(
groupId, companyId, selResource,
ResourceConstants.SCOPE_GROUP_TEMPLATE,
String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID),
roleId, actionId);
}
else if (scope == ResourceConstants.SCOPE_GROUP) {
_resourcePermissionService.removeResourcePermissions(
groupId, companyId, selResource,
ResourceConstants.SCOPE_GROUP, roleId, actionId);
for (String curGroupId : groupIds) {
_resourcePermissionService.addResourcePermission(
groupId, companyId, selResource,
ResourceConstants.SCOPE_GROUP, curGroupId, roleId,
actionId);
}
}
}
else {
// Remove company, group template, and group permissions
_resourcePermissionService.removeResourcePermissions(
groupId, companyId, selResource,
ResourceConstants.SCOPE_COMPANY, roleId, actionId);
_resourcePermissionService.removeResourcePermissions(
groupId, companyId, selResource,
ResourceConstants.SCOPE_GROUP_TEMPLATE, roleId, actionId);
_resourcePermissionService.removeResourcePermissions(
groupId, companyId, selResource, ResourceConstants.SCOPE_GROUP,
roleId, actionId);
}
}
protected void updateActions_Blocks(
Role role, long scopeGroupId, String selResource, String actionId,
boolean selected, int scope, String[] groupIds)
throws Exception {
long companyId = role.getCompanyId();
long roleId = role.getRoleId();
if (selected) {
if (scope == ResourceConstants.SCOPE_GROUP) {
_resourceBlockService.removeAllGroupScopePermissions(
scopeGroupId, companyId, selResource, roleId, actionId);
_resourceBlockService.removeCompanyScopePermission(
scopeGroupId, companyId, selResource, roleId, actionId);
for (String groupId : groupIds) {
_resourceBlockService.addGroupScopePermission(
scopeGroupId, companyId, GetterUtil.getLong(groupId),
selResource, roleId, actionId);
}
}
else {
_resourceBlockService.removeAllGroupScopePermissions(
scopeGroupId, companyId, selResource, roleId, actionId);
_resourceBlockService.addCompanyScopePermission(
scopeGroupId, companyId, selResource, roleId, actionId);
}
}
else {
_resourceBlockService.removeAllGroupScopePermissions(
scopeGroupId, companyId, selResource, roleId, actionId);
_resourceBlockService.removeCompanyScopePermission(
scopeGroupId, companyId, selResource, roleId, actionId);
}
}
protected void updateViewControlPanelPermission(
Role role, long scopeGroupId, String portletId, int scope,
String[] groupIds)
throws Exception {
PanelCategoryHelper panelCategoryHelper = new PanelCategoryHelper(
_panelAppRegistry, _panelCategoryRegistry);
String selResource = null;
String actionId = null;
if (panelCategoryHelper.containsPortlet(
portletId, PanelCategoryKeys.CONTROL_PANEL) &&
(role.getType() == RoleConstants.TYPE_REGULAR)) {
selResource = PortletKeys.PORTAL;
actionId = ActionKeys.VIEW_CONTROL_PANEL;
}
else if (panelCategoryHelper.containsPortlet(
portletId, PanelCategoryKeys.SITE_ADMINISTRATION)) {
selResource = Group.class.getName();
actionId = ActionKeys.VIEW_SITE_ADMINISTRATION;
}
if (selResource != null) {
updateAction(
role, scopeGroupId, selResource, actionId, true, scope,
groupIds);
}
}
protected void updateViewRootResourcePermission(
Role role, long scopeGroupId, String portletId, int scope,
String[] groupIds)
throws Exception {
String modelResource = ResourceActionsUtil.getPortletRootModelResource(
portletId);
if (modelResource != null) {
List<String> actions = ResourceActionsUtil.getModelResourceActions(
modelResource);
if (actions.contains(ActionKeys.VIEW)) {
updateAction(
role, scopeGroupId, modelResource, ActionKeys.VIEW, true,
scope, groupIds);
}
}
}
private GroupService _groupService;
@Reference
private Http _http;
private PanelAppRegistry _panelAppRegistry;
private PanelCategoryRegistry _panelCategoryRegistry;
@Reference
private Portal _portal;
private ResourceBlockLocalService _resourceBlockLocalService;
private ResourceBlockService _resourceBlockService;
private ResourcePermissionService _resourcePermissionService;
private RoleLocalService _roleLocalService;
private RoleService _roleService;
private UserService _userService;
}