001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/security/control/StoreUsersListener.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.io.BufferedWriter; 039 import java.io.File; 040 import java.io.FileWriter; 041 import java.io.IOException; 042 import java.text.ParseException; 043 import java.util.Iterator; 044 import java.util.Vector; 045 046 import org.deegree.enterprise.control.AbstractListener; 047 import org.deegree.enterprise.control.FormEvent; 048 import org.deegree.enterprise.control.RPCException; 049 import org.deegree.enterprise.control.RPCMember; 050 import org.deegree.enterprise.control.RPCMethodCall; 051 import org.deegree.enterprise.control.RPCParameter; 052 import org.deegree.enterprise.control.RPCStruct; 053 import org.deegree.enterprise.control.RPCWebEvent; 054 import org.deegree.framework.log.ILogger; 055 import org.deegree.framework.log.LoggerFactory; 056 import org.deegree.framework.util.StringTools; 057 import org.deegree.i18n.Messages; 058 import org.deegree.security.GeneralSecurityException; 059 import org.deegree.security.drm.SecurityAccessManager; 060 import org.deegree.security.drm.SecurityTransaction; 061 import org.deegree.security.drm.model.User; 062 063 /** 064 * This <code>Listener</code> reacts on 'storeUsers' events, extracts the contained user 065 * definitions and updates the <code>SecurityManager</code> accordingly. 066 * 067 * Access constraints: 068 * <ul> 069 * <li>only users that have the 'SEC_ADMIN'-role are allowed</li> 070 * </ul> 071 * 072 * @author <a href="mschneider@lat-lon.de">Markus Schneider </a> 073 * @author last edited by: $Author: mschneider $ 074 * 075 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 076 */ 077 public class StoreUsersListener extends AbstractListener { 078 079 private static final ILogger LOG = LoggerFactory.getLogger( StoreUsersListener.class ); 080 081 //ME: added for context chooser 082 String usersDirectoryPath = null; 083 084 String defaultContextName = null; 085 086 String defaultContextPath = null; 087 088 private final String STARTCONTEXT = "STARTCONTEXT"; 089 090 private final String CONTEXTNAME = "CONTEXT_NAME"; 091 092 @Override 093 public void actionPerformed( FormEvent event ) { 094 095 SecurityAccessManager manager = null; 096 SecurityTransaction transaction = null; 097 098 User[] users = null; 099 100 try { 101 RPCWebEvent ev = (RPCWebEvent) event; 102 RPCMethodCall rpcCall = ev.getRPCMethodCall(); 103 RPCParameter[] params = rpcCall.getParameters(); 104 105 // ME: this part concerns extracting the usersdirectory member 106 Vector<RPCParameter> vector = new Vector<RPCParameter>( params.length ); 107 for ( int i = 0; i < params.length; i++ ) { 108 vector.add( params[i] ); 109 } 110 111 boolean isUsersDirectoryFound = false; 112 boolean isDefaultContextNameFound = false; 113 boolean isDefaultContextPathFound = false; 114 Iterator<RPCParameter> it = vector.iterator(); 115 116 while ( it.hasNext() ) { 117 RPCStruct struct = (RPCStruct) it.next().getValue(); 118 RPCMember usersDirectoryRPC = struct.getMember( "usersDirectory" ); 119 RPCMember defCnNameRPC = struct.getMember( "defaultContextName" ); 120 RPCMember defCnPathRPC = struct.getMember( "defaultContextPath" ); 121 122 if ( usersDirectoryRPC != null ) { 123 if ( usersDirectoryRPC.getValue() instanceof String ) { 124 isUsersDirectoryFound = true; 125 usersDirectoryPath = (String) usersDirectoryRPC.getValue(); 126 } 127 } 128 129 if ( defCnNameRPC != null ) { 130 if ( defCnNameRPC.getValue() instanceof String ) { 131 isDefaultContextNameFound = true; 132 defaultContextName = (String) defCnNameRPC.getValue(); 133 } 134 } 135 136 if ( defCnPathRPC != null ) { 137 if ( defCnPathRPC.getValue() instanceof String ) { 138 isDefaultContextPathFound = true; 139 defaultContextPath = (String) defCnPathRPC.getValue(); 140 } 141 } 142 if ( isUsersDirectoryFound || isDefaultContextNameFound || isDefaultContextPathFound ) { 143 it.remove(); 144 break; 145 } 146 } 147 148 params = new RPCParameter[vector.size()]; 149 for ( int i = 0; i < vector.size(); i++ ) { 150 params[i] = vector.elementAt( i ); 151 } 152 // ME: end 153 154 // now extracting the members of each parameter 155 users = new User[params.length]; 156 157 for ( int i = 0; i < params.length; i++ ) { 158 if ( !( params[0].getValue() instanceof RPCStruct ) ) { 159 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_STRUCT" ) ); 160 } 161 RPCStruct struct = (RPCStruct) params[i].getValue(); 162 163 // extract user details 164 RPCMember userIdRPC = struct.getMember( "userId" ); 165 RPCMember userNameRPC = struct.getMember( "userName" ); 166 RPCMember emailRPC = struct.getMember( "email" ); 167 RPCMember passwordRPC = struct.getMember( "password" ); 168 RPCMember firstNameRPC = struct.getMember( "firstName" ); 169 RPCMember lastNameRPC = struct.getMember( "lastName" ); 170 //ME: added for context chooser 171 RPCMember contextNameRPC = struct.getMember( "contextName" ); 172 RPCMember contextPathRPC = struct.getMember( "contextPath" ); 173 174 int userId; 175 String userName = null; 176 String email = null; 177 String password = null; 178 String firstName = null; 179 String lastName = null; 180 //ME: added for context chooser 181 String contextName = null; 182 String contextPath = null; 183 184 if ( userIdRPC == null ) { 185 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_MEMBER", "user", "userId" ) ); 186 } 187 if ( !( userIdRPC.getValue() instanceof String ) ) { 188 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "userId", "string" ) ); 189 } 190 try { 191 userId = Integer.parseInt( ( (String) userIdRPC.getValue() ) ); 192 } catch ( NumberFormatException e ) { 193 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "userId", "integer" ) ); 194 } 195 // extract userName 196 if ( userNameRPC != null ) { 197 if ( !( userNameRPC.getValue() instanceof String ) ) { 198 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "userName", "string" ) ); 199 } 200 userName = (String) userNameRPC.getValue(); 201 202 } 203 // extract email 204 if ( emailRPC != null ) { 205 if ( !( emailRPC.getValue() instanceof String ) ) { 206 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "email", "string" ) ); 207 } 208 email = (String) emailRPC.getValue(); 209 210 } 211 // extract password 212 if ( passwordRPC != null ) { 213 if ( !( passwordRPC.getValue() instanceof String ) ) { 214 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "password", "string" ) ); 215 } 216 password = (String) passwordRPC.getValue(); 217 218 } 219 // extract firstName 220 if ( firstNameRPC != null ) { 221 if ( !( firstNameRPC.getValue() instanceof String ) ) { 222 throw new RPCException( 223 Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "firstName", "string" ) ); 224 } 225 firstName = (String) firstNameRPC.getValue(); 226 227 } 228 // extract lastName 229 if ( lastNameRPC != null ) { 230 if ( !( lastNameRPC.getValue() instanceof String ) ) { 231 throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_WRONG_MEMBER", "lastName", "string" ) ); 232 } 233 lastName = (String) lastNameRPC.getValue(); 234 235 } 236 237 if ( userName == null ) { 238 throw new GeneralSecurityException( Messages.getMessage( "IGEO_STD_SEC_MISSING_MEMBER", "user", 239 "name" ) ); 240 } 241 if ( email == null ) { 242 throw new GeneralSecurityException( Messages.getMessage( "IGEO_STD_SEC_MISSING_MEMBER", "user", 243 "email address" ) ); 244 } 245 246 /* 247 * getting the value only in case this is not the default context or the param is 248 * missing 249 * 250 * if contextPathRPC==null, that means that no param is given, that means probably 251 * that the init parameter method in InitUserEditor didn't get anything from the 252 * conf_startcontext.xml 253 * 254 * otherwise if the contextPath is null we delete the users contexts, if it has a 255 * value we assign it this value 256 */ 257 258 LOG.logDebug( "userNameRPC: " + userName ); 259 LOG.logDebug( isUsersDirectoryFound ? "true" : "false" ); 260 LOG.logDebug( contextNameRPC != null ? "context name not null" : "context name null" ); 261 LOG.logDebug( contextPathRPC != null ? "contextPath not null" : "contextpath null" ); 262 263 if ( isUsersDirectoryFound && contextNameRPC != null ) { 264 contextName = (String) contextNameRPC.getValue(); 265 if ( contextPathRPC != null ) { 266 contextPath = (String) contextPathRPC.getValue(); 267 } else { 268 contextPath = null; 269 } 270 updateUserDirectory( userName, contextPath, contextName ); 271 } 272 // ME: end 273 274 users[i] = new User( userId, userName, password, firstName, lastName, email, null ); 275 } 276 277 for ( int i = 0; i < users.length; i++ ) { 278 LOG.logDebug( "id: " + users[i].getID() ); 279 LOG.logDebug( "firstName: " + users[i].getFirstName() ); 280 LOG.logDebug( "lastName: " + users[i].getLastName() ); 281 LOG.logDebug( "email: " + users[i].getEmailAddress() ); 282 LOG.logDebug( "password: " + users[i].getPassword() ); 283 } 284 285 // get Transaction and perform access check 286 manager = SecurityAccessManager.getInstance(); 287 transaction = SecurityHelper.acquireTransaction( this ); 288 SecurityHelper.checkForAdminRole( transaction ); 289 290 // remove deleted users 291 User[] oldUsers = transaction.getAllUsers(); 292 for ( int i = 0; i < oldUsers.length; i++ ) { 293 boolean deleted = true; 294 for ( int j = 0; j < users.length; j++ ) { 295 if ( users[j].equals( oldUsers[i] ) ) { 296 deleted = false; 297 } 298 } 299 if ( oldUsers[i].getID() != User.ID_SEC_ADMIN && deleted ) { 300 transaction.deregisterUser( oldUsers[i] ); 301 } 302 } 303 304 // register all new users / update old users 305 for ( int i = 0; i < users.length; i++ ) { 306 if ( users[i].getID() == -1 ) { 307 transaction.registerUser( users[i].getName(), users[i].getPassword(), users[i].getLastName(), 308 users[i].getFirstName(), users[i].getEmailAddress() ); 309 } else if ( users[i].getID() != User.ID_SEC_ADMIN ) { 310 transaction.updateUser( users[i] ); 311 } 312 } 313 manager.commitTransaction( transaction ); 314 transaction = null; 315 316 getRequest().setAttribute( "MESSAGE", Messages.getMessage( "IGEO_STD_SEC_SUCCESS_INITUSEREDITOR" ) ); 317 } catch ( RPCException e ) { 318 getRequest().setAttribute( "SOURCE", this.getClass().getName() ); 319 getRequest().setAttribute( "MESSAGE", Messages.getMessage( "IGEO_STD_SEC_ERROR_CHANGE_REQ", e.getMessage() ) ); 320 setNextPage( "error.jsp" ); 321 LOG.logError( e.getMessage() ); 322 } catch ( GeneralSecurityException e ) { 323 getRequest().setAttribute( "SOURCE", this.getClass().getName() ); 324 getRequest().setAttribute( "MESSAGE", Messages.getMessage( "IGEO_STD_SEC_ERROR_CHANGE", e.getMessage() ) ); 325 setNextPage( "error.jsp" ); 326 LOG.logError( e.getMessage(), e ); 327 } catch ( Exception e ) { 328 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_UNKNOWN", StringTools.stackTraceToString( e ) ) ); 329 } finally { 330 if ( manager != null && transaction != null ) { 331 try { 332 manager.abortTransaction( transaction ); 333 } catch ( GeneralSecurityException ex ) { 334 LOG.logError( ex.getMessage(), ex ); 335 } 336 } 337 } 338 } 339 340 /** 341 * ME: added for context chooser 342 * 343 * update the users directory, context.properties data, accroding to the value of contextPath 344 * also creates a user folder in case it doesn't exist 345 * 346 * @param user 347 * @param contextPath 348 * @throws IOException 349 * @throws ParseException 350 * 351 */ 352 private void updateUserDirectory( String user, String contextPath, String contextName ) 353 throws IOException, ParseException { 354 355 LOG.logDebug( "user name: " + user ); 356 File usersRootDirectory = new File( usersDirectoryPath ); 357 358 File userDirectory = null; 359 try { 360 userDirectory = new File( usersRootDirectory.getCanonicalPath() + "/" + user + "/" ); 361 } catch ( IOException e ) { 362 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_CANONICAL_PATH", 363 usersRootDirectory.getAbsolutePath() ) ); 364 throw new IOException( Messages.getMessage( "IGEO_STD_SEC_ERROR_CANONICAL_PATH", 365 usersRootDirectory.getAbsolutePath() ) ); 366 } 367 368 LOG.logDebug( "context Path " + contextPath ); 369 if ( contextPath == null || contextPath.equals( "null" ) || contextPath.equals( "undefined" ) ) { 370 LOG.logDebug( "trying to create a folder" ); 371 File userContextProperties = new File( userDirectory + "/" + "context.properties" ); 372 if ( userContextProperties.exists() ) { 373 try { 374 if ( userContextProperties.delete() ) { 375 LOG.logDebug( "context deleted successfully" ); 376 } 377 378 return; 379 } catch ( SecurityException e ) { 380 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_ACCESSING_FILE", userContextProperties ) ); 381 throw new SecurityException( Messages.getMessage( "IGEO_STD_SEC_ERROR_ACCESSING_FILE", 382 userContextProperties ) ); 383 } 384 } else { 385 if ( !userDirectory.exists() ) { 386 userDirectory.mkdir(); 387 } 388 } 389 return; 390 } 391 392 if ( !userDirectory.exists() ) { 393 userDirectory.mkdir(); 394 } 395 // Here we know that the StartContext is not the default one 396 File newContext = null; 397 try { 398 newContext = new File( userDirectory.getCanonicalPath() + "/" + "context.properties" ); 399 } catch ( IOException e ) { 400 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_CANONICAL_PATH", userDirectory.getPath() ) ); 401 } 402 if ( !userDirectory.exists() ) { 403 userDirectory.mkdir(); 404 } 405 406 // Here we will map the file path, in case the context doesn't exist 407 // From the Drm-Admin directorty to the portal directory 408 String outputPath = null; 409 410 // String relativeUserDir= usersDirectoryPath + "/" + user; 411 // LOG.logDebug("sourcePath: " + relativeUserDir); 412 File absCntxtPath = new File( contextPath ); 413 String[] delimiters = { "\\", "/" }; 414 outputPath = RelativePath.mapRelativePath( userDirectory.getCanonicalPath(), absCntxtPath.getCanonicalPath(), 415 delimiters ); 416 417 try { 418 BufferedWriter bufferedWriter = new BufferedWriter( new FileWriter( newContext.getCanonicalPath() ) ); 419 bufferedWriter.flush(); 420 StringBuffer buffer = new StringBuffer(); 421 buffer.append( STARTCONTEXT + '=' + outputPath + System.getProperty( "line.separator" ) ); 422 buffer.append( CONTEXTNAME + '=' + contextName + System.getProperty( "line.separator" ) ); 423 bufferedWriter.write( buffer.toString() ); 424 bufferedWriter.close(); 425 426 } catch ( IOException e ) { 427 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_ACCESSING_FILE", newContext.getPath() ) ); 428 throw new IOException( Messages.getMessage( "IGEO_STD_SEC_ERROR_ACCESSING_FILE", newContext.getPath() ) ); 429 } catch ( Exception e ) { 430 LOG.logError( Messages.getMessage( "IGEO_STD_SEC_ERROR_UNKNOWN", StringTools.stackTraceToString( e ) ) ); 431 } 432 } 433 }