001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }