/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.config; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.ValidationException; import org.jasypt.util.password.PasswordEncryptor; import org.jasypt.util.password.StrongPasswordEncryptor; import org.opennms.core.xml.CastorUtils; import org.opennms.netmgt.EventConstants; import org.opennms.netmgt.config.users.Contact; import org.opennms.netmgt.config.users.DutySchedule; import org.opennms.netmgt.config.users.Header; import org.opennms.netmgt.config.users.Password; import org.opennms.netmgt.config.users.User; import org.opennms.netmgt.config.users.Userinfo; import org.opennms.netmgt.config.users.Users; import org.opennms.netmgt.model.OnmsUser; import org.opennms.netmgt.model.OnmsUserList; /** * <p>Abstract UserManager class.</p> * * @author <a href="mailto:david@opennms.org">David Hustace</a> * @author <a href="mailto:brozow@opennms.org">Matt Brozowski</a> */ public abstract class UserManager { private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static final PasswordEncryptor m_passwordEncryptor = new StrongPasswordEncryptor(); private final ReadWriteLock m_readWriteLock = new ReentrantReadWriteLock(); private final Lock m_readLock = m_readWriteLock.readLock(); private final Lock m_writeLock = m_readWriteLock.writeLock(); protected GroupManager m_groupManager; /** * A mapping of user IDs to the User objects */ protected Map<String, User> m_users; /** * The duty schedules for each user */ protected HashMap<String, List<DutySchedule>> m_dutySchedules; private Header oldHeader; /** * <p>Constructor for UserManager.</p> * * @param groupManager a {@link org.opennms.netmgt.config.GroupManager} object. */ protected UserManager(final GroupManager groupManager) { m_groupManager = groupManager; } /** * <p>parseXML</p> * * @param in a {@link java.io.InputStream} object. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public void parseXML(final InputStream in) throws MarshalException, ValidationException { m_writeLock.lock(); try { final Userinfo userinfo = CastorUtils.unmarshal(Userinfo.class, in); final Users users = userinfo.getUsers(); oldHeader = userinfo.getHeader(); final List<User> usersList = users.getUserCollection(); m_users = new TreeMap<String, User>(); for (final User curUser : usersList) { m_users.put(curUser.getUserId(), curUser); } _buildDutySchedules(m_users); } finally { m_writeLock.unlock(); } } /** * Adds a new user and overwrites the "users.xml" * * @param name a {@link java.lang.String} object. * @param details a {@link org.opennms.netmgt.config.users.User} object. * @throws java.lang.Exception if any. */ public void saveUser(final String name, final User details) throws Exception { m_writeLock.lock(); try { _writeUser(name, details); } finally { m_writeLock.unlock(); } } private void _writeUser(final String name, final User details) throws Exception { if (name == null || details == null) { throw new Exception("UserFactory:saveUser null"); } else { m_users.put(name, details); } _saveCurrent(); } public void save(final OnmsUser user) throws Exception { m_writeLock.lock(); try { User castorUser = _getUser(user.getUsername()); if (castorUser == null) { castorUser = new User(); castorUser.setUserId(user.getUsername()); } castorUser.setFullName(user.getFullName()); castorUser.setUserComments(user.getComments()); final Password pass = new Password(); pass.setContent(user.getPassword()); pass.setSalt(user.getPasswordSalted()); castorUser.setPassword(pass); if (user.getDutySchedule() != null) { castorUser.setDutySchedule(user.getDutySchedule()); } _writeUser(user.getUsername(), castorUser); } finally { m_writeLock.unlock(); } } /** * Builds a mapping between user IDs and duty schedules. These are used by * Notifd when determining to send a notice to a given user. This helps * speed up the decision process. * * @param users * the map of users parsed from the XML configuration file */ private void _buildDutySchedules(final Map<String,User> users) { m_dutySchedules = new HashMap<String,List<DutySchedule>>(); for (final String key : users.keySet()) { final User curUser = users.get(key); if (curUser.getDutyScheduleCount() > 0) { final List<DutySchedule> dutyList = new ArrayList<DutySchedule>(); for (final String duty : curUser.getDutyScheduleCollection()) { dutyList.add(new DutySchedule(duty)); } m_dutySchedules.put(key, dutyList); } } } /** * Determines if a user is on duty at a given time. If a user has no duty * schedules listed in the configuration file, that user is assumed to always be on * duty. * * @param user * the user id * @param time * the time to check for a duty schedule * @return boolean, true if the user is on duty, false otherwise. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public boolean isUserOnDuty(final String user, final Calendar time) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { // if the user has no duty schedules then he is on duty if (!m_dutySchedules.containsKey(user)) return true; for (final DutySchedule curSchedule : m_dutySchedules.get(user)) { if (curSchedule.isInSchedule(time)) { return true; } } } finally { m_readLock.unlock(); } return false; } /** * Return a <code>Map</code> of usernames to user instances. * * @return a {@link java.util.Map} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public Map<String, User> getUsers() throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return Collections.unmodifiableMap(m_users); } finally { m_readLock.unlock(); } } public OnmsUserList getOnmsUserList() throws MarshalException, ValidationException, IOException { final OnmsUserList list = new OnmsUserList(); m_readLock.lock(); try { for (final String username : _getUserNames()) { list.add(_getOnmsUser(username)); } list.setTotalCount(list.getCount()); return list; } finally { m_readLock.unlock(); } } public OnmsUser getOnmsUser(final String username) throws MarshalException, ValidationException, IOException { m_readLock.lock(); try { return _getOnmsUser(username); } finally { m_readLock.unlock(); } } private OnmsUser _getOnmsUser(final String username) throws IOException, MarshalException, ValidationException { final User castorUser = _getUser(username); if (castorUser == null) return null; final OnmsUser user = new OnmsUser(username); user.setFullName(castorUser.getFullName()); user.setComments(castorUser.getUserComments()); user.setPassword(castorUser.getPassword().getContent()); user.setPasswordSalted(castorUser.getPassword().getSalt()); user.setDutySchedule(castorUser.getDutyScheduleCollection()); return user; } /** * Returns a boolean indicating if the user name appears in the XML file * * @return true if the user exists in the XML file, false otherwise * @param userName a {@link java.lang.String} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public boolean hasUser(final String userName) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return m_users.containsKey(userName); } finally { m_readLock.unlock(); } } /** * <p>getUserNames</p> * * @return a {@link java.util.List} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public List<String> getUserNames() throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getUserNames(); } finally { m_readLock.unlock(); } } private List<String> _getUserNames() { final List<String> userNames = new ArrayList<String>(); userNames.addAll(m_users.keySet()); return userNames; } /** * Get a user by name * * @param name * the name of the user to return * @return the user specified by name * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public User getUser(final String name) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getUser(name); } finally { m_readLock.unlock(); } } private User _getUser(final String name) { return m_users.get(name); } /** * Get a user's telephone PIN by name * * @param name * the name of the user to return * @return the telephone PIN of the user specified by name * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTuiPin(final String name) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return m_users.get(name).getTuiPin(); } finally { m_readLock.unlock(); } } /** * Get a user's telephone PIN by User object * * @return the telephone PIN of the user specified by user * @param user a {@link org.opennms.netmgt.config.users.User} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTuiPin(final User user) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return m_users.get(user.getUserId()).getTuiPin(); } finally { m_readLock.unlock(); } } /** * Get a user's microblog username by username * * @param name * the username of the user whose microblog username should be returned * @return the microblog username of the specified user * @throws java.io.IOException if any. * @throws java.io.FileNotFoundException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. */ public String getMicroblogName(final String name) throws MarshalException, ValidationException, FileNotFoundException, IOException { return getContactInfo(name, "microblog"); } /** * Get a user's microblog username by User * * @param user * the user object of the user whose microblog username should be returned * @return the microblog username of the specified user * @throws java.io.IOException if any. * @throws java.io.FileNotFoundException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. */ public String getMicroblogName(final User user) throws MarshalException, ValidationException, FileNotFoundException, IOException { return getContactInfo(user, "microblog"); } /** * Get the contact info given a command string * * @param userID * the name of the user * @param command * the command to look up the contact info for * @return the contact information * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getContactInfo(final String userID, final String command) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { final User user = m_users.get(userID); return _getContactInfo(user, command); } finally { m_readLock.unlock(); } } /** * <p>getContactInfo</p> * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @param command a {@link java.lang.String} object. * @return a {@link java.lang.String} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getContactInfo(final User user, final String command) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getContactInfo(user, command); } finally { m_readLock.unlock(); } } private String _getContactInfo(final User user, final String command) { if (user == null) return ""; for (final Contact contact : user.getContactCollection()) { if (contact != null && contact.getType().equals(command)) { return contact.getInfo(); } } return ""; } /** * Get the contact service provider, given a command string * * @param userID * the name of the user * @param command * the command to look up the contact info for * @return the contact information * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getContactServiceProvider(final String userID, final String command) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { final User user = m_users.get(userID); return _getContactServiceProvider(user, command); } finally { m_readLock.unlock(); } } /** * <p>getContactServiceProvider</p> * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @param command a {@link java.lang.String} object. * @return a {@link java.lang.String} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getContactServiceProvider(final User user, final String command) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getContactServiceProvider(user, command); } finally { m_readLock.unlock(); } } private String _getContactServiceProvider(final User user, final String command) { if (user == null) return ""; for (final Contact contact : user.getContactCollection()) { if (contact != null && contact.getType().equals(command)) { return contact.getServiceProvider(); } } return ""; } /** * Get a email by name * * @param userID * the user ID of the user to return * @return String the email specified by name * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getEmail(final String userID) throws IOException, MarshalException, ValidationException { return getContactInfo(userID, "email"); } /** * Get a email by user * * @param user the user to find the email for * @return String the email specified by name * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getEmail(final User user) throws IOException, MarshalException, ValidationException { return getContactInfo(user, "email"); } /** * Get a pager email by name * * @param userID * the user ID of the user to return * @return String the pager email * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getPagerEmail(final String userID) throws IOException, MarshalException, ValidationException { return getContactInfo(userID, "pagerEmail"); } /** * Get a pager email by user * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @return String the pager email * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getPagerEmail(final User user) throws IOException, MarshalException, ValidationException { return getContactInfo(user, "pagerEmail"); } /** * Get a numeric pin * * @param userID * the user ID of the user to return * @return String the numeric pin * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getNumericPin(final String userID) throws IOException, MarshalException, ValidationException { return getContactInfo(userID, "numericPage"); } /** * Get a numeric pin * * @return String the numeric pin * @param user a {@link org.opennms.netmgt.config.users.User} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getNumericPin(final User user) throws IOException, MarshalException, ValidationException { return getContactInfo(user, "numericPage"); } /** * Get an XMPP address by name * * @param userID * the user ID of the user to return * @return String the XMPP address * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getXMPPAddress(final String userID) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { final User user = m_users.get(userID); return _getXMPPAddress(user); } finally { m_readLock.unlock(); } } /** * Get an XMPP address by name * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @return String the XMPP address * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getXMPPAddress(final User user) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getXMPPAddress(user); } finally { m_readLock.unlock(); } } private String _getXMPPAddress(final User user) { if (user == null) return ""; for (final Contact contact : user.getContactCollection()) { if (contact != null && contact.getType().equals("xmppAddress")) { return contact.getInfo(); } } return ""; } /** * Get a numeric service provider * * @param userID * the user ID of the user to return * @return String the service provider * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getNumericPage(final String userID) throws IOException, MarshalException, ValidationException { return getContactServiceProvider(userID, "numericPage"); } /** * Get a numeric service provider * * @return String the service provider * @param user a {@link org.opennms.netmgt.config.users.User} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getNumericPage(final User user) throws IOException, MarshalException, ValidationException { return getContactServiceProvider(user, "numericPage"); } /** * Get a text pin * * @param userID * the user ID of the user to return * @return String the text pin * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTextPin(final String userID) throws IOException, MarshalException, ValidationException { return getContactInfo(userID, "textPage"); } /** * Get a text pin * * @return String the text pin * @param user a {@link org.opennms.netmgt.config.users.User} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTextPin(final User user) throws IOException, MarshalException, ValidationException { return getContactInfo(user, "textPage"); } /** * Get a Text Page Service Provider * * @param userID * the user ID of the user to return * @return String the text page service provider. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTextPage(final String userID) throws IOException, MarshalException, ValidationException { return getContactServiceProvider(userID, "textPage"); } /** * Get a Text Page Service Provider * * @return String the text page service provider. * @param user a {@link org.opennms.netmgt.config.users.User} object. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String getTextPage(final User user) throws IOException, MarshalException, ValidationException { return getContactServiceProvider(user, "textPage"); } /** * Get a work phone number * * @param userID * the user ID of the user to return * @return String the work phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. */ public String getWorkPhone(final String userID) throws MarshalException, ValidationException, IOException { return getContactInfo(userID, "workPhone"); } /** * Get a work phone number * * @return String the work phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @param user a {@link org.opennms.netmgt.config.users.User} object. */ public String getWorkPhone(final User user) throws MarshalException, ValidationException, IOException { return getContactInfo(user, "workPhone"); } /** * Get a mobile phone number * * @param userID * the user ID of the user to return * @return String the mobile phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. */ public String getMobilePhone(final String userID) throws MarshalException, ValidationException, IOException { return getContactInfo(userID, "mobilePhone"); } /** * Get a mobile phone number * * @return String the mobile phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @param user a {@link org.opennms.netmgt.config.users.User} object. */ public String getMobilePhone(final User user) throws MarshalException, ValidationException, IOException { return getContactInfo(user, "mobilePhone"); } /** * Get a home phone number * * @param userID * the user ID of the user to return * @return String the home phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. */ public String getHomePhone(final String userID) throws MarshalException, ValidationException, IOException { return getContactInfo(userID, "homePhone"); } /** * Get a home phone number * * @return String the home phone number * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @param user a {@link org.opennms.netmgt.config.users.User} object. */ public String getHomePhone(final User user) throws MarshalException, ValidationException, IOException { return getContactInfo(user, "homePhone"); } /** * <p>saveUsers</p> * * @param usersList a {@link java.util.Collection} object. * @throws java.lang.Exception if any. */ public void saveUsers(final Collection<User> usersList) throws Exception { m_writeLock.lock(); try { // clear out the internal structure and reload it m_users.clear(); for (final User curUser : usersList) { m_users.put(curUser.getUserId(), curUser); } } finally { m_writeLock.unlock(); } } /** * Removes the user from the list of users. Then overwrites to the * "users.xml" * * @param name a {@link java.lang.String} object. * @throws java.lang.Exception if any. */ public void deleteUser(final String name) throws Exception { m_writeLock.lock(); try { // Check if the user exists if (m_users.containsKey(name)) { // Delete the user in the user map. m_users.remove(name); // Delete the user in the group. m_groupManager.deleteUser(name); // Delete the user in the view. // viewFactory.deleteUser(name); } else { throw new Exception("UserFactory:delete The old user name " + name + " is not found"); } _saveCurrent(); } finally { m_writeLock.unlock(); } } /** * Saves into "users.xml" file */ private void _saveCurrent() throws Exception { final Users users = new Users(); for (final User user : m_users.values()) { users.addUser(user); } final Userinfo userinfo = new Userinfo(); userinfo.setUsers(users); final Header header = oldHeader; if (header != null) { header.setCreated(EventConstants.formatToString(new Date())); userinfo.setHeader(header); } oldHeader = header; // marshal to a string first, then write the string to the file. This // way the original configuration // isn't lost if the XML from the marshal is hosed. final StringWriter stringWriter = new StringWriter(); Marshaller.marshal(userinfo, stringWriter); final String writerString = stringWriter.toString(); saveXML(writerString); } /** * <p>saveXML</p> * * @param writerString a {@link java.lang.String} object. * @throws java.io.IOException if any. */ protected abstract void saveXML(final String writerString) throws IOException ; /** * When this method is called users name is changed, so also is the username * belonging to the group and the view. Also overwrites the "users.xml" file * * @param oldName a {@link java.lang.String} object. * @param newName a {@link java.lang.String} object. * @throws java.lang.Exception if any. */ public void renameUser(final String oldName, final String newName) throws Exception { m_writeLock.lock(); try { // Get the old data if (m_users.containsKey(oldName)) { final User data = m_users.get(oldName); if (data == null) { m_users.remove(oldName); throw new Exception("UserFactory:rename the data contained for old user " + oldName + " is null"); } else { // Rename the user in the user map. m_users.remove(oldName); data.setUserId(newName); m_users.put(newName, data); // Rename the user in the group. m_groupManager.renameUser(oldName, newName); // Rename the user in the view. // viewFactory.renameUser(oldName, newName); } } else { throw new Exception("UserFactory:rename the old user name " + oldName + " is not found"); } _saveCurrent(); } finally { m_writeLock.unlock(); } } /** * Sets the password for this user, assuming that the value passed in is * already encrypted properly * * @param userID * the user ID to change the password for * @param aPassword * the encrypted password * @throws java.lang.Exception if any. */ public void setEncryptedPassword(final String userID, final String aPassword, final boolean salted) throws Exception { m_writeLock.lock(); try { final User user = m_users.get(userID); if (user != null) { final Password pass = new Password(); pass.setContent(aPassword); pass.setSalt(salted); user.setPassword(pass); } _saveCurrent(); } finally { m_writeLock.unlock(); } } /** * Sets the password for this user, first encrypting it * * @param userID * the user ID to change the password for * @param aPassword * the password * @throws java.lang.Exception if any. */ public void setUnencryptedPassword(final String userID, final String aPassword) throws Exception { m_writeLock.lock(); try { final User user = m_users.get(userID); if (user != null) { final Password pass = new Password(); pass.setContent(encryptedPassword(aPassword, true)); pass.setSalt(true); user.setPassword(pass); } _saveCurrent(); } finally { m_writeLock.unlock(); } } /** * <p>encryptedPassword</p> * * @param aPassword a {@link java.lang.String} object. * @param useSalt TODO * @return a {@link java.lang.String} object. */ public String encryptedPassword(final String aPassword, final boolean useSalt) { String encryptedPassword = null; if (useSalt) { encryptedPassword = m_passwordEncryptor.encryptPassword(aPassword); } else { // old crappy algorithm try { final MessageDigest digest = MessageDigest.getInstance("MD5"); // build the digest, get the bytes, convert to hexadecimal string // and return encryptedPassword = hexToString(digest.digest(aPassword.getBytes())); } catch (final NoSuchAlgorithmException e) { throw new IllegalStateException(e.toString()); } } return encryptedPassword; } /** * @param data * @return */ private String hexToString(final byte[] data) { // check to see if the byte array has an even number of elements if ((data.length % 2) != 0) return null; // there will be two hexadecimal characters for each byte element final char[] buffer = new char[data.length * 2]; for (int i = 0; i < data.length; i++) { final int low = (int) (data[i] & 0x0f); final int high = (int) ((data[i] & 0xf0) >> 4); buffer[i * 2] = HEX[high]; buffer[i * 2 + 1] = HEX[low]; } return new String(buffer); } /** * This method compares two encrypted strings for equality. * * @param userID * the user ID to check against. * @param aPassword * the password to check for equality * @return true if the two passwords are equal (after encryption), false * otherwise */ public boolean comparePasswords(final String userID, final String aPassword) { m_readLock.lock(); try { final User user = m_users.get(userID); if (user == null) return false; final String password = user.getPassword().getContent().trim(); final boolean isSalted = user.getPassword().getSalt(); if (isSalted) { return checkSaltedPassword(aPassword, password); } else { return password.equals(encryptedPassword(aPassword, false)); } } finally { m_readLock.unlock(); } } public boolean checkSaltedPassword(final String raw, final String encrypted) { return m_passwordEncryptor.checkPassword(raw, encrypted); } /** * <p>update</p> * * @throws java.io.IOException if any. * @throws java.io.FileNotFoundException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ protected abstract void doUpdate() throws IOException, FileNotFoundException, MarshalException, ValidationException; public final void update() throws IOException, FileNotFoundException, MarshalException, ValidationException { m_writeLock.lock(); try { doUpdate(); } finally { m_writeLock.unlock(); } } /** * <p>getUsersWithRole</p> * * @param roleid a {@link java.lang.String} object. * @return an array of {@link java.lang.String} objects. * @throws java.io.IOException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. */ public String[] getUsersWithRole(final String roleid) throws IOException, MarshalException, ValidationException { update(); m_readLock.lock(); try { return _getUsersWithRole(roleid); } finally { m_readLock.unlock(); } } private String[] _getUsersWithRole(final String roleid) throws MarshalException, ValidationException, IOException { final List<String> usersWithRole = new ArrayList<String>(); for (final User user : m_users.values()) { if (_userHasRole(user, roleid)) { usersWithRole.add(user.getUserId()); } } return usersWithRole.toArray(new String[usersWithRole.size()]); } /** * <p>userHasRole</p> * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @param roleid a {@link java.lang.String} object. * @return a boolean. * @throws java.io.FileNotFoundException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws java.io.IOException if any. */ public boolean userHasRole(final User user, final String roleid) throws FileNotFoundException, MarshalException, ValidationException, IOException { update(); m_readLock.lock(); try { return _userHasRole(user, roleid); } finally { m_readLock.unlock(); } } private boolean _userHasRole(final User user, final String roleid) throws MarshalException, ValidationException, IOException { if (roleid == null) throw new NullPointerException("roleid is null"); return m_groupManager.userHasRole(user.getUserId(), roleid); } /** * <p>isUserScheduledForRole</p> * * @param user a {@link org.opennms.netmgt.config.users.User} object. * @param roleid a {@link java.lang.String} object. * @param time a {@link java.util.Date} object. * @return a boolean. * @throws java.io.FileNotFoundException if any. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws java.io.IOException if any. */ public boolean isUserScheduledForRole(final User user, final String roleid, final Date time) throws FileNotFoundException, MarshalException, ValidationException, IOException { update(); m_readLock.lock(); try { return _isUserScheduledForRole(user, roleid, time); } finally { m_readLock.unlock(); } } private boolean _isUserScheduledForRole(final User user, final String roleid, final Date time) throws MarshalException, ValidationException, IOException { if (roleid == null) throw new NullPointerException("roleid is null"); return m_groupManager.isUserScheduledForRole(user.getUserId(), roleid, time); } /** * <p>getUsersScheduledForRole</p> * * @param roleid a {@link java.lang.String} object. * @param time a {@link java.util.Date} object. * @return an array of {@link java.lang.String} objects. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws java.io.IOException if any. */ public String[] getUsersScheduledForRole(final String roleid, final Date time) throws MarshalException, ValidationException, IOException { update(); m_readLock.lock(); try { final List<String> usersScheduledForRole = new ArrayList<String>(); for (final User user : m_users.values()) { if (_isUserScheduledForRole(user, roleid, time)) { usersScheduledForRole.add(user.getUserId()); } } return usersScheduledForRole.toArray(new String[usersScheduledForRole.size()]); } finally { m_readLock.unlock(); } } /** * <p>hasRole</p> * * @param roleid a {@link java.lang.String} object. * @return a boolean. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws java.io.IOException if any. */ public boolean hasRole(final String roleid) throws MarshalException, ValidationException, IOException { m_readLock.lock(); try { return m_groupManager.getRole(roleid) != null; } finally { m_readLock.unlock(); } } /** * <p>countUsersWithRole</p> * * @param roleid a {@link java.lang.String} object. * @return a int. * @throws org.exolab.castor.xml.MarshalException if any. * @throws org.exolab.castor.xml.ValidationException if any. * @throws java.io.IOException if any. */ public int countUsersWithRole(final String roleid) throws MarshalException, ValidationException, IOException { m_readLock.lock(); try { final String[] users = _getUsersWithRole(roleid); if (users == null) return 0; return users.length; } finally { m_readLock.unlock(); } } /** * <p>isUpdateNeeded</p> * * @return a boolean. */ public abstract boolean isUpdateNeeded(); public abstract long getLastModified(); }