/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.security.ui.filter; import java.lang.reflect.Constructor; import java.security.Permission; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.riena.core.injector.InjectionFailure; import org.eclipse.riena.core.service.Service; import org.eclipse.riena.core.util.StringUtils; import org.eclipse.riena.core.wire.InjectExtension; import org.eclipse.riena.core.wire.InjectService; import org.eclipse.riena.internal.navigation.ui.filter.IUIFilterApplier; import org.eclipse.riena.navigation.IApplicationNode; import org.eclipse.riena.navigation.INavigationNode; import org.eclipse.riena.navigation.ISimpleNavigationNodeListener; import org.eclipse.riena.navigation.NavigationNodeUtility; import org.eclipse.riena.navigation.model.SimpleNavigationNodeAdapter; import org.eclipse.riena.security.common.authorization.ISentinelService; import org.eclipse.riena.ui.filter.IUIFilter; import org.eclipse.riena.ui.filter.IUIFilterContainer; import org.eclipse.riena.ui.filter.IUIFilterProvider; import org.eclipse.riena.ui.filter.impl.UIFilter; /** * Applies {@link UIFilter}s to the application model and ridgets depending on * the {@link Permission}s available for the current {@link Principal}. * */ public class PermissionUIFilterApplier implements IUIFilterApplier { private IApplicationNode applicationNode; private final List<PermissionFilterMapping> permissionFilterMappings; private ISentinelService sentinel; /** * Creates a new {@link PermissionFilterMapping} instance */ public PermissionUIFilterApplier() { permissionFilterMappings = new ArrayList<PermissionFilterMapping>(); } public void applyFilter(final INavigationNode<?> navigationNode) { if (!(navigationNode instanceof IApplicationNode)) { return; } this.applicationNode = (IApplicationNode) navigationNode; updateFilters(); observeNavigationModel(); } protected void observeNavigationModel() { new NodeStructureObserver(applicationNode, createStructureEventDelegation()).start(); } /* * updates the user interface filters for the current principal */ private void updateFilters() { if (permissionFilterMappings.size() == 0) { return; } for (final PermissionFilterMapping mapper : permissionFilterMappings) { if (!sentinel.checkAccess(mapper.getPermission())) { final IUIFilterContainer container = mapper.getFilterContainer(); final IUIFilter filter = container.getFilter(); final Collection<String> targetNodeIds = container.getFilterTargetNodeIds(); for (final String targetNodeId : targetNodeIds) { final List<INavigationNode<?>> nodes = new ArrayList<INavigationNode<?>>(); NavigationNodeUtility.findNodesByLongId(targetNodeId, applicationNode, nodes); for (final INavigationNode<?> node : nodes) { if (!node.getFilters().contains(filter)) { node.addFilter(filter); } } } } } } /* * class for delegation of application model events to the filter logic */ private ISimpleNavigationNodeListener createStructureEventDelegation() { return new SimpleNavigationNodeAdapter() { @Override public void childAdded(final INavigationNode<?> source, final INavigationNode<?> childAdded) { updateFilters(); } @Override public void childRemoved(final INavigationNode<?> source, final INavigationNode<?> childRemoved) { updateFilters(); } }; } /** * Binds the given {@link ISentinelService} */ @InjectService public void bind(final ISentinelService sentinel) { this.sentinel = sentinel; } /** * Unbinds the given {@link ISentinelService} */ public void unbind(final ISentinelService sentinel) { if (this.sentinel == sentinel) { this.sentinel = null; } } /** * Binds the {@link IPermissionFilterMappingExtension} extensions */ @InjectExtension public void update(final IPermissionFilterMappingExtension[] principalFilterMappers) { permissionFilterMappings.clear(); final IUIFilterProvider uiFilterProvider = getUIFilterProvider(); for (final IPermissionFilterMappingExtension mapping : principalFilterMappers) { permissionFilterMappings.add(new PermissionFilterMapping(createPermission(mapping), uiFilterProvider .provideFilter(mapping.getFilterID()))); } } protected IUIFilterProvider getUIFilterProvider() { return Service.get(IUIFilterProvider.class); } private Permission createPermission(final IPermissionFilterMappingExtension mapping) { Class<? extends Permission> permissionClass = mapping.getPermissionClass(); if (permissionClass == null) { permissionClass = UserInterfacePermission.class; } try { if (StringUtils.isEmpty(mapping.getPermissionAction())) { final Constructor<? extends Permission> constructor = permissionClass.getConstructor(String.class); return constructor.newInstance(mapping.getPermissionName()); } else { final Constructor<? extends Permission> constructor = permissionClass.getConstructor(String.class, String.class); return constructor.newInstance(mapping.getPermissionName(), mapping.getPermissionAction()); } } catch (final Exception e) { throw new InjectionFailure("Could not create permission from '" + mapping + "'s.", e); //$NON-NLS-1$ //$NON-NLS-2$ } } /* * class caching a relation between a permission and a user interface filter */ private class PermissionFilterMapping { private final Permission permission; private final IUIFilterContainer filterContainer; public PermissionFilterMapping(final Permission permission, final IUIFilterContainer filterContainer) { this.permission = permission; this.filterContainer = filterContainer; } public Permission getPermission() { return permission; } public IUIFilterContainer getFilterContainer() { return filterContainer; } } }