    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    }