package org.jivesoftware.openfire.plugin.rest.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.ws.rs.core.Response;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.plugin.rest.dao.PropertyDAO;
import org.jivesoftware.openfire.plugin.rest.entity.GroupEntity;
import org.jivesoftware.openfire.plugin.rest.entity.RosterEntities;
import org.jivesoftware.openfire.plugin.rest.entity.RosterItemEntity;
import org.jivesoftware.openfire.plugin.rest.entity.UserEntities;
import org.jivesoftware.openfire.plugin.rest.entity.UserEntity;
import org.jivesoftware.openfire.plugin.rest.entity.UserGroupsEntity;
import org.jivesoftware.openfire.plugin.rest.entity.UserProperty;
import org.jivesoftware.openfire.plugin.rest.exceptions.ExceptionType;
import org.jivesoftware.openfire.plugin.rest.exceptions.ServiceException;
import org.jivesoftware.openfire.plugin.rest.utils.UserUtils;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.session.ClientSession;
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.xmpp.packet.JID;
import org.xmpp.packet.StreamError;
/**
* The Class UserServiceController.
*/
public class UserServiceController {
/** The Constant INSTANCE. */
public static final UserServiceController INSTANCE = new UserServiceController();
/** The user manager. */
private UserManager userManager;
/** The roster manager. */
private RosterManager rosterManager;
/** The server. */
private XMPPServer server;
/** The lock out manager. */
private LockOutManager lockOutManager;
/**
* Gets the single instance of UserServiceController.
*
* @return single instance of UserServiceController
*/
public static UserServiceController getInstance() {
return INSTANCE;
}
/**
* Instantiates a new user service controller.
*/
private UserServiceController() {
server = XMPPServer.getInstance();
userManager = server.getUserManager();
rosterManager = server.getRosterManager();
lockOutManager = server.getLockOutManager();
}
/**
* 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.CONFLICT);
}
addProperties(userEntity.getUsername(), userEntity.getProperties());
} else {
throw new ServiceException("Could not create new user",
"users", ExceptionType.ILLEGAL_ARGUMENT_EXCEPTION, Response.Status.BAD_REQUEST);
}
}
/**
* 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()) {
// Payload contains another username than provided over path
// parameter
if (userEntity.getUsername() != null) {
if (!userEntity.getUsername().equals(username)) {
JustMarriedController.changeName(username, userEntity.getUsername(), true, userEntity.getEmail(),
userEntity.getName());
addProperties(userEntity.getUsername(), userEntity.getProperties());
return;
}
}
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(username, userEntity.getProperties());
}
}
/**
* 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
* @param propertyValue
* @param propertyKey
* @return the user entities
* @throws ServiceException
*/
public UserEntities getUserEntities(String userSearch, String propertyKey, String propertyValue)
throws ServiceException {
if (propertyKey != null) {
return getUserEntitiesByProperty(propertyKey, propertyValue);
}
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.enableAccount(username);
}
/**
* Disable user.
*
* @param username
* the username
* @throws ServiceException
* the service exception
*/
public void disableUser(String username) throws ServiceException {
getAndCheckUser(username);
lockOutManager.disableAccount(username, null, null);
if (lockOutManager.isAccountDisabled(username)) {
final StreamError error = new StreamError(StreamError.Condition.not_authorized);
for (ClientSession sess : SessionManager.getInstance().getSessions(username)) {
sess.deliverRawText(error.toXML());
sess.close();
}
}
}
/**
* 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
* the service 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 = GroupController.getInstance().createGroup(new GroupEntity(groupName, ""));
}
groups.add(group);
}
for (Group group : groups) {
group.getMembers().add(server.createJID(username, null));
}
}
}
/**
* Adds the user to group.
*
* @param username the username
* @param groupName the group name
* @throws ServiceException the service exception
*/
public void addUserToGroup(String username, String groupName) throws ServiceException {
Group group = null;
try {
group = GroupManager.getInstance().getGroup(groupName);
} catch (GroupNotFoundException e) {
// Create this group
group = GroupController.getInstance().createGroup(new GroupEntity(groupName, ""));
}
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));
}
}
}
/**
* Delete user from group.
*
* @param username the username
* @param groupName the group name
* @throws ServiceException the service exception
*/
public void deleteUserFromGroup(String username, String groupName) throws ServiceException {
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(String username, List<UserProperty> properties) throws ServiceException {
User user = getAndCheckUser(username);
user.getProperties().clear();
if (properties != null) {
for (UserProperty property : properties) {
user.getProperties().put(property.getKey(), property.getValue());
}
}
}
/**
* 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);
}
}
}