001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/portal/standard/security/control/InitRightsEditorListener.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.portal.standard.security.control; 037 038 import java.util.ArrayList; 039 import java.util.HashMap; 040 import java.util.Iterator; 041 import java.util.LinkedList; 042 import java.util.Map; 043 044 import javax.servlet.ServletRequest; 045 046 import org.deegree.datatypes.QualifiedName; 047 import org.deegree.enterprise.control.AbstractListener; 048 import org.deegree.enterprise.control.FormEvent; 049 import org.deegree.enterprise.control.RPCException; 050 import org.deegree.enterprise.control.RPCMethodCall; 051 import org.deegree.enterprise.control.RPCParameter; 052 import org.deegree.enterprise.control.RPCWebEvent; 053 import org.deegree.framework.log.ILogger; 054 import org.deegree.framework.log.LoggerFactory; 055 import org.deegree.i18n.Messages; 056 import org.deegree.model.filterencoding.ComplexFilter; 057 import org.deegree.model.filterencoding.Filter; 058 import org.deegree.model.filterencoding.Literal; 059 import org.deegree.model.filterencoding.LogicalOperation; 060 import org.deegree.model.filterencoding.Operation; 061 import org.deegree.model.filterencoding.OperationDefines; 062 import org.deegree.model.filterencoding.PropertyIsCOMPOperation; 063 import org.deegree.model.filterencoding.PropertyName; 064 import org.deegree.model.filterencoding.SpatialOperation; 065 import org.deegree.model.spatialschema.Envelope; 066 import org.deegree.model.spatialschema.Position; 067 import org.deegree.ogcbase.PropertyPath; 068 import org.deegree.ogcbase.PropertyPathFactory; 069 import org.deegree.security.GeneralSecurityException; 070 import org.deegree.security.drm.SecurityAccess; 071 import org.deegree.security.drm.model.Right; 072 import org.deegree.security.drm.model.RightType; 073 import org.deegree.security.drm.model.Role; 074 import org.deegree.security.drm.model.SecuredObject; 075 import org.deegree.security.drm.model.Service; 076 import org.deegree.security.drm.model.User; 077 078 /** 079 * This <code>Listener</code> reacts on RPC-EditRole events, extracts the submitted role-id and passes the role + known 080 * securable objects on the JSP. 081 * <p> 082 * Access constraints: 083 * <ul> 084 * <li>only users that have the 'SEC_ADMIN'-role are allowed</li> 085 * </ul> 086 * 087 * @author <a href="mschneider@lat-lon.de">Markus Schneider</a> 088 * @author last edited by: $Author: aschmitz $ 089 * 090 * @version $Revision: 25490 $, $Date: 2010-07-26 11:47:34 +0200 (Mo, 26 Jul 2010) $ 091 */ 092 public class InitRightsEditorListener extends AbstractListener { 093 094 private static final ILogger LOG = LoggerFactory.getLogger( InitRightsEditorListener.class ); 095 096 @Override 097 public void actionPerformed( FormEvent event ) { 098 099 ServletRequest request = getRequest(); 100 try { 101 // perform access check 102 SecurityAccess access = SecurityHelper.acquireAccess( this ); 103 SecurityHelper.checkForAdminRole( access ); 104 User user = access.getUser(); 105 106 RPCWebEvent ev = (RPCWebEvent) event; 107 RPCMethodCall rpcCall = ev.getRPCMethodCall(); 108 RPCParameter[] params = rpcCall.getParameters(); 109 110 if ( params.length != 1 ) { 111 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_PARAM_NUM" ) ); 112 } 113 if ( params[0].getType() != String.class ) { 114 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_STRING" ) ); 115 } 116 int roleId = -1; 117 try { 118 roleId = Integer.parseInt( (String) params[0].getValue() ); 119 } catch ( NumberFormatException e ) { 120 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_ROLE_VALUE" ) ); 121 } 122 123 // get Role to be edited 124 Role role = access.getRoleById( roleId ); 125 126 // check if user has the right to update the role 127 if ( !user.hasRight( access, RightType.UPDATE, role ) ) { 128 throw new GeneralSecurityException( Messages.getMessage( "IGEO_STD_SEC_MISSING_RIGHT", role.getName() ) ); 129 } 130 131 String s = (String) request.getAttribute( "supportManyServices" ); 132 boolean manyServices = false; 133 if ( s != null ) { 134 manyServices = s.equalsIgnoreCase( "true" ); 135 } 136 if ( manyServices ) { 137 LinkedList<Service> services = access.getAllServices(); 138 request.setAttribute( "SERVICES", services ); 139 } 140 141 SecuredObject[] layers = access.getAllSecuredObjects( ClientHelper.TYPE_LAYER ); 142 SecuredObjectRight[] getMapRights = new SecuredObjectRight[layers.length]; 143 for ( int i = 0; i < layers.length; i++ ) { 144 Right right = role.getRights( access, layers[i] ).getRight( layers[i], RightType.GETMAP ); 145 boolean isAccessible = right != null; 146 Map<String, String[]> constraintsMap = new HashMap<String, String[]>(); 147 if ( right != null && right.getConstraints() != null ) { 148 constraintsMap = buildConstraintsMap( right.getConstraints() ); 149 } 150 151 if ( ILogger.LOG_DEBUG == LOG.getLevel() ) { 152 LOG.logDebug( "---------------------" ); 153 if ( constraintsMap == null ) { 154 LOG.logDebug( "no constraints" ); 155 } else { 156 for ( String key : constraintsMap.keySet() ) { 157 Object value = constraintsMap.get( key ); 158 LOG.logDebug( key, " = ", value ); 159 } 160 } 161 LOG.logDebug( "---------------------" ); 162 } 163 getMapRights[i] = new SecuredObjectRight( isAccessible, layers[i], constraintsMap ); 164 } 165 166 SecuredObject[] featureTypes = access.getAllSecuredObjects( ClientHelper.TYPE_FEATURETYPE ); 167 SecuredObjectRight[] getFeatureRights = new SecuredObjectRight[featureTypes.length]; 168 boolean[] deleteRights = new boolean[featureTypes.length]; 169 boolean[] insertRights = new boolean[featureTypes.length]; 170 boolean[] updateRights = new boolean[featureTypes.length]; 171 for ( int i = 0; i < featureTypes.length; i++ ) { 172 Right right = role.getRights( access, featureTypes[i] ).getRight( featureTypes[i], RightType.GETFEATURE ); 173 boolean isAccessible = right != null ? true : false; 174 Map<Object, Object> constraints = new HashMap<Object, Object>(); 175 getFeatureRights[i] = new SecuredObjectRight( isAccessible, featureTypes[i], constraints ); 176 right = role.getRights( access, featureTypes[i] ).getRight( featureTypes[i], RightType.INSERT ); 177 insertRights[i] = right != null ? true : false; 178 right = role.getRights( access, featureTypes[i] ).getRight( featureTypes[i], RightType.UPDATE ); 179 updateRights[i] = right != null ? true : false; 180 right = role.getRights( access, featureTypes[i] ).getRight( featureTypes[i], RightType.DELETE ); 181 deleteRights[i] = right != null ? true : false; 182 } 183 184 request.setAttribute( "ROLE", role ); 185 request.setAttribute( "RIGHTS_GET_MAP", getMapRights ); 186 request.setAttribute( "RIGHTS_GET_FEATURE", getFeatureRights ); 187 request.setAttribute( "RIGHTS_DELETE_FEATURE", deleteRights ); 188 request.setAttribute( "RIGHTS_INSERT_FEATURE", insertRights ); 189 request.setAttribute( "RIGHTS_UPDATE_FEATURE", updateRights ); 190 } catch ( RPCException e ) { 191 LOG.logError( e.getMessage(), e ); 192 request.setAttribute( "SOURCE", this.getClass().getName() ); 193 request.setAttribute( "MESSAGE", Messages.getMessage( "IGEO_STD_SEC_ERROR_RIGHTSEDITOR_REQUEST", 194 e.getMessage() ) ); 195 setNextPage( "error.jsp" ); 196 } catch ( GeneralSecurityException e ) { 197 LOG.logError( e.getMessage(), e ); 198 request.setAttribute( "SOURCE", this.getClass().getName() ); 199 request.setAttribute( "MESSAGE", Messages.getMessage( "IGEO_STD_SEC_ERROR_RIGHTSEDITOR", e.getMessage() ) ); 200 setNextPage( "error.jsp" ); 201 } catch ( Exception e ) { 202 LOG.logError( e.getMessage(), e ); 203 } 204 205 } 206 207 /** 208 * Reconstructs the constraints map (keys are Strings, values are arrays of Strings) from the given 209 * <code>Filter</code> expression. This only works if the expression meets the very format used by the 210 * <code>StoreRightsListener</code>. 211 * 212 * @param filter 213 * @return Map 214 * @throws SecurityException 215 */ 216 private Map<String, String[]> buildConstraintsMap( Filter filter ) 217 throws SecurityException { 218 Map<String, String[]> constraintsMap = new HashMap<String, String[]>(); 219 if ( filter instanceof ComplexFilter ) { 220 Operation operation = ( (ComplexFilter) filter ).getOperation(); 221 if ( operation.getOperatorId() == OperationDefines.AND ) { 222 LogicalOperation andOperation = (LogicalOperation) operation; 223 Iterator<?> it = andOperation.getArguments().iterator(); 224 while ( it.hasNext() ) { 225 addConstraintToMap( (Operation) it.next(), constraintsMap ); 226 } 227 } else { 228 addConstraintToMap( operation, constraintsMap ); 229 } 230 } 231 return constraintsMap; 232 } 233 234 /** 235 * Extracts the constraint in the given <code>Operation</code> and adds it to the also supplied <code>Map</code>. 236 * The <code>Operation</code> must be of type OperationDefines.OR (with children that are all of type 237 * <code>PropertyIsCOMPOperations</code> or <code>BBOX</code>) or of type <code>PropertyIsCOMPOperation</code>( 238 * <code>BBOX</code>), in any other case this method will fail. 239 * 240 * @param operation 241 * @param map 242 * @throws SecurityException 243 */ 244 private void addConstraintToMap( Operation operation, Map<String, String[]> map ) 245 throws SecurityException { 246 247 PropertyPath constraintName = null; 248 String[] parameters = new String[1]; 249 250 if ( operation instanceof PropertyIsCOMPOperation ) { 251 PropertyIsCOMPOperation comparison = (PropertyIsCOMPOperation) operation; 252 try { 253 constraintName = ( (PropertyName) comparison.getFirstExpression() ).getValue(); 254 parameters[0] = ( (Literal) comparison.getSecondExpression() ).getValue(); 255 } catch ( ClassCastException e ) { 256 LOG.logDebug( e.getMessage(), e ); 257 throw new SecurityException( "Unable to reconstruct constraint map from stored filter expression." ); 258 } 259 } else if ( operation.getOperatorId() == OperationDefines.BBOX 260 || operation.getOperatorId() == OperationDefines.WITHIN 261 || operation.getOperatorId() == OperationDefines.CONTAINS ) { 262 constraintName = PropertyPathFactory.createPropertyPath( new QualifiedName( "bbox" ) ); 263 SpatialOperation spatialOperation = (SpatialOperation) operation; 264 Envelope envelope = spatialOperation.getGeometry().getEnvelope(); 265 try { 266 Position max = envelope.getMax(); 267 Position min = envelope.getMin(); 268 parameters = new String[4]; 269 parameters[0] = "" + min.getX(); 270 parameters[1] = "" + min.getY(); 271 parameters[2] = "" + max.getX(); 272 parameters[3] = "" + max.getY(); 273 } catch ( ClassCastException e ) { 274 LOG.logDebug( e.getMessage(), e ); 275 throw new SecurityException( "Unable to reconstruct constraint map from stored filter expression." ); 276 } 277 } else if ( operation.getOperatorId() == OperationDefines.OR ) { 278 LogicalOperation logical = (LogicalOperation) operation; 279 Iterator<?> it = logical.getArguments().iterator(); 280 ArrayList<String> parameterList = new ArrayList<String>( 10 ); 281 while ( it.hasNext() ) { 282 try { 283 PropertyIsCOMPOperation argument = (PropertyIsCOMPOperation) it.next(); 284 PropertyName propertyName = (PropertyName) argument.getFirstExpression(); 285 if ( constraintName != null && ( !constraintName.equals( propertyName.getValue() ) ) ) { 286 throw new SecurityException( 287 "Unable to reconstruct constraint map from stored filter expression." ); 288 } 289 constraintName = propertyName.getValue(); 290 parameterList.add( ( (Literal) argument.getSecondExpression() ).getValue() ); 291 } catch ( ClassCastException e ) { 292 LOG.logDebug( e.getMessage(), e ); 293 throw new SecurityException( "Unable to reconstruct constraint map from stored filter expression. " 294 + "Invalid filter format." ); 295 } 296 } 297 parameters = parameterList.toArray( new String[parameterList.size()] ); 298 } else { 299 LOG.logDebug( "OperatorId = " + operation.getOperatorId() ); 300 throw new SecurityException( "Unable to reconstruct constraint map from stored filter expression: " 301 + operation ); 302 } 303 map.put( constraintName.getAsString(), parameters ); 304 } 305 }