Commit f839625a authored by Dave Cridland's avatar Dave Cridland

Merge pull request #75 from Redor/openfire

User Service Plugin update to 2.0.0
parents 436b90e3 49ebcaac
......@@ -43,6 +43,16 @@
<h1>
User Service Plugin Changelog
</h1>
<p><b>2.0.0</b> -- October 4th, 2014</p>
<ul>
<li>New restfull API (see readme). The plugin is backward compatible.</li>
<li>Added new requst to get all or specific users</li>
<li>The user is now extendible with key / values properties</li>
<li>Added new requst to get roster entries of a specific users</li>
<li>Added new requst to get group names of a specific users</li>
<li>Added new request to add user to a group or remove a user from a group</li>
</ul>
<p><b>1.4.4</b> -- May 5th, 2014</p>
<ul>
<li>Added new requests grouplist and usergrouplist</li>
......
......@@ -4,9 +4,9 @@
<class>org.jivesoftware.openfire.plugin.UserServicePlugin</class>
<name>User Service</name>
<description>Allows administration of users via HTTP requests.</description>
<author>Justin Hunt</author>
<version>1.4.4</version>
<date>26/05/2014</date>
<author>Roman Soldatow, Justin Hunt</author>
<version>2.0.0</version>
<date>10/04/2014</date>
<minServerVersion>3.9.0</minServerVersion>
<adminconsole>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
package org.jivesoftware.openfire.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The Class RosterEntities.
*/
@XmlRootElement(name = "roster")
public class RosterEntities {
/** The roster. */
List<RosterItemEntity> roster;
/**
* Instantiates a new roster entities.
*/
public RosterEntities() {
}
/**
* Instantiates a new roster entities.
*
* @param roster
* the roster
*/
public RosterEntities(List<RosterItemEntity> roster) {
this.roster = roster;
}
/**
* Gets the roster.
*
* @return the roster
*/
@XmlElement(name = "rosterItem")
public List<RosterItemEntity> getRoster() {
return roster;
}
/**
* Sets the roster.
*
* @param roster
* the new roster
*/
public void setRoster(List<RosterItemEntity> roster) {
this.roster = roster;
}
}
package org.jivesoftware.openfire.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* The Class RosterItemEntity.
*/
@XmlRootElement(name = "rosterItem")
@XmlType(propOrder = { "jid", "nickname", "subscriptionType", "groups" })
public class RosterItemEntity {
/** The jid. */
private String jid;
/** The nickname. */
private String nickname;
/** The subscription type. */
private int subscriptionType;
/** The groups. */
private List<String> groups;
/**
* Instantiates a new roster item entity.
*/
public RosterItemEntity() {
}
/**
* Instantiates a new roster item entity.
*
* @param jid
* the jid
* @param nickname
* the nickname
* @param subscriptionType
* the subscription type
*/
public RosterItemEntity(String jid, String nickname, int subscriptionType) {
this.jid = jid;
this.nickname = nickname;
this.subscriptionType = subscriptionType;
}
/**
* Gets the jid.
*
* @return the jid
*/
@XmlElement
public String getJid() {
return jid;
}
/**
* Sets the jid.
*
* @param jid
* the new jid
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Gets the nickname.
*
* @return the nickname
*/
@XmlElement
public String getNickname() {
return nickname;
}
/**
* Sets the nickname.
*
* @param nickname
* the new nickname
*/
public void setNickname(String nickname) {
this.nickname = nickname;
}
/**
* Gets the subscription type.
*
* @return the subscription type
*/
@XmlElement
public int getSubscriptionType() {
return subscriptionType;
}
/**
* Sets the subscription type.
*
* @param subscriptionType
* the new subscription type
*/
public void setSubscriptionType(int subscriptionType) {
this.subscriptionType = subscriptionType;
}
/**
* Gets the groups.
*
* @return the groups
*/
@XmlElement(name = "group")
@XmlElementWrapper(name = "groups")
public List<String> getGroups() {
return groups;
}
/**
* Sets the groups.
*
* @param groups
* the new groups
*/
public void setGroups(List<String> groups) {
this.groups = groups;
}
}
package org.jivesoftware.openfire.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The Class UserEntities.
*/
@XmlRootElement(name = "users")
public class UserEntities {
/** The users. */
List<UserEntity> users;
/**
* Instantiates a new user entities.
*/
public UserEntities() {
}
/**
* Instantiates a new user entities.
*
* @param users
* the users
*/
public UserEntities(List<UserEntity> users) {
this.users = users;
}
/**
* Gets the users.
*
* @return the users
*/
@XmlElement(name = "user")
public List<UserEntity> getUsers() {
return users;
}
/**
* Sets the users.
*
* @param users
* the new users
*/
public void setUsers(List<UserEntity> users) {
this.users = users;
}
}
package org.jivesoftware.openfire.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* The Class UserEntity.
*/
@XmlRootElement(name = "user")
@XmlType(propOrder = { "username", "name", "email", "password", "properties" })
public class UserEntity {
/** The username. */
private String username;
/** The name. */
private String name;
/** The email. */
private String email;
/** The password. */
private String password;
/** The properties. */
private List<UserProperty> properties;
/**
* Instantiates a new user entity.
*/
public UserEntity() {
}
/**
* Instantiates a new user entity.
*
* @param username
* the username
* @param name
* the name
* @param email
* the email
*/
public UserEntity(String username, String name, String email) {
this.username = username;
this.name = name;
this.email = email;
}
/**
* Gets the username.
*
* @return the username
*/
@XmlElement
public String getUsername() {
return username;
}
/**
* Sets the username.
*
* @param username
* the new username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Gets the name.
*
* @return the name
*/
@XmlElement
public String getName() {
return name;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the email.
*
* @return the email
*/
@XmlElement
public String getEmail() {
return email;
}
/**
* Sets the email.
*
* @param email
* the new email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Gets the password.
*
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Sets the password.
*
* @param password
* the new password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Gets the properties.
*
* @return the properties
*/
@XmlElement(name = "property")
@XmlElementWrapper(name = "properties")
public List<UserProperty> getProperties() {
return properties;
}
/**
* Sets the properties.
*
* @param properties
* the new properties
*/
public void setProperties(List<UserProperty> properties) {
this.properties = properties;
}
}
package org.jivesoftware.openfire.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The Class UserGroupsEntity.
*/
@XmlRootElement(name = "groups")
public class UserGroupsEntity {
/** The group names. */
private List<String> groupNames;
/**
* Instantiates a new user groups entity.
*/
public UserGroupsEntity() {
}
/**
* Instantiates a new user groups entity.
*
* @param groupNames
* the group names
*/
public UserGroupsEntity(List<String> groupNames) {
this.groupNames = groupNames;
}
/**
* Gets the group names.
*
* @return the group names
*/
@XmlElement(name = "groupname")
public List<String> getGroupNames() {
return groupNames;
}
/**
* Sets the group names.
*
* @param groupNames
* the new group names
*/
public void setGroupNames(List<String> groupNames) {
this.groupNames = groupNames;
}
}
package org.jivesoftware.openfire.entity;
import javax.xml.bind.annotation.XmlAttribute;
/**
* The Class UserProperty.
*/
public class UserProperty {
/** The key. */
private String key;
/** The value. */
private String value;
/**
* Instantiates a new user property.
*/
public UserProperty() {
}
/**
* Instantiates a new user property.
*
* @param key
* the key
* @param value
* the value
*/
public UserProperty(String key, String value) {
this.key = key;
this.value = value;
}
/**
* Gets the key.
*
* @return the key
*/
@XmlAttribute
public String getKey() {
return key;
}
/**
* Sets the key.
*
* @param key
* the new key
*/
public void setKey(String key) {
this.key = key;
}
/**
* Gets the value.
*
* @return the value
*/
@XmlAttribute
public String getValue() {
return value;
}
/**
* Sets the value.
*
* @param value
* the new value
*/
public void setValue(String value) {
this.value = value;
}
}
package org.jivesoftware.openfire.exceptions;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The Class ErrorResponse.
*/
@XmlRootElement(name = "error")
public class ErrorResponse {
/** The ressource. */
private String ressource;
/** The message. */
private String message;
/** The exception. */
private String exception;
/** The exception stack. */
private String exceptionStack;
/**
* Gets the ressource.
*
* @return the ressource
*/
public String getRessource() {
return ressource;
}
/**
* Sets the ressource.
*
* @param ressource
* the new ressource
*/
public void setRessource(String ressource) {
this.ressource = ressource;
}
/**
* Gets the message.
*
* @return the message
*/
public String getMessage() {
return message;
}
/**
* Sets the message.
*
* @param message
* the new message
*/
public void setMessage(String message) {
this.message = message;
}
/**
* Gets the exception.
*
* @return the exception
*/
public String getException() {
return exception;
}
/**
* Sets the exception.
*
* @param exception
* the new exception
*/
public void setException(String exception) {
this.exception = exception;
}
/**
* Gets the exception stack.
*
* @return the exception stack
*/
public String getExceptionStack() {
return exceptionStack;
}
/**
* Sets the exception stack.
*
* @param exceptionStack
* the new exception stack
*/
public void setExceptionStack(String exceptionStack) {
this.exceptionStack = exceptionStack;
}
}
\ No newline at end of file
package org.jivesoftware.openfire.exceptions;
/**
* The Class ExceptionType.
*/
public final class ExceptionType {
/** The Constant SHARED_GROUP_EXCEPTION. */
public static final String SHARED_GROUP_EXCEPTION = "SharedGroupException";
/** The Constant PROPERTY_NOT_FOUND. */
public static final String PROPERTY_NOT_FOUND = "PropertyNotFoundException";
/** The Constant USER_ALREADY_EXISTS_EXCEPTION. */
public static final String USER_ALREADY_EXISTS_EXCEPTION = "UserAlreadyExistsException";
/** The Constant USER_NOT_FOUND_EXCEPTION. */
public static final String USER_NOT_FOUND_EXCEPTION = "UserNotFoundException";
/** The Constant GROUP_ALREADY_EXISTS. */
public static final String GROUP_ALREADY_EXISTS = "GroupAlreadyExistsException";
/** The Constant GROUP_NOT_FOUND. */
public static final String GROUP_NOT_FOUND = "GroupNotFoundException";
/**
* Instantiates a new exception type.
*/
private ExceptionType() {
}
}
package org.jivesoftware.openfire.exceptions;
import javax.ws.rs.core.Response.Status;
/**
* The Class MUCServiceException.
*/
public class ServiceException extends Exception {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 4351720088030656859L;
/** The ressource. */
private String ressource;
/** The exception. */
private String exception;
/** The status. */
private Status status;
/**
* Instantiates a new mUC service exception.
*
* @param msg
* the msg
* @param ressource
* the ressource
* @param exception
* the exception
* @param status
* the status
*/
public ServiceException(String msg, String ressource, String exception, Status status) {
super(msg);
this.ressource = ressource;
this.exception = exception;
this.status = status;
}
/**
* Instantiates a new service exception.
*
* @param msg
* the msg
* @param ressource
* the ressource
* @param exception
* the exception
* @param status
* the status
* @param cause
* the cause
*/
public ServiceException(String msg, String ressource, String exception, Status status, Throwable cause) {
super(msg, cause);
this.ressource = ressource;
this.exception = exception;
this.status = status;
}
/**
* Gets the ressource.
*
* @return the ressource
*/
public String getRessource() {
return ressource;
}
/**
* Sets the ressource.
*
* @param ressource
* the new ressource
*/
public void setRessource(String ressource) {
this.ressource = ressource;
}
/**
* Gets the exception.
*
* @return the exception
*/
public String getException() {
return exception;
}
/**
* Sets the exception.
*
* @param exception
* the new exception
*/
public void setException(String exception) {
this.exception = exception;
}
/**
* Gets the status.
*
* @return the status
*/
public Status getStatus() {
return status;
}
/**
* Sets the status.
*
* @param status
* the new status
*/
public void setStatus(Status status) {
this.status = status;
}
}
\ No newline at end of file
package org.jivesoftware.openfire.plugin;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response.Status;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.admin.AdminManager;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.ConnectionException;
import org.jivesoftware.openfire.auth.InternalUnauthenticatedException;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
/**
* The Class AuthFilter.
*/
public class AuthFilter implements ContainerRequestFilter {
/** The log. */
private static Logger LOG = LoggerFactory.getLogger(AuthFilter.class);
/** The http request. */
@Context
private HttpServletRequest httpRequest;
/** The plugin. */
private UserServicePlugin plugin = (UserServicePlugin) XMPPServer.getInstance().getPluginManager()
.getPlugin("userservice");
/*
* (non-Javadoc)
*
* @see
* com.sun.jersey.spi.container.ContainerRequestFilter#filter(com.sun.jersey
* .spi.container.ContainerRequest)
*/
@Override
public ContainerRequest filter(ContainerRequest containerRequest) throws WebApplicationException {
if (!plugin.isEnabled()) {
throw new WebApplicationException(Status.FORBIDDEN);
}
if (!plugin.getAllowedIPs().isEmpty()) {
// Get client's IP address
String ipAddress = httpRequest.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = httpRequest.getHeader("X_FORWARDED_FOR");
if (ipAddress == null) {
ipAddress = httpRequest.getHeader("X-Forward-For");
if (ipAddress == null) {
ipAddress = httpRequest.getRemoteAddr();
}
}
}
if (!plugin.getAllowedIPs().contains(ipAddress)) {
LOG.warn("User service rejected service to IP address: " + ipAddress);
throw new WebApplicationException(Status.UNAUTHORIZED);
}
}
// Get the authentification passed in HTTP headers parameters
String auth = containerRequest.getHeaderValue("authorization");
if (auth == null) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
// HTTP Basic Auth or Shared Secret key
if (plugin.isHttpBasicAuth()) {
String[] usernameAndPassword = BasicAuth.decode(auth);
// If username or password fail
if (usernameAndPassword == null || usernameAndPassword.length != 2) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
boolean userAdmin = AdminManager.getInstance().isUserAdmin(usernameAndPassword[0], true);
if (!userAdmin) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
try {
AuthFactory.authenticate(usernameAndPassword[0], usernameAndPassword[1]);
} catch (UnauthorizedException e) {
LOG.warn("Wrong HTTP Basic Auth authorization", e);
throw new WebApplicationException(Status.UNAUTHORIZED);
} catch (ConnectionException e) {
throw new WebApplicationException(Status.UNAUTHORIZED);
} catch (InternalUnauthenticatedException e) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
} else {
if (!auth.equals(plugin.getSecret())) {
LOG.warn("Wrong secret key authorization. Provided key: " + auth);
throw new WebApplicationException(Status.UNAUTHORIZED);
}
}
return containerRequest;
}
}
\ No newline at end of file
package org.jivesoftware.openfire.plugin;
import javax.xml.bind.DatatypeConverter;
public class BasicAuth {
/**
* Decode the basic auth and convert it to array login/password
*
* @param auth
* The string encoded authentification
* @return The login (case 0), the password (case 1)
*/
public static String[] decode(String auth) {
// Replacing "Basic THE_BASE_64" to "THE_BASE_64" directly
auth = auth.replaceFirst("[B|b]asic ", "");
// Decode the Base64 into byte[]
byte[] decodedBytes = DatatypeConverter.parseBase64Binary(auth);
// If the decode fails in any case
if (decodedBytes == null || decodedBytes.length == 0) {
return null;
}
// Now we can convert the byte[] into a splitted array :
// - the first one is login,
// - the second one password
return new String(decodedBytes).split(":", 2);
}
}
package org.jivesoftware.openfire.plugin;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.jivesoftware.admin.AuthCheckFilter;
import org.jivesoftware.openfire.plugin.service.UserGroupService;
import org.jivesoftware.openfire.plugin.service.UserLockoutService;
import org.jivesoftware.openfire.plugin.service.UserRosterService;
import org.jivesoftware.openfire.plugin.service.UserService;
import org.jivesoftware.openfire.plugin.service.UserServiceLegacy;
import org.jivesoftware.openfire.plugin.service.UserServiceProperties;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
/**
* The Class JerseyWrapper.
*/
public class JerseyWrapper extends ServletContainer {
/** The Constant AUTHFILTER. */
private static final String AUTHFILTER = "org.jivesoftware.openfire.plugin.AuthFilter";
/** The Constant CONTAINER_REQUEST_FILTERS. */
private static final String CONTAINER_REQUEST_FILTERS = "com.sun.jersey.spi.container.ContainerRequestFilters";
/** The Constant RESOURCE_CONFIG_CLASS_KEY. */
private static final String RESOURCE_CONFIG_CLASS_KEY = "com.sun.jersey.config.property.resourceConfigClass";
/** The Constant RESOURCE_CONFIG_CLASS. */
private static final String RESOURCE_CONFIG_CLASS = "com.sun.jersey.api.core.PackagesResourceConfig";
/** The Constant SCAN_PACKAGE_DEFAULT. */
private static final String SCAN_PACKAGE_DEFAULT = JerseyWrapper.class.getPackage().getName();
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The Constant SERVLET_URL. */
private static final String SERVLET_URL = "userService/*";
/** The config. */
private static Map<String, Object> config;
/** The prc. */
private static PackagesResourceConfig prc;
static {
config = new HashMap<String, Object>();
config.put(RESOURCE_CONFIG_CLASS_KEY, RESOURCE_CONFIG_CLASS);
prc = new PackagesResourceConfig(SCAN_PACKAGE_DEFAULT);
prc.setPropertiesAndFeatures(config);
prc.getProperties().put(CONTAINER_REQUEST_FILTERS, AUTHFILTER);
prc.getClasses().add(UserServiceLegacy.class);
prc.getClasses().add(UserService.class);
prc.getClasses().add(UserRosterService.class);
prc.getClasses().add(UserGroupService.class);
prc.getClasses().add(UserServiceProperties.class);
prc.getClasses().add(UserLockoutService.class);
prc.getClasses().add(RESTExceptionMapper.class);
}
/**
* Instantiates a new jersey wrapper.
*/
public JerseyWrapper() {
super(prc);
}
/*
* (non-Javadoc)
*
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
// Exclude this servlet from requering the user to login
AuthCheckFilter.addExclude(SERVLET_URL);
}
/*
* (non-Javadoc)
*
* @see com.sun.jersey.spi.container.servlet.ServletContainer#destroy()
*/
@Override
public void destroy() {
super.destroy();
// Release the excluded URL
AuthCheckFilter.removeExclude(SERVLET_URL);
}
}
package org.jivesoftware.openfire.plugin;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.Response;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.exceptions.ExceptionType;
import org.jivesoftware.openfire.exceptions.ServiceException;
/**
* The Class PropertyDAO.
*/
public class PropertyDAO {
/** The Constant LOAD_PROPERTY. */
private final static String LOAD_PROPERTY = "SELECT username FROM ofUserProp WHERE name=? AND propValue=?";
/** The Constant LOAD_PROPERTY_BY_KEY. */
private final static String LOAD_PROPERTY_BY_KEY = "SELECT username FROM ofUserProp WHERE name=?";
/**
* Gets the username by property key and or value.
*
* @param propertyName
* the property name
* @param propertyValue
* the property value (can be null)
* @return the username by property
* @throws ServiceException
* the service exception
*/
public static List<String> getUsernameByProperty(String propertyName, String propertyValue) throws ServiceException {
List<String> usernames = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
// Load property by key and value
if (propertyValue != null) {
pstmt = con.prepareStatement(LOAD_PROPERTY);
pstmt.setString(1, propertyName);
pstmt.setString(2, propertyValue);
} else {
// Load property by key
pstmt = con.prepareStatement(LOAD_PROPERTY_BY_KEY);
pstmt.setString(1, propertyName);
}
rs = pstmt.executeQuery();
while (rs.next()) {
usernames.add(rs.getString(1));
}
} catch (SQLException sqle) {
throw new ServiceException("Could not get username by property", propertyName,
ExceptionType.PROPERTY_NOT_FOUND, Response.Status.NOT_FOUND, sqle);
} finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return usernames;
}
}
package org.jivesoftware.openfire.plugin;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.jivesoftware.openfire.exceptions.ErrorResponse;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class RESTExceptionMapper.
*/
@Provider
public class RESTExceptionMapper implements ExceptionMapper<ServiceException> {
/** The log. */
private static Logger LOG = LoggerFactory.getLogger(RESTExceptionMapper.class);
/**
* Instantiates a new REST exception mapper.
*/
public RESTExceptionMapper() {
}
/*
* (non-Javadoc)
*
* @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable)
*/
public Response toResponse(ServiceException exception) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setRessource(exception.getRessource());
errorResponse.setMessage(exception.getMessage());
errorResponse.setException(exception.getException());
LOG.error(
exception.getException() + ": " + exception.getMessage() + " with ressource "
+ exception.getRessource(), exception.getException());
return Response.status(exception.getStatus()).entity(errorResponse).type(MediaType.APPLICATION_XML).build();
}
}
......@@ -32,9 +32,9 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupAlreadyExistsException;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.group.GroupAlreadyExistsException;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
......@@ -55,386 +55,417 @@ import org.xmpp.packet.JID;
* @author Justin Hunt
*/
public class UserServicePlugin implements Plugin, PropertyEventListener {
private UserManager userManager;
private RosterManager rosterManager;
private XMPPServer server;
private String secret;
private boolean enabled;
private Collection<String> allowedIPs;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
server = XMPPServer.getInstance();
userManager = server.getUserManager();
rosterManager = server.getRosterManager();
secret = JiveGlobals.getProperty("plugin.userservice.secret", "");
// If no secret key has been assigned to the user service yet, assign a random one.
if (secret.equals("")){
secret = StringUtils.randomString(8);
setSecret(secret);
}
// See if the service is enabled or not.
enabled = JiveGlobals.getBooleanProperty("plugin.userservice.enabled", false);
// Get the list of IP addresses that can use this service. An empty list means that this filter is disabled.
allowedIPs = StringUtils.stringToCollection(JiveGlobals.getProperty("plugin.userservice.allowedIPs", ""));
// Listen to system property events
PropertyEventDispatcher.addListener(this);
}
public void destroyPlugin() {
userManager = null;
// Stop listening to system property events
PropertyEventDispatcher.removeListener(this);
}
public void createUser(String username, String password, String name, String email, String groupNames)
throws UserAlreadyExistsException, GroupAlreadyExistsException, UserNotFoundException, GroupNotFoundException
{
userManager.createUser(username, password, name, email);
userManager.getUser(username);
if (groupNames != null) {
Collection<Group> groups = new ArrayList<Group>();
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens())
{
private UserManager userManager;
private RosterManager rosterManager;
private XMPPServer server;
private String secret;
private boolean enabled;
private boolean httpBasicAuth;
private Collection<String> allowedIPs;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
server = XMPPServer.getInstance();
userManager = server.getUserManager();
rosterManager = server.getRosterManager();
secret = JiveGlobals.getProperty("plugin.userservice.secret", "");
// If no secret key has been assigned to the user service yet, assign a
// random one.
if (secret.equals("")) {
secret = StringUtils.randomString(8);
setSecret(secret);
}
// See if the service is enabled or not.
enabled = JiveGlobals.getBooleanProperty("plugin.userservice.enabled", false);
// See if the HTTP Basic Auth is enabled or not.
httpBasicAuth = JiveGlobals.getBooleanProperty("plugin.userservice.httpAuth.enabled", false);
// Get the list of IP addresses that can use this service. An empty list
// means that this filter is disabled.
allowedIPs = StringUtils.stringToCollection(JiveGlobals.getProperty("plugin.userservice.allowedIPs", ""));
// Listen to system property events
PropertyEventDispatcher.addListener(this);
}
public void destroyPlugin() {
userManager = null;
// Stop listening to system property events
PropertyEventDispatcher.removeListener(this);
}
public void createUser(String username, String password, String name, String email, String groupNames)
throws UserAlreadyExistsException, GroupAlreadyExistsException, UserNotFoundException,
GroupNotFoundException {
userManager.createUser(username, password, name, email);
userManager.getUser(username);
if (groupNames != null) {
Collection<Group> groups = new ArrayList<Group>();
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
String groupName = tkn.nextToken();
Group group = null;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group ;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group ;
group = GroupManager.getInstance().createGroup(groupName);
group.getProperties().put("sharedRoster.showInRoster", "onlyGroup");
group.getProperties().put("sharedRoster.displayName", groupName);
group.getProperties().put("sharedRoster.groupList", "");
}
groups.add(group);
}
for (Group group : groups) {
group.getMembers().add(server.createJID(username, null));
}
}
}
public void deleteUser(String username) throws UserNotFoundException, SharedGroupException
{
User user = getUser(username);
userManager.deleteUser(user);
}
groups.add(group);
}
for (Group group : groups) {
group.getMembers().add(server.createJID(username, null));
}
}
}
public void deleteUser(String username) throws UserNotFoundException, SharedGroupException {
User user = getUser(username);
userManager.deleteUser(user);
rosterManager.deleteRoster(server.createJID(username, null));
}
/**
* Lock Out on a given username
*
* @param username the username of the local user to disable.
* @throws UserNotFoundException if the requested user
* does not exist in the local server.
*/
public void disableUser(String username) throws UserNotFoundException
{
User user = getUser(username);
LockOutManager.getInstance().disableAccount(username, null, null);
}
/**
* Remove the lockout on a given username
*
* @param username the username of the local user to enable.
* @throws UserNotFoundException if the requested user
* does not exist in the local server.
*/
public void enableUser(String username) throws UserNotFoundException
{
User user = getUser(username);
LockOutManager.getInstance().enableAccount(username);
}
public void updateUser(String username, String password, String name, String email, String groupNames)
throws UserNotFoundException, GroupAlreadyExistsException
{
User user = getUser(username);
if (password != null) user.setPassword(password);
if (name != null) user.setName(name);
if (email != null) user.setEmail(email);
if (groupNames != null) {
Collection<Group> newGroups = new ArrayList<Group>();
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens())
{
}
/**
* Lock Out on a given username
*
* @param username
* the username of the local user to disable.
* @throws UserNotFoundException
* if the requested user does not exist in the local server.
*/
public void disableUser(String username) throws UserNotFoundException {
getUser(username);
LockOutManager.getInstance().disableAccount(username, null, null);
}
/**
* Remove the lockout on a given username
*
* @param username
* the username of the local user to enable.
* @throws UserNotFoundException
* if the requested user does not exist in the local server.
*/
public void enableUser(String username) throws UserNotFoundException {
getUser(username);
LockOutManager.getInstance().enableAccount(username);
}
public void updateUser(String username, String password, String name, String email, String groupNames)
throws UserNotFoundException, GroupAlreadyExistsException {
User user = getUser(username);
if (password != null)
user.setPassword(password);
if (name != null)
user.setName(name);
if (email != null)
user.setEmail(email);
if (groupNames != null) {
Collection<Group> newGroups = new ArrayList<Group>();
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
String groupName = tkn.nextToken();
Group group = null;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group ;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group ;
group = GroupManager.getInstance().createGroup(groupName);
group.getProperties().put("sharedRoster.showInRoster", "onlyGroup");
group.getProperties().put("sharedRoster.displayName", groupName);
group.getProperties().put("sharedRoster.groupList", "");
}
newGroups.add(group);
}
Collection<Group> existingGroups = GroupManager.getInstance().getGroups(user);
// Get the list of groups to add to the user
Collection<Group> groupsToAdd = new ArrayList<Group>(newGroups);
groupsToAdd.removeAll(existingGroups);
// Get the list of groups to remove from the user
Collection<Group> groupsToDelete = new ArrayList<Group>(existingGroups);
groupsToDelete.removeAll(newGroups);
// Add the user to the new groups
for (Group group : groupsToAdd) {
group.getMembers().add(server.createJID(username, null));
}
// Remove the user from the old groups
for (Group group : groupsToDelete) {
group.getMembers().remove(server.createJID(username, null));
}
}
}
/**
* Add new roster item for specified user
*
* @param username the username of the local user to add roster item to.
* @param itemJID the JID of the roster item to be added.
* @param itemName the nickname of the roster item.
* @param subscription the type of subscription of the roster item. Possible values are: -1(remove), 0(none), 1(to), 2(from), 3(both).
* @param groupNames the name of a group to place contact into.
* @throws UserNotFoundException if the user does not exist in the local server.
* @throws UserAlreadyExistsException if roster item with the same JID already exists.
* @throws SharedGroupException if roster item cannot be added to a shared group.
*/
public void addRosterItem(String username, String itemJID, String itemName, String subscription, String groupNames)
throws UserNotFoundException, UserAlreadyExistsException, SharedGroupException
{
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
try {
r.getRosterItem(j);
throw new UserAlreadyExistsException(j.toBareJID());
}
catch (UserNotFoundException e) {
//Roster item does not exist. Try to add it.
}
if (r != null) {
List<String> groups = new ArrayList<String>();
if (groupNames != null) {
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
groups.add(tkn.nextToken());
}
}
RosterItem ri = r.createRosterItem(j, itemName, groups, false, true);
if (subscription == null) {
subscription = "0";
}
ri.setSubStatus(RosterItem.SubType.getTypeFromInt(Integer.parseInt(subscription)));
r.updateRosterItem(ri);
}
}
/**
* Update roster item for specified user
*
* @param username the username of the local user to update roster item for.
* @param itemJID the JID of the roster item to be updated.
* @param itemName the nickname of the roster item.
* @param subscription the type of subscription of the roster item. Possible values are: -1(remove), 0(none), 1(to), 2(from), 3(both).
* @param groupNames the name of a group.
* @throws UserNotFoundException if the user does not exist in the local server or roster item does not exist.
* @throws SharedGroupException if roster item cannot be added to a shared group.
*/
public void updateRosterItem(String username, String itemJID, String itemName, String subscription, String groupNames)
throws UserNotFoundException, SharedGroupException
{
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
RosterItem ri = r.getRosterItem(j);
List<String> groups = new ArrayList<String>();
if (groupNames != null) {
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
groups.add(tkn.nextToken());
}
}
ri.setGroups(groups);
ri.setNickname(itemName);
if (subscription == null) {
subscription = "0";
}
ri.setSubStatus(RosterItem.SubType.getTypeFromInt(Integer.parseInt(subscription)));
r.updateRosterItem(ri);
}
/**
* Delete roster item for specified user. No error returns if nothing to delete.
*
* @param username the username of the local user to add roster item to.
* @param itemJID the JID of the roster item to be deleted.
* @throws UserNotFoundException if the user does not exist in the local server.
* @throws SharedGroupException if roster item cannot be deleted from a shared group.
*/
public void deleteRosterItem(String username, String itemJID)
throws UserNotFoundException, SharedGroupException
{
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
// No roster item is found. Uncomment the following line to throw UserNotFoundException.
//r.getRosterItem(j);
r.deleteRosterItem(j, true);
}
/**
* Returns the the requested user or <tt>null</tt> if there are any
* problems that don't throw an error.
*
* @param username the username of the local user to retrieve.
* @return the requested user.
* @throws UserNotFoundException if the requested user
* does not exist in the local server.
*/
private User getUser(String username) throws UserNotFoundException {
JID targetJID = server.createJID(username, null);
// Check that the sender is not requesting information of a remote server entity
if (targetJID.getNode() == null) {
// Sender is requesting presence information of an anonymous user
throw new UserNotFoundException("Username is null");
}
return userManager.getUser(targetJID.getNode());
}
/**
* Returns all group names or an empty collection.
*
*/
public Collection<String> getAllGroups(){
Collection<Group> groups = GroupManager.getInstance().getGroups();
Collection<String> groupNames = new ArrayList<String>();
for(Group group : groups)
{
groupNames.add(group.getName());
}
return groupNames;
}
/**
* Returns all group names or an empty collection for specific user
*
*/
public Collection<String> getUserGroups(String username) throws UserNotFoundException{
User user = getUser(username);
Collection<Group> groups = GroupManager.getInstance().getGroups(user);
Collection<String> groupNames = new ArrayList<String>();
for(Group group : groups)
{
groupNames.add(group.getName());
}
return groupNames;
}
/**
* Returns the secret key that only valid requests should know.
*
* @return the secret key.
*/
public String getSecret() {
return secret;
}
/**
* Sets the secret key that grants permission to use the userservice.
*
* @param secret the secret key.
*/
public void setSecret(String secret) {
JiveGlobals.setProperty("plugin.userservice.secret", secret);
this.secret = secret;
}
public Collection<String> getAllowedIPs() {
return allowedIPs;
}
public void setAllowedIPs(Collection<String> allowedIPs) {
JiveGlobals.setProperty("plugin.userservice.allowedIPs", StringUtils.collectionToString(allowedIPs));
this.allowedIPs = allowedIPs;
}
/**
* Returns true if the user service is enabled. If not enabled, it will not accept
* requests to create new accounts.
*
* @return true if the user service is enabled.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Enables or disables the user service. If not enabled, it will not accept
* requests to create new accounts.
*
* @param enabled true if the user service should be enabled.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
JiveGlobals.setProperty("plugin.userservice.enabled", enabled ? "true" : "false");
}
public void propertySet(String property, Map<String, Object> params) {
if (property.equals("plugin.userservice.secret")) {
this.secret = (String)params.get("value");
}
else if (property.equals("plugin.userservice.enabled")) {
this.enabled = Boolean.parseBoolean((String)params.get("value"));
}
else if (property.equals("plugin.userservice.allowedIPs")) {
this.allowedIPs = StringUtils.stringToCollection((String)params.get("value"));
}
}
public void propertyDeleted(String property, Map<String, Object> params) {
if (property.equals("plugin.userservice.secret")) {
this.secret = "";
}
else if (property.equals("plugin.userservice.enabled")) {
this.enabled = false;
}
else if (property.equals("plugin.userservice.allowedIPs")) {
this.allowedIPs = Collections.emptyList();
}
}
public void xmlPropertySet(String property, Map<String, Object> params) {
// Do nothing
}
public void xmlPropertyDeleted(String property, Map<String, Object> params) {
// Do nothing
}
group.getProperties().put("sharedRoster.showInRoster", "onlyGroup");
group.getProperties().put("sharedRoster.displayName", groupName);
group.getProperties().put("sharedRoster.groupList", "");
}
newGroups.add(group);
}
Collection<Group> existingGroups = GroupManager.getInstance().getGroups(user);
// Get the list of groups to add to the user
Collection<Group> groupsToAdd = new ArrayList<Group>(newGroups);
groupsToAdd.removeAll(existingGroups);
// Get the list of groups to remove from the user
Collection<Group> groupsToDelete = new ArrayList<Group>(existingGroups);
groupsToDelete.removeAll(newGroups);
// Add the user to the new groups
for (Group group : groupsToAdd) {
group.getMembers().add(server.createJID(username, null));
}
// Remove the user from the old groups
for (Group group : groupsToDelete) {
group.getMembers().remove(server.createJID(username, null));
}
}
}
/**
* Add new roster item for specified user
*
* @param username
* the username of the local user to add roster item to.
* @param itemJID
* the JID of the roster item to be added.
* @param itemName
* the nickname of the roster item.
* @param subscription
* the type of subscription of the roster item. Possible values
* are: -1(remove), 0(none), 1(to), 2(from), 3(both).
* @param groupNames
* the name of a group to place contact into.
* @throws UserNotFoundException
* if the user does not exist in the local server.
* @throws UserAlreadyExistsException
* if roster item with the same JID already exists.
* @throws SharedGroupException
* if roster item cannot be added to a shared group.
*/
public void addRosterItem(String username, String itemJID, String itemName, String subscription, String groupNames)
throws UserNotFoundException, UserAlreadyExistsException, SharedGroupException {
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
try {
r.getRosterItem(j);
throw new UserAlreadyExistsException(j.toBareJID());
} catch (UserNotFoundException e) {
// Roster item does not exist. Try to add it.
}
if (r != null) {
List<String> groups = new ArrayList<String>();
if (groupNames != null) {
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
groups.add(tkn.nextToken());
}
}
RosterItem ri = r.createRosterItem(j, itemName, groups, false, true);
if (subscription == null) {
subscription = "0";
}
ri.setSubStatus(RosterItem.SubType.getTypeFromInt(Integer.parseInt(subscription)));
r.updateRosterItem(ri);
}
}
/**
* Update roster item for specified user
*
* @param username
* the username of the local user to update roster item for.
* @param itemJID
* the JID of the roster item to be updated.
* @param itemName
* the nickname of the roster item.
* @param subscription
* the type of subscription of the roster item. Possible values
* are: -1(remove), 0(none), 1(to), 2(from), 3(both).
* @param groupNames
* the name of a group.
* @throws UserNotFoundException
* if the user does not exist in the local server or roster item
* does not exist.
* @throws SharedGroupException
* if roster item cannot be added to a shared group.
*/
public void updateRosterItem(String username, String itemJID, String itemName, String subscription,
String groupNames) throws UserNotFoundException, SharedGroupException {
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
RosterItem ri = r.getRosterItem(j);
List<String> groups = new ArrayList<String>();
if (groupNames != null) {
StringTokenizer tkn = new StringTokenizer(groupNames, ",");
while (tkn.hasMoreTokens()) {
groups.add(tkn.nextToken());
}
}
ri.setGroups(groups);
ri.setNickname(itemName);
if (subscription == null) {
subscription = "0";
}
ri.setSubStatus(RosterItem.SubType.getTypeFromInt(Integer.parseInt(subscription)));
r.updateRosterItem(ri);
}
/**
* Delete roster item for specified user. No error returns if nothing to
* delete.
*
* @param username
* the username of the local user to add roster item to.
* @param itemJID
* the JID of the roster item to be deleted.
* @throws UserNotFoundException
* if the user does not exist in the local server.
* @throws SharedGroupException
* if roster item cannot be deleted from a shared group.
*/
public void deleteRosterItem(String username, String itemJID) throws UserNotFoundException, SharedGroupException {
getUser(username);
Roster r = rosterManager.getRoster(username);
JID j = new JID(itemJID);
// No roster item is found. Uncomment the following line to throw
// UserNotFoundException.
// r.getRosterItem(j);
r.deleteRosterItem(j, true);
}
/**
* Returns the the requested user or <tt>null</tt> if there are any problems
* that don't throw an error.
*
* @param username
* the username of the local user to retrieve.
* @return the requested user.
* @throws UserNotFoundException
* if the requested user does not exist in the local server.
*/
private User getUser(String username) throws UserNotFoundException {
JID targetJID = server.createJID(username, null);
// Check that the sender is not requesting information of a remote
// server entity
if (targetJID.getNode() == null) {
// Sender is requesting presence information of an anonymous user
throw new UserNotFoundException("Username is null");
}
return userManager.getUser(targetJID.getNode());
}
/**
* Returns all group names or an empty collection.
*
*/
public Collection<String> getAllGroups() {
Collection<Group> groups = GroupManager.getInstance().getGroups();
Collection<String> groupNames = new ArrayList<String>();
for (Group group : groups) {
groupNames.add(group.getName());
}
return groupNames;
}
/**
* Returns all group names or an empty collection for specific user
*
*/
public Collection<String> getUserGroups(String username) throws UserNotFoundException {
User user = getUser(username);
Collection<Group> groups = GroupManager.getInstance().getGroups(user);
Collection<String> groupNames = new ArrayList<String>();
for (Group group : groups) {
groupNames.add(group.getName());
}
return groupNames;
}
/**
* Returns the secret key that only valid requests should know.
*
* @return the secret key.
*/
public String getSecret() {
return secret;
}
/**
* Sets the secret key that grants permission to use the userservice.
*
* @param secret
* the secret key.
*/
public void setSecret(String secret) {
JiveGlobals.setProperty("plugin.userservice.secret", secret);
this.secret = secret;
}
public Collection<String> getAllowedIPs() {
return allowedIPs;
}
public void setAllowedIPs(Collection<String> allowedIPs) {
JiveGlobals.setProperty("plugin.userservice.allowedIPs", StringUtils.collectionToString(allowedIPs));
this.allowedIPs = allowedIPs;
}
/**
* Returns true if the user service is enabled. If not enabled, it will not
* accept requests to create new accounts.
*
* @return true if the user service is enabled.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Enables or disables the user service. If not enabled, it will not accept
* requests to create new accounts.
*
* @param enabled
* true if the user service should be enabled.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
JiveGlobals.setProperty("plugin.userservice.enabled", enabled ? "true" : "false");
}
public boolean isHttpBasicAuth() {
return httpBasicAuth;
}
public void setHttpBasicAuth(boolean httpBasicAuth) {
this.httpBasicAuth = httpBasicAuth;
JiveGlobals.setProperty("plugin.userservice.httpAuth.enabled", enabled ? "true" : "false");
}
public void propertySet(String property, Map<String, Object> params) {
if (property.equals("plugin.userservice.secret")) {
this.secret = (String) params.get("value");
} else if (property.equals("plugin.userservice.enabled")) {
this.enabled = Boolean.parseBoolean((String) params.get("value"));
} else if (property.equals("plugin.userservice.allowedIPs")) {
this.allowedIPs = StringUtils.stringToCollection((String) params.get("value"));
}
}
public void propertyDeleted(String property, Map<String, Object> params) {
if (property.equals("plugin.userservice.secret")) {
this.secret = "";
} else if (property.equals("plugin.userservice.enabled")) {
this.enabled = false;
} else if (property.equals("plugin.userservice.allowedIPs")) {
this.allowedIPs = Collections.emptyList();
}
}
public void xmlPropertySet(String property, Map<String, Object> params) {
// Do nothing
}
public void xmlPropertyDeleted(String property, Map<String, Object> params) {
// Do nothing
}
}
package org.jivesoftware.openfire.plugin;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.entity.RosterEntities;
import org.jivesoftware.openfire.entity.RosterItemEntity;
import org.jivesoftware.openfire.entity.UserEntities;
import org.jivesoftware.openfire.entity.UserEntity;
import org.jivesoftware.openfire.entity.UserGroupsEntity;
import org.jivesoftware.openfire.entity.UserProperty;
import org.jivesoftware.openfire.exceptions.ExceptionType;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupAlreadyExistsException;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.utils.UserUtils;
import org.xmpp.packet.JID;
/**
* The Class UserServicePluginNG.
*/
public class UserServicePluginNG {
/** The Constant INSTANCE. */
public static final UserServicePluginNG INSTANCE = new UserServicePluginNG();
/** The user manager. */
private UserManager userManager;
/** The roster manager. */
private RosterManager rosterManager;
/** The server. */
private XMPPServer server;
/**
* Gets the single instance of UserServicePluginNG.
*
* @return single instance of UserServicePluginNG
*/
public static UserServicePluginNG getInstance() {
return INSTANCE;
}
/**
* Instantiates a new user service plugin ng.
*/
private UserServicePluginNG() {
server = XMPPServer.getInstance();
userManager = server.getUserManager();
rosterManager = server.getRosterManager();
}
/**
* Creates the user.
*
* @param userEntity
* the user entity
* @throws ServiceException
* the service exception
*/
public void createUser(UserEntity userEntity) throws ServiceException {
if (userEntity != null && !userEntity.getUsername().isEmpty()) {
if (userEntity.getPassword() == null) {
throw new ServiceException("Could not create new user, because password is null",
userEntity.getUsername(), "PasswordIsNull", Response.Status.BAD_REQUEST);
}
try {
userManager.createUser(userEntity.getUsername(), userEntity.getPassword(), userEntity.getName(),
userEntity.getEmail());
} catch (UserAlreadyExistsException e) {
throw new ServiceException("Could not create new user", userEntity.getUsername(),
ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.BAD_REQUEST);
}
addProperties(userEntity);
}
}
/**
* Update user.
*
* @param username
* the username
* @param userEntity
* the user entity
* @throws ServiceException
* the service exception
*/
public void updateUser(String username, UserEntity userEntity) throws ServiceException {
if (userEntity != null && !username.isEmpty()) {
User user = getAndCheckUser(username);
if (userEntity.getPassword() != null) {
user.setPassword(userEntity.getPassword());
}
if (userEntity.getName() != null) {
user.setName(userEntity.getName());
}
if (userEntity.getEmail() != null) {
user.setEmail(userEntity.getEmail());
}
addProperties(userEntity);
}
}
/**
* Delete user.
*
* @param username
* the username
* @throws ServiceException
* the service exception
*/
public void deleteUser(String username) throws ServiceException {
User user = getAndCheckUser(username);
userManager.deleteUser(user);
rosterManager.deleteRoster(server.createJID(username, null));
}
/**
* Gets the user entities.
*
* @param userSearch
* the user search
* @return the user entities
*/
public UserEntities getUserEntities(String userSearch) {
UserEntities userEntities = new UserEntities();
userEntities.setUsers(UserUtils.convertUsersToUserEntities(userManager.getUsers(), userSearch));
return userEntities;
}
/**
* Gets the user entity.
*
* @param username
* the username
* @return the user entity
* @throws ServiceException
* the service exception
*/
public UserEntity getUserEntity(String username) throws ServiceException {
return UserUtils.convertUserToUserEntity(getAndCheckUser(username));
}
/**
* Enable user.
*
* @param username
* the username
* @throws ServiceException
* the service exception
*/
public void enableUser(String username) throws ServiceException {
getAndCheckUser(username);
LockOutManager.getInstance().enableAccount(username);
}
/**
* Disable user.
*
* @param username
* the username
* @throws ServiceException
* the service exception
*/
public void disableUser(String username) throws ServiceException {
getAndCheckUser(username);
LockOutManager.getInstance().disableAccount(username, null, null);
}
/**
* Gets the roster entities.
*
* @param username
* the username
* @return the roster entities
* @throws ServiceException
* the service exception
*/
public RosterEntities getRosterEntities(String username) throws ServiceException {
Roster roster = getUserRoster(username);
List<RosterItemEntity> rosterEntities = new ArrayList<RosterItemEntity>();
for (RosterItem rosterItem : roster.getRosterItems()) {
RosterItemEntity rosterItemEntity = new RosterItemEntity(rosterItem.getJid().toBareJID(),
rosterItem.getNickname(), rosterItem.getSubStatus().getValue());
rosterItemEntity.setGroups(rosterItem.getGroups());
rosterEntities.add(rosterItemEntity);
}
return new RosterEntities(rosterEntities);
}
/**
* Adds the roster item.
*
* @param username
* the username
* @param rosterItemEntity
* the roster item entity
* @throws ServiceException
* the service exception
* @throws UserAlreadyExistsException
* the user already exists exception
* @throws SharedGroupException
* the shared group exception
* @throws UserNotFoundException
* the user not found exception
*/
public void addRosterItem(String username, RosterItemEntity rosterItemEntity) throws ServiceException,
UserAlreadyExistsException, SharedGroupException, UserNotFoundException {
Roster roster = getUserRoster(username);
if (rosterItemEntity.getJid() == null) {
throw new ServiceException("JID is null", "JID", "IllegalArgumentException", Response.Status.BAD_REQUEST);
}
JID jid = new JID(rosterItemEntity.getJid());
try {
roster.getRosterItem(jid);
throw new UserAlreadyExistsException(jid.toBareJID());
} catch (UserNotFoundException e) {
// Roster item does not exist. Try to add it.
}
if (roster != null) {
RosterItem rosterItem = roster.createRosterItem(jid, rosterItemEntity.getNickname(),
rosterItemEntity.getGroups(), false, true);
UserUtils.checkSubType(rosterItemEntity.getSubscriptionType());
rosterItem.setSubStatus(RosterItem.SubType.getTypeFromInt(rosterItemEntity.getSubscriptionType()));
roster.updateRosterItem(rosterItem);
}
}
/**
* Update roster item.
*
* @param username
* the username
* @param rosterJid
* the roster jid
* @param rosterItemEntity
* the roster item entity
* @throws ServiceException
* the service exception
* @throws UserNotFoundException
* the user not found exception
* @throws UserAlreadyExistsException
* the user already exists exception
* @throws SharedGroupException
* the shared group exception
*/
public void updateRosterItem(String username, String rosterJid, RosterItemEntity rosterItemEntity)
throws ServiceException, UserNotFoundException, UserAlreadyExistsException, SharedGroupException {
getAndCheckUser(username);
Roster roster = getUserRoster(username);
JID jid = new JID(rosterJid);
RosterItem rosterItem = roster.getRosterItem(jid);
if (rosterItemEntity.getNickname() != null) {
rosterItem.setNickname(rosterItemEntity.getNickname());
}
if (rosterItemEntity.getGroups() != null) {
rosterItem.setGroups(rosterItemEntity.getGroups());
}
UserUtils.checkSubType(rosterItemEntity.getSubscriptionType());
rosterItem.setSubStatus(RosterItem.SubType.getTypeFromInt(rosterItemEntity.getSubscriptionType()));
roster.updateRosterItem(rosterItem);
}
/**
* Delete roster item.
*
* @param username
* the username
* @param rosterJid
* the roster jid
* @throws SharedGroupException
* the shared group exception
* @throws ServiceException
* the service exception
*/
public void deleteRosterItem(String username, String rosterJid) throws SharedGroupException, ServiceException {
getAndCheckUser(username);
Roster roster = getUserRoster(username);
JID jid = new JID(rosterJid);
if (roster.deleteRosterItem(jid, true) == null) {
throw new ServiceException("Roster Item could not deleted", jid.toBareJID(), "RosterItemNotFound",
Response.Status.NOT_FOUND);
}
}
/**
* Gets the user groups.
*
* @param username
* the username
* @return the user groups
* @throws ServiceException
* the service exception
*/
public List<String> getUserGroups(String username) throws ServiceException {
User user = getAndCheckUser(username);
Collection<Group> groups = GroupManager.getInstance().getGroups(user);
List<String> groupNames = new ArrayList<String>();
for (Group group : groups) {
groupNames.add(group.getName());
}
return groupNames;
}
/**
* Adds the user to group.
*
* @param username
* the username
* @param userGroupsEntity
* the user groups entity
* @throws ServiceException
* @throws GroupAlreadyExistsException
* the group already exists exception
*/
public void addUserToGroups(String username, UserGroupsEntity userGroupsEntity) throws ServiceException {
if (userGroupsEntity != null) {
Collection<Group> groups = new ArrayList<Group>();
for (String groupName : userGroupsEntity.getGroupNames()) {
Group group = null;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group
group = createGroup(groupName);
}
groups.add(group);
}
for (Group group : groups) {
group.getMembers().add(server.createJID(username, null));
}
}
}
/**
* Delete user from groups.
*
* @param username
* the username
* @param userGroupsEntity
* the user groups entity
* @throws ServiceException
* the service exception
*/
public void deleteUserFromGroups(String username, UserGroupsEntity userGroupsEntity) throws ServiceException {
if (userGroupsEntity != null) {
for (String groupName : userGroupsEntity.getGroupNames()) {
Group group = null;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
throw new ServiceException("Could not find group", groupName, ExceptionType.GROUP_NOT_FOUND,
Response.Status.NOT_FOUND, e);
}
group.getMembers().remove(server.createJID(username, null));
}
}
}
/**
* Gets the user entities by property key and or value.
*
* @param propertyKey
* the property key
* @param propertyValue
* the property value (can be null)
* @return the user entities by property
* @throws ServiceException
* the service exception
*/
public UserEntities getUserEntitiesByProperty(String propertyKey, String propertyValue) throws ServiceException {
List<String> usernames = PropertyDAO.getUsernameByProperty(propertyKey, propertyValue);
List<UserEntity> users = new ArrayList<UserEntity>();
UserEntities userEntities = new UserEntities();
for (String username : usernames) {
users.add(getUserEntity(username));
}
userEntities.setUsers(users);
return userEntities;
}
/**
* Adds the properties.
*
* @param userEntity
* the user entity
* @throws ServiceException
* the service exception
*/
private void addProperties(UserEntity userEntity) throws ServiceException {
User user = getAndCheckUser(userEntity.getUsername());
user.getProperties().clear();
if (userEntity.getProperties() != null) {
for (UserProperty property : userEntity.getProperties()) {
user.getProperties().put(property.getKey(), property.getValue());
}
}
}
/**
* Creates the group.
*
* @param groupName
* the group name
* @return the group
* @throws ServiceException
* @throws GroupAlreadyExistsException
* the group already exists exception
*/
private Group createGroup(String groupName) throws ServiceException {
Group group = null;
try {
group = GroupManager.getInstance().createGroup(groupName);
group.getProperties().put("sharedRoster.showInRoster", "onlyGroup");
group.getProperties().put("sharedRoster.displayName", groupName);
group.getProperties().put("sharedRoster.groupList", "");
} catch (GroupAlreadyExistsException e) {
throw new ServiceException("Could not create group", groupName, ExceptionType.GROUP_ALREADY_EXISTS,
Response.Status.BAD_REQUEST, e);
}
return group;
}
/**
* Gets the and check user.
*
* @param username
* the username
* @return the and check user
* @throws ServiceException
* the service exception
*/
private User getAndCheckUser(String username) throws ServiceException {
JID targetJID = server.createJID(username, null);
if (targetJID.getNode() == null) {
throw new ServiceException("Could not get user", username, ExceptionType.USER_NOT_FOUND_EXCEPTION,
Response.Status.NOT_FOUND);
}
try {
return userManager.getUser(targetJID.getNode());
} catch (UserNotFoundException e) {
throw new ServiceException("Could not get user", username, ExceptionType.USER_NOT_FOUND_EXCEPTION,
Response.Status.NOT_FOUND, e);
}
}
/**
* Gets the user roster.
*
* @param username
* the username
* @return the user roster
* @throws ServiceException
* the service exception
*/
private Roster getUserRoster(String username) throws ServiceException {
try {
return rosterManager.getRoster(username);
} catch (UserNotFoundException e) {
throw new ServiceException("Could not get user roster", username, ExceptionType.USER_NOT_FOUND_EXCEPTION,
Response.Status.NOT_FOUND, e);
}
}
}
package org.jivesoftware.openfire.plugin.service;
import javax.annotation.PostConstruct;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.entity.UserGroupsEntity;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.UserServicePluginNG;
@Path("userService/users/{username}/groups")
public class UserGroupService {
private UserServicePluginNG plugin;
@PostConstruct
public void init() {
plugin = UserServicePluginNG.getInstance();
}
@GET
@Produces(MediaType.APPLICATION_XML)
public UserGroupsEntity getUserGroups(@PathParam("username") String username) throws ServiceException {
return new UserGroupsEntity(plugin.getUserGroups(username));
}
@POST
public Response addUserToGroups(@PathParam("username") String username, UserGroupsEntity userGroupsEntity)
throws ServiceException {
plugin.addUserToGroups(username, userGroupsEntity);
return Response.status(Response.Status.CREATED).build();
}
@DELETE
public Response deleteUserFromGroups(@PathParam("username") String username, UserGroupsEntity userGroupsEntity)
throws ServiceException {
plugin.deleteUserFromGroups(username, userGroupsEntity);
return Response.status(Response.Status.OK).build();
}
}
package org.jivesoftware.openfire.plugin.service;
import javax.annotation.PostConstruct;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.UserServicePluginNG;
@Path("userService/lockouts")
public class UserLockoutService {
private UserServicePluginNG plugin;
@PostConstruct
public void init() {
plugin = UserServicePluginNG.getInstance();
}
@POST
@Path("/{username}")
public Response disableUser(@PathParam("username") String username) throws ServiceException {
plugin.disableUser(username);
return Response.status(Response.Status.CREATED).build();
}
@DELETE
@Path("/{username}")
public Response enableUser(@PathParam("username") String username) throws ServiceException {
plugin.enableUser(username);
return Response.status(Response.Status.OK).build();
}
}
package org.jivesoftware.openfire.plugin.service;
import javax.annotation.PostConstruct;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.entity.RosterEntities;
import org.jivesoftware.openfire.entity.RosterItemEntity;
import org.jivesoftware.openfire.exceptions.ExceptionType;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.UserServicePluginNG;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
@Path("userService/users/{username}/roster")
public class UserRosterService {
private static final String COULD_NOT_UPDATE_THE_ROSTER = "Could not update the roster";
private static final String COULD_NOT_CREATE_ROSTER_ITEM = "Could not create roster item";
private UserServicePluginNG plugin;
@PostConstruct
public void init() {
plugin = UserServicePluginNG.getInstance();
}
@GET
@Produces(MediaType.APPLICATION_XML)
public RosterEntities getUserRoster(@PathParam("username") String username) throws ServiceException {
return plugin.getRosterEntities(username);
}
@POST
public Response createRoster(@PathParam("username") String username, RosterItemEntity rosterItemEntity)
throws ServiceException {
try {
plugin.addRosterItem(username, rosterItemEntity);
} catch (UserNotFoundException e) {
throw new ServiceException(COULD_NOT_CREATE_ROSTER_ITEM, "", ExceptionType.USER_NOT_FOUND_EXCEPTION,
Response.Status.NOT_FOUND, e);
} catch (UserAlreadyExistsException e) {
throw new ServiceException(COULD_NOT_CREATE_ROSTER_ITEM, "", ExceptionType.USER_ALREADY_EXISTS_EXCEPTION,
Response.Status.BAD_REQUEST, e);
} catch (SharedGroupException e) {
throw new ServiceException(COULD_NOT_CREATE_ROSTER_ITEM, "", ExceptionType.SHARED_GROUP_EXCEPTION,
Response.Status.BAD_REQUEST, e);
}
return Response.status(Response.Status.CREATED).build();
}
@DELETE
@Path("/{rosterJid}")
public Response deleteRoster(@PathParam("username") String username, @PathParam("rosterJid") String rosterJid)
throws ServiceException {
try {
plugin.deleteRosterItem(username, rosterJid);
} catch (SharedGroupException e) {
throw new ServiceException("Could not delete the roster item", rosterJid,
ExceptionType.SHARED_GROUP_EXCEPTION, Response.Status.BAD_REQUEST, e);
}
return Response.status(Response.Status.OK).build();
}
@PUT
@Path("/{rosterJid}")
public Response updateRoster(@PathParam("username") String username, @PathParam("rosterJid") String rosterJid,
RosterItemEntity rosterItemEntity) throws ServiceException {
try {
plugin.updateRosterItem(username, rosterJid, rosterItemEntity);
} catch (UserNotFoundException e) {
throw new ServiceException(COULD_NOT_UPDATE_THE_ROSTER, rosterJid, ExceptionType.USER_NOT_FOUND_EXCEPTION,
Response.Status.NOT_FOUND, e);
} catch (SharedGroupException e) {
throw new ServiceException(COULD_NOT_UPDATE_THE_ROSTER, rosterJid, ExceptionType.SHARED_GROUP_EXCEPTION,
Response.Status.BAD_REQUEST, e);
} catch (UserAlreadyExistsException e) {
throw new ServiceException(COULD_NOT_UPDATE_THE_ROSTER, rosterJid,
ExceptionType.USER_ALREADY_EXISTS_EXCEPTION, Response.Status.BAD_REQUEST, e);
}
return Response.status(Response.Status.OK).build();
}
}
package org.jivesoftware.openfire.plugin.service;
import javax.annotation.PostConstruct;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.entity.UserEntities;
import org.jivesoftware.openfire.entity.UserEntity;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.UserServicePluginNG;
@Path("userService/users")
public class UserService {
private UserServicePluginNG plugin;
@PostConstruct
public void init() {
plugin = UserServicePluginNG.getInstance();
}
@GET
@Produces(MediaType.APPLICATION_XML)
public UserEntities getUsers(@QueryParam("search") String userSearch) {
return plugin.getUserEntities(userSearch);
}
@POST
public Response createUser(UserEntity userEntity) throws ServiceException {
plugin.createUser(userEntity);
return Response.status(Response.Status.CREATED).build();
}
@GET
@Path("/{username}")
@Produces(MediaType.APPLICATION_XML)
public UserEntity getUser(@PathParam("username") String username) throws ServiceException {
return plugin.getUserEntity(username);
}
@PUT
@Path("/{username}")
public Response updateUser(@PathParam("username") String username, UserEntity userEntity) throws ServiceException {
plugin.updateUser(username, userEntity);
return Response.status(Response.Status.OK).build();
}
@DELETE
@Path("/{username}")
public Response deleteUser(@PathParam("username") String username) throws ServiceException {
plugin.deleteUser(username);
return Response.status(Response.Status.OK).build();
}
}
package org.jivesoftware.openfire.plugin.service;
import gnu.inet.encoding.Stringprep;
import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
import org.jivesoftware.admin.AuthCheckFilter;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.plugin.UserServicePlugin;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
@Path("userService")
public class UserServiceLegacy {
private static Logger Log = Logger.getLogger(UserServiceLegacy.class);
@Context
private HttpServletRequest request;
@Context
private HttpServletResponse response;
private UserServicePlugin plugin;
@PostConstruct
public void init() {
plugin = (UserServicePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("userservice");
// Exclude this servlet from requiring the user to login
AuthCheckFilter.addExclude("userService/userservice");
}
@POST
@Path("/userservice")
public void userSerivcePostRequest() throws IOException {
userSerivceRequest();
}
@GET
@Path("/userservice")
public Response userSerivceRequest() throws IOException {
// Printwriter for writing out responses to browser
PrintWriter out = response.getWriter();
if (!plugin.getAllowedIPs().isEmpty()) {
// Get client's IP address
String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = request.getHeader("X_FORWARDED_FOR");
if (ipAddress == null) {
ipAddress = request.getHeader("X-Forward-For");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
}
}
if (!plugin.getAllowedIPs().contains(ipAddress)) {
Log.warn("User service rejected service to IP address: " + ipAddress);
replyError("RequestNotAuthorised", response, out);
return Response.status(200).build();
}
}
String username = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
String email = request.getParameter("email");
String type = request.getParameter("type");
String secret = request.getParameter("secret");
String groupNames = request.getParameter("groups");
String item_jid = request.getParameter("item_jid");
String sub = request.getParameter("subscription");
// No defaults, add, delete, update only
// type = type == null ? "image" : type;
// Check that our plugin is enabled.
if (!plugin.isEnabled()) {
Log.warn("User service plugin is disabled: " + request.getQueryString());
replyError("UserServiceDisabled", response, out);
return Response.status(200).build();
}
// Check this request is authorised
if (secret == null || !secret.equals(plugin.getSecret())) {
Log.warn("An unauthorised user service request was received: " + request.getQueryString());
replyError("RequestNotAuthorised", response, out);
return Response.status(200).build();
}
// Some checking is required on the username
if (username == null && !"grouplist".equals(type)) {
replyError("IllegalArgumentException", response, out);
return Response.status(200).build();
}
if ((type.equals("add_roster") || type.equals("update_roster") || type.equals("delete_roster"))
&& (item_jid == null || !(sub == null || sub.equals("-1") || sub.equals("0") || sub.equals("1")
|| sub.equals("2") || sub.equals("3")))) {
replyError("IllegalArgumentException", response, out);
return Response.status(200).build();
}
// Check the request type and process accordingly
try {
if ("grouplist".equals(type)) {
String message = "";
for (String groupname : plugin.getAllGroups()) {
message += "<groupname>" + groupname + "</groupname>";
}
replyMessage(message, response, out);
} else {
username = username.trim().toLowerCase();
username = JID.escapeNode(username);
username = Stringprep.nodeprep(username);
if ("add".equals(type)) {
plugin.createUser(username, password, name, email, groupNames);
replyMessage("ok", response, out);
} else if ("delete".equals(type)) {
plugin.deleteUser(username);
replyMessage("ok", response, out);
} else if ("enable".equals(type)) {
plugin.enableUser(username);
replyMessage("ok", response, out);
} else if ("disable".equals(type)) {
plugin.disableUser(username);
replyMessage("ok", response, out);
} else if ("update".equals(type)) {
plugin.updateUser(username, password, name, email, groupNames);
replyMessage("ok", response, out);
} else if ("add_roster".equals(type)) {
plugin.addRosterItem(username, item_jid, name, sub, groupNames);
replyMessage("ok", response, out);
} else if ("update_roster".equals(type)) {
plugin.updateRosterItem(username, item_jid, name, sub, groupNames);
replyMessage("ok", response, out);
} else if ("delete_roster".equals(type)) {
plugin.deleteRosterItem(username, item_jid);
replyMessage("ok", response, out);
} else if ("usergrouplist".equals(type)) {
String message = "";
for (String groupname : plugin.getUserGroups(username)) {
message += "<groupname>" + groupname + "</groupname>";
}
replyMessage(message, response, out);
} else {
Log.warn("The userService servlet received an invalid request of type: " + type);
// TODO Do something
}
}
} catch (UserAlreadyExistsException e) {
replyError("UserAlreadyExistsException", response, out);
} catch (UserNotFoundException e) {
replyError("UserNotFoundException", response, out);
} catch (IllegalArgumentException e) {
replyError("IllegalArgumentException", response, out);
} catch (SharedGroupException e) {
replyError("SharedGroupException", response, out);
} catch (Exception e) {
replyError(e.toString(), response, out);
}
return Response.status(200).build();
}
private void replyMessage(String message, HttpServletResponse response, PrintWriter out) {
response.setContentType("text/xml");
out.println("<result>" + message + "</result>");
out.flush();
}
private void replyError(String error, HttpServletResponse response, PrintWriter out) {
response.setContentType("text/xml");
out.println("<error>" + error + "</error>");
out.flush();
}
}
package org.jivesoftware.openfire.plugin.service;
import javax.annotation.PostConstruct;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jivesoftware.openfire.entity.UserEntities;
import org.jivesoftware.openfire.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.UserServicePluginNG;
@Path("userService/properties")
public class UserServiceProperties {
private UserServicePluginNG plugin;
@PostConstruct
public void init() {
plugin = UserServicePluginNG.getInstance();
}
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/{key}")
public UserEntities getUsersByPropertyKey(@PathParam("key") String key) throws ServiceException {
return plugin.getUserEntitiesByProperty(key, null);
}
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/{key}/{value}")
public UserEntities getUsersByPropertyKeyValue(@PathParam("key") String key, @PathParam("value") String value)
throws ServiceException {
return plugin.getUserEntitiesByProperty(key, value);
}
}
/**
* $RCSfile$
* $Revision: 1710 $
* $Date: 2005-07-26 11:56:14 -0700 (Tue, 26 Jul 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.openfire.plugin.userService;
import gnu.inet.encoding.Stringprep;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jivesoftware.admin.AuthCheckFilter;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.plugin.UserServicePlugin;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.Log;
import org.xmpp.packet.JID;
/**
* Servlet that addition/deletion/modification of the users info in the system.
* Use the <b>type</b>
* parameter to specify the type of action. Possible values are <b>add</b>,<b>delete</b> and
* <b>update</b>. <p>
* <p/>
* The request <b>MUST</b> include the <b>secret</b> parameter. This parameter will be used
* to authenticate the request. If this parameter is missing from the request then
* an error will be logged and no action will occur.
*
* @author Justin Hunt
*/
public class UserServiceServlet extends HttpServlet {
private UserServicePlugin plugin;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
plugin = (UserServicePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("userservice");
// Exclude this servlet from requiring the user to login
AuthCheckFilter.addExclude("userService/userservice");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// Printwriter for writing out responses to browser
PrintWriter out = response.getWriter();
if (!plugin.getAllowedIPs().isEmpty()) {
// Get client's IP address
String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = request.getHeader("X_FORWARDED_FOR");
if (ipAddress == null) {
ipAddress = request.getHeader("X-Forward-For");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
}
}
if (!plugin.getAllowedIPs().contains(ipAddress)) {
Log.warn("User service rejected service to IP address: " + ipAddress);
replyError("RequestNotAuthorised",response, out);
return;
}
}
String username = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
String email = request.getParameter("email");
String type = request.getParameter("type");
String secret = request.getParameter("secret");
String groupNames = request.getParameter("groups");
String item_jid = request.getParameter("item_jid");
String sub = request.getParameter("subscription");
//No defaults, add, delete, update only
//type = type == null ? "image" : type;
// Check that our plugin is enabled.
if (!plugin.isEnabled()) {
Log.warn("User service plugin is disabled: " + request.getQueryString());
replyError("UserServiceDisabled",response, out);
return;
}
// Check this request is authorised
if (secret == null || !secret.equals(plugin.getSecret())){
Log.warn("An unauthorised user service request was received: " + request.getQueryString());
replyError("RequestNotAuthorised",response, out);
return;
}
// Some checking is required on the username
if (username == null && !"grouplist".equals(type)){
replyError("IllegalArgumentException",response, out);
return;
}
if ((type.equals("add_roster") || type.equals("update_roster") || type.equals("delete_roster")) &&
(item_jid == null || !(sub == null || sub.equals("-1") || sub.equals("0") ||
sub.equals("1") || sub.equals("2") || sub.equals("3")))) {
replyError("IllegalArgumentException",response, out);
return;
}
// Check the request type and process accordingly
try {
if ("grouplist".equals(type)){
String message = "";
for(String groupname : plugin.getAllGroups())
{
message += "<groupname>"+groupname+"</groupname>";
}
replyMessage(message, response, out);
}
else
{
username = username.trim().toLowerCase();
username = JID.escapeNode(username);
username = Stringprep.nodeprep(username);
if ("add".equals(type)) {
plugin.createUser(username, password, name, email, groupNames);
replyMessage("ok",response, out);
//imageProvider.sendInfo(request, response, presence);
}
else if ("delete".equals(type)) {
plugin.deleteUser(username);
replyMessage("ok",response,out);
//xmlProvider.sendInfo(request, response, presence);
}
else if ("enable".equals(type)) {
plugin.enableUser(username);
replyMessage("ok",response,out);
}
else if ("disable".equals(type)) {
plugin.disableUser(username);
replyMessage("ok",response,out);
}
else if ("update".equals(type)) {
plugin.updateUser(username, password,name,email, groupNames);
replyMessage("ok",response,out);
//xmlProvider.sendInfo(request, response, presence);
}
else if ("add_roster".equals(type)) {
plugin.addRosterItem(username, item_jid, name, sub, groupNames);
replyMessage("ok",response, out);
}
else if ("update_roster".equals(type)) {
plugin.updateRosterItem(username, item_jid, name, sub, groupNames);
replyMessage("ok",response, out);
}
else if ("delete_roster".equals(type)) {
plugin.deleteRosterItem(username, item_jid);
replyMessage("ok",response, out);
}
if ("usergrouplist".equals(type)){
String message = "";
for(String groupname : plugin.getUserGroups(username))
{
message += "<groupname>"+groupname+"</groupname>";
}
replyMessage(message, response, out);
}
else {
Log.warn("The userService servlet received an invalid request of type: " + type);
// TODO Do something
}
}
}
catch (UserAlreadyExistsException e) {
replyError("UserAlreadyExistsException",response, out);
}
catch (UserNotFoundException e) {
replyError("UserNotFoundException",response, out);
}
catch (IllegalArgumentException e) {
replyError("IllegalArgumentException",response, out);
}
catch (SharedGroupException e) {
replyError("SharedGroupException",response, out);
}
catch (Exception e) {
replyError(e.toString(),response, out);
}
}
private void replyMessage(String message,HttpServletResponse response, PrintWriter out){
response.setContentType("text/xml");
out.println("<result>" + message + "</result>");
out.flush();
}
private void replyError(String error,HttpServletResponse response, PrintWriter out){
response.setContentType("text/xml");
out.println("<error>" + error + "</error>");
out.flush();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
@Override
public void destroy() {
super.destroy();
// Release the excluded URL
AuthCheckFilter.removeExclude("userService/userservice");
}
}
package org.jivesoftware.openfire.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import org.jivesoftware.openfire.entity.UserEntity;
import org.jivesoftware.openfire.entity.UserProperty;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
/**
* The Class UserUtils.
*/
public class UserUtils {
/**
* Instantiates a new user utils.
*/
private UserUtils() {
throw new AssertionError();
}
/**
* Convert users to user entities.
*
* @param users
* the users
* @param userSearch
* @return the list
*/
public static List<UserEntity> convertUsersToUserEntities(Collection<User> users, String userSearch) {
List<UserEntity> result = new ArrayList<UserEntity>();
for (User user : users) {
if (userSearch != null) {
if (!user.getUsername().contains(userSearch)) {
continue;
}
}
result.add(convertUserToUserEntity(user));
}
return result;
}
/**
* Convert user to user entity.
*
* @param user
* the user
* @return the user entity
*/
public static UserEntity convertUserToUserEntity(User user) {
UserEntity userEntity = new UserEntity(user.getUsername(), user.getName(), user.getEmail());
List<UserProperty> userProperties = new ArrayList<UserProperty>();
for (Entry<String, String> property : user.getProperties().entrySet()) {
userProperties.add(new UserProperty(property.getKey(), property.getValue()));
}
userEntity.setProperties(userProperties);
return userEntity;
}
/**
* Checks if is valid sub type.
*
* @param subType
* the sub type
* @return true, if is valid sub type
* @throws UserAlreadyExistsException
*/
public static void checkSubType(int subType) throws UserAlreadyExistsException {
if (!(subType >= -1 && subType <= 3)) {
throw new UserAlreadyExistsException();
}
}
}
......@@ -3,14 +3,24 @@
<web-app>
<!-- Servlets -->
<servlet>
<servlet-name>UserServiceServlet</servlet-name>
<servlet-class>org.jivesoftware.openfire.plugin.userService.UserServiceServlet</servlet-class>
<servlet-name>JerseyWrapper</servlet-name>
<servlet-class>org.jivesoftware.openfire.plugin.JerseyWrapper</servlet-class>
</servlet>
<!-- Servlet mappings -->
<servlet-mapping>
<servlet-name>UserServiceServlet</servlet-name>
<url-pattern>/userservice</url-pattern>
<servlet-name>JerseyWrapper</servlet-name>
<url-pattern>/users/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JerseyWrapper</servlet-name>
<url-pattern>/properties/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JerseyWrapper</servlet-name>
<url-pattern>/lockouts/*</url-pattern>
</servlet-mapping>
</web-app>
<%@ page import="java.util.*,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.*,
org.jivesoftware.openfire.plugin.UserServicePlugin"
org.jivesoftware.util.*,org.jivesoftware.openfire.plugin.UserServicePlugin"
errorPage="error.jsp"
%>
......@@ -18,6 +17,7 @@
boolean success = request.getParameter("success") != null;
String secret = ParamUtils.getParameter(request, "secret");
boolean enabled = ParamUtils.getBooleanParameter(request, "enabled");
boolean httpBasicAuth = ParamUtils.getBooleanParameter(request, "authtype");
String allowedIPs = ParamUtils.getParameter(request, "allowedIPs");
UserServicePlugin plugin = (UserServicePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("userservice");
......@@ -28,6 +28,7 @@
if (errors.size() == 0) {
plugin.setEnabled(enabled);
plugin.setSecret(secret);
plugin.setHttpBasicAuth(httpBasicAuth);
plugin.setAllowedIPs(StringUtils.stringToCollection(allowedIPs));
response.sendRedirect("user-service.jsp?success=true");
return;
......@@ -36,6 +37,7 @@
secret = plugin.getSecret();
enabled = plugin.isEnabled();
httpBasicAuth = plugin.isHttpBasicAuth();
allowedIPs = StringUtils.collectionToString(plugin.getAllowedIPs());
%>
......@@ -48,7 +50,7 @@
<p>
Use the form below to enable or disable the User Service and configure the secret key.
Use the form below to enable or disable the User Service and configure the secret key or HTTP basic auth.
By default the User Service plugin is <strong>disabled</strong>, which means that
HTTP requests to the service will be ignored.
</p>
......@@ -78,7 +80,8 @@ HTTP requests to the service will be ignored.
simple integration with other applications.</p>
<p>However, the presence of this service exposes a security risk. Therefore,
a secret key is used to validate legitimate requests to this service. Moreover,
a secret key is used to validate legitimate requests to this service.
Another validation could be done over the HTTP basic authentication. Moreover,
for extra security you can specify the list of IP addresses that are allowed to
use this service. An empty list means that the service can be accessed from any
location. Addresses are delimited by commas.
......@@ -89,11 +92,17 @@ HTTP requests to the service will be ignored.
<label for="rb01"><b>Enabled</b> - User service requests will be processed.</label>
<br>
<input type="radio" name="enabled" value="false" id="rb02"
<%= ((!enabled) ? "checked" : "") %>>
<%= ((!enabled) ? "checked" : "") %>>
<label for="rb02"><b>Disabled</b> - User service requests will be ignored.</label>
<br><br>
<label for="text_secret">Secret key:</label>
<input type="radio" name="authtype" value="true" id="http_basic_auth" <%= ((httpBasicAuth) ? "checked" : "") %>>
<label for="http_basic_auth">HTTP basic auth - User service REST authentication with Openfire admin account.</label>
<br>
<input type="radio" name="authtype" value="false" id="secretKeyAuth" <%= ((!httpBasicAuth) ? "checked" : "") %>>
<label for="secretKeyAuth">Secret key auth - User service REST authentication over specified secret key.</label>
<br>
<label style="padding-left: 25px" for="text_secret">Secret key:</label>
<input type="text" name="secret" value="<%= secret %>" id="text_secret">
<br><br>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment