/* * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.ui; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.exoplatform.ecm.utils.lock.LockUtil; import org.exoplatform.ecm.webui.utils.JCRExceptionManager; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.services.ecm.publication.PublicationPlugin; import org.exoplatform.services.ecm.publication.PublicationService; import org.exoplatform.services.jcr.access.AccessControlEntry; import org.exoplatform.services.jcr.access.AccessControlList; import org.exoplatform.services.jcr.access.PermissionType; import org.exoplatform.services.jcr.impl.core.NodeImpl; import org.exoplatform.services.security.Identity; import org.exoplatform.services.security.IdentityRegistry; import org.exoplatform.services.wcm.extensions.publication.PublicationManager; import org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.AuthoringPublicationConstant; import org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig.Lifecycle; import org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig.State; import org.exoplatform.services.wcm.publication.PublicationDefaultStates; import org.exoplatform.services.wcm.publication.WCMPublicationService; import org.exoplatform.services.wcm.publication.lifecycle.stageversion.ui.UIPublicationContainer; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.config.annotation.EventConfig; import org.exoplatform.webui.core.UIApplication; import org.exoplatform.webui.core.lifecycle.UIFormLifecycle; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.event.EventListener; import javax.jcr.Node; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Created by The eXo Platform MEA Author : haikel.thamri@exoplatform.com */ @ComponentConfig(lifecycle = UIFormLifecycle.class, template = "app:/groovy/webui/component/explorer/popup/action/UIPublicationPanel.gtmpl", events = { @EventConfig(listeners = UIPublicationPanel.ChangeStateActionListener.class), @EventConfig(listeners = UIPublicationPanel.ChangeVersionActionListener.class), @EventConfig(listeners = UIPublicationPanel.PreviewVersionActionListener.class), @EventConfig(listeners = UIPublicationPanel.RestoreVersionActionListener.class), @EventConfig(listeners = UIPublicationPanel.SeeAllVersionActionListener.class)}) public class UIPublicationPanel extends org.exoplatform.services.wcm.publication.lifecycle.stageversion.ui.UIPublicationPanel { private static final Log LOG = LogFactory.getLog(UIPublicationPanel.class.getName()); /** * Instantiates a new uI publication panel. * * @throws Exception the exception */ public UIPublicationPanel() throws Exception { } public void init(Node node) throws Exception { String nodeVersionUUID = null; super.init(node); String currentState = node.getProperty(AuthoringPublicationConstant.CURRENT_STATE).getString(); if (PublicationDefaultStates.PUBLISHED.equals(currentState) || PublicationDefaultStates.UNPUBLISHED.equals(currentState) || PublicationDefaultStates.OBSOLETE.equals(currentState)) { if (node.hasProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP)) { nodeVersionUUID = node.getProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP).getString(); } if (StringUtils.isNotEmpty(nodeVersionUUID)) { Node revision = this.getRevisionByUUID(nodeVersionUUID); this.setCurrentRevision(revision); } } } /** * The listener interface for receiving draftAction events. The class that is * interested in processing a draftAction event implements this interface, and * the object created with that class is registered with a component using the * component's <code>addDraftActionListener</code> method. When * the draftAction event occurs, that object's appropriate * method is invoked. */ public static class ChangeStateActionListener extends EventListener<UIPublicationPanel> { /* * (non-Javadoc) * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform * .webui.event.Event) */ public void execute(Event<UIPublicationPanel> event) throws Exception { UIPublicationPanel publicationPanel = event.getSource(); String state = event.getRequestContext().getRequestParameter(OBJECTID) ; Node currentNode = publicationPanel.getCurrentNode(); PublicationService publicationService = publicationPanel.getApplicationComponent(PublicationService.class); WCMPublicationService wcmPublicationService = publicationPanel.getApplicationComponent(WCMPublicationService.class); PublicationPlugin publicationPlugin = publicationService.getPublicationPlugins() .get(AuthoringPublicationConstant.LIFECYCLE_NAME); HashMap<String, String> context = new HashMap<String, String>(); Node currentRevision = publicationPanel.getCurrentRevision(); if (currentRevision != null) { context.put(AuthoringPublicationConstant.CURRENT_REVISION_NAME, currentRevision.getName()); } try { if(currentNode.isLocked()) { currentNode.getSession().addLockToken(LockUtil.getLockToken(currentNode)); } publicationPlugin.changeState(currentNode, state, context); currentNode.setProperty("publication:lastUser", event.getRequestContext().getRemoteUser()); String nodeVersionUUID = null; String currentState = currentNode.getProperty(AuthoringPublicationConstant.CURRENT_STATE).getString(); if (PublicationDefaultStates.PUBLISHED.equals(currentState) || PublicationDefaultStates.UNPUBLISHED.equals(currentState) || PublicationDefaultStates.OBSOLETE.equals(currentState)) { if(currentNode.hasProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP)){ nodeVersionUUID = currentNode.getProperty(AuthoringPublicationConstant.LIVE_REVISION_PROP).getString(); } if (nodeVersionUUID != null && !nodeVersionUUID.isEmpty()) { publicationPanel.setCurrentRevision(publicationPanel.getRevisionByUUID(nodeVersionUUID)); } } String siteName = Util.getPortalRequestContext().getPortalOwner(); String remoteUser = Util.getPortalRequestContext().getRemoteUser(); wcmPublicationService.updateLifecyleOnChangeContent(currentNode, siteName, remoteUser, state); publicationPanel.updatePanel(); } catch (Exception e) { UIApplication uiApp = publicationPanel.getAncestorOfType(UIApplication.class); JCRExceptionManager.process(uiApp, e); } UIPublicationContainer publicationContainer = publicationPanel.getAncestorOfType(UIPublicationContainer.class); publicationContainer.setActiveTab(publicationPanel, event.getRequestContext()); } } public List<State> getStates(Node cNode) throws Exception { List<State> states = new ArrayList<State>(); String lifecycleName = getLifeCycle(cNode); PublicationManager publicationManagerImpl = getApplicationComponent(PublicationManager.class); Lifecycle lifecycle = publicationManagerImpl.getLifecycle(lifecycleName); states = lifecycle.getStates(); return states; } private String getLifeCycle(Node cNode) throws Exception { String lifecycleName = null; try { lifecycleName = cNode.getProperty("publication:lifecycle").getString(); } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("Failed to get States for node " + cNode, e); } } return lifecycleName; } /** * Check if a user is authorized to reach the given state of a given node. * The user must satisfy the constraints defined by state (memberships or role) * @param state * @param remoteUser * @param node * @return */ public boolean canReachState(State state, String remoteUser, NodeImpl node) { IdentityRegistry identityRegistry = getApplicationComponent(IdentityRegistry.class); Identity currentUser = identityRegistry.getIdentity(remoteUser); if (isAuthorizedByMembership(state, currentUser)) { return true; } if (isAuthorizedByRole(state, currentUser, node)) { return true; } return false; } /** * Check if the user has the memberships defined in the state * @param state * @param currentUser * @return */ boolean isAuthorizedByMembership(State state, Identity currentUser) { String membership = state.getMembership(); List<String> memberships = new ArrayList<String>(); if (membership != null) { memberships.add(membership); } if (state.getMemberships() != null) { memberships.addAll(state.getMemberships()); } for (String membership_ : memberships) { String[] membershipTab = membership_.split(":"); String expectedRole = membershipTab[0]; String expectedGroup = membershipTab[1]; if (currentUser.isMemberOf(expectedGroup, expectedRole)) { return true; } } return false; } /** * Check if a user is authorized to reach the state based on the state's role. * The user must have the role * @param state * @param currentUser * @param node * @return */ boolean isAuthorizedByRole(State state, Identity currentUser, NodeImpl node) { try { String role_ = state.getRole(); List<String> roles = new ArrayList<String>(); if (role_ != null) { roles.add(role_); } if (state.getRoles() != null) { roles.addAll(state.getRoles()); } for (String role : roles) { AccessControlList acl = node.getACL(); if (acl.hasPermissions()) { List<AccessControlEntry> entries = acl.getPermissionEntries(); for (AccessControlEntry accessControlEntry : entries) { String identity = accessControlEntry.getIdentity(); if (identity.indexOf(':') > 0) { // write access on node is defined by 'set_property' in exo JCR if (PermissionType.SET_PROPERTY.equals(accessControlEntry.getPermission())) { String authorizedGroup = identity.split(":")[1]; // user must have the configured role in one of the node's // authorized groups if (currentUser.isMemberOf(authorizedGroup, role)) { return true; } } } } } } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("Failed to extract node permissions", e); } } return false; } }