/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso 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 3 of the License, or * (at your option) any later version. * * Jspresso 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. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.application.security; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jspresso.framework.action.IAction; import org.jspresso.framework.application.model.Module; import org.jspresso.framework.application.model.Workspace; import org.jspresso.framework.model.descriptor.ICollectionDescriptorProvider; import org.jspresso.framework.model.descriptor.IComponentDescriptorProvider; import org.jspresso.framework.model.descriptor.IModelDescriptor; import org.jspresso.framework.model.descriptor.IPropertyDescriptor; import org.jspresso.framework.security.EAuthorization; import org.jspresso.framework.security.ISecurityContextBuilder; import org.jspresso.framework.view.action.ActionList; import org.jspresso.framework.view.action.ActionMap; import org.jspresso.framework.view.descriptor.IPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.ITreeLevelDescriptor; import org.jspresso.framework.view.descriptor.IViewDescriptor; /** * Security context builder that helps building a security context. * * @author Vincent Vandenschrick */ public class SecurityContextBuilder implements ISecurityContextBuilder { private Map<String, Object> currentSecurityContext; private final List<Map<String, Object>> snapshots; private static final String LAST_PUSHED_VIEW = "LAST_PUSHED_VIEW"; /** * Constructs a new {@code SecurityContextBuilder} instance. */ public SecurityContextBuilder() { currentSecurityContext = new HashMap<>(); currentSecurityContext.put(SecurityContextConstants.AUTH_TYPE, EAuthorization.VISIBLE); snapshots = new ArrayList<>(); } /** * Returns the current security context this builder works on. * * @return the current security context this builder works on. */ @Override public Map<String, Object> getSecurityContext() { // return a defensive copy. return new HashMap<>(currentSecurityContext); } /** * {@inheritDoc} */ @Override public SecurityContextBuilder pushToSecurityContext(Object contextElement) { snapshots.add(getSecurityContext()); if (contextElement instanceof Workspace) { return append((Workspace) contextElement); } if (contextElement instanceof Module) { return append((Module) contextElement); } if (contextElement instanceof ActionMap) { return append((ActionMap) contextElement); } if (contextElement instanceof ActionList) { return append((ActionList) contextElement); } if (contextElement instanceof IAction) { return append((IAction) contextElement); } if (contextElement instanceof EAuthorization) { return append((EAuthorization) contextElement); } if (contextElement instanceof ITreeLevelDescriptor) { return append((ITreeLevelDescriptor) contextElement); } if (contextElement instanceof IViewDescriptor) { return append((IViewDescriptor) contextElement); } if (contextElement instanceof IModelDescriptor) { return append((IModelDescriptor) contextElement); } return this; } /** * {@inheritDoc} */ @Override public SecurityContextBuilder restoreLastSecurityContextSnapshot() { if (snapshots.size() > 0) { currentSecurityContext = snapshots.remove(snapshots.size() - 1); } return this; } private SecurityContextBuilder append(EAuthorization auth) { if (auth != null) { currentSecurityContext.put(SecurityContextConstants.AUTH_TYPE, auth); } return this; } private SecurityContextBuilder append(ITreeLevelDescriptor treeLevelDescriptor) { if (treeLevelDescriptor != null) { String permId = treeLevelDescriptor.getPermId(); if (permId == null) { permId = treeLevelDescriptor.getNodeGroupDescriptor().getPermId(); } append(treeLevelDescriptor.getNodeGroupDescriptor().getModelDescriptor()); appendToViewChain(permId); } return this; } private SecurityContextBuilder append(IViewDescriptor viewDescriptor) { if (viewDescriptor != null) { // prevents double-push of same view descriptor if (!viewDescriptor.equals(currentSecurityContext.get(LAST_PUSHED_VIEW))) { currentSecurityContext.put(LAST_PUSHED_VIEW, viewDescriptor); append(viewDescriptor.getModelDescriptor()); appendToViewChain(viewDescriptor.getPermId()); } } return this; } @SuppressWarnings("unchecked") private void appendToViewChain(String permId) { if (permId != null) { List<String> viewChain = (List<String>) currentSecurityContext .get(SecurityContextConstants.VIEW_CHAIN); if (viewChain == null) { viewChain = new ArrayList<>(); } else { // copy to preserve snapshot. viewChain = new ArrayList<>(viewChain); } viewChain.add(permId); currentSecurityContext .put(SecurityContextConstants.VIEW_CHAIN, viewChain); } } private SecurityContextBuilder append(IModelDescriptor modelDescriptor) { if (modelDescriptor != null) { if (modelDescriptor instanceof IPropertyDescriptor) { currentSecurityContext.put(SecurityContextConstants.PROPERTY, ((IPropertyDescriptor) modelDescriptor).getPermId()); } if (modelDescriptor instanceof IComponentDescriptorProvider<?> && ((IComponentDescriptorProvider<?>) modelDescriptor) .getComponentDescriptor() != null) { if (!(currentSecurityContext.get(LAST_PUSHED_VIEW) instanceof IPropertyViewDescriptor)) { // only dig the model if we are not on a reference property view (LOV // field). see bug #560. currentSecurityContext.put(SecurityContextConstants.MODEL, ((IComponentDescriptorProvider<?>) modelDescriptor) .getComponentDescriptor().getPermId()); } } else if (modelDescriptor instanceof ICollectionDescriptorProvider<?>) { currentSecurityContext.put(SecurityContextConstants.MODEL, ((ICollectionDescriptorProvider<?>) modelDescriptor) .getCollectionDescriptor().getElementDescriptor().getPermId()); } } return this; } private SecurityContextBuilder append(Module module) { if (module != null) { Module currentModule = module; List<String> moduleChain = new ArrayList<>(); while (currentModule != null) { if (currentModule.getPermId() != null) { moduleChain.add(currentModule.getPermId()); } currentModule = currentModule.getParent(); } currentSecurityContext.put(SecurityContextConstants.MODULE_CHAIN, moduleChain); } return this; } private SecurityContextBuilder append(Workspace workspace) { if (workspace != null) { currentSecurityContext.put(SecurityContextConstants.WORKSPACE, workspace.getPermId()); } return this; } private SecurityContextBuilder append(ActionList actionList) { if (actionList != null) { currentSecurityContext.put(SecurityContextConstants.ACTION_LIST, actionList.getPermId()); } return this; } private SecurityContextBuilder append(ActionMap actionMap) { if (actionMap != null) { currentSecurityContext.put(SecurityContextConstants.ACTION_MAP, actionMap.getPermId()); } return this; } private SecurityContextBuilder append(IAction action) { if (action != null) { currentSecurityContext.put(SecurityContextConstants.ACTION, action.getPermId()); } return this; } }