Commit b3406dfd authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Created ExternalComponentManagerListener that could reject an attempt to...

Created ExternalComponentManagerListener that could reject an attempt to modify an ExternalComponentManager setting. JM-1267

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9886 b35dd754-fafc-0310-a699-88a17e54d16e
parent daf25719
......@@ -2199,4 +2199,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -2185,4 +2185,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -1294,6 +1294,7 @@ component.settings.defaultSecret=Default shared secret:
component.settings.valid.defaultSecret=Please specify a default secret key.
component.settings.valid.subdomain=Please specify the subdomain of the component.
component.settings.valid.secret=Please specify the secret key of the component.
component.settings.modification.denied=Requested operation is not allowed.
component.settings.allowed=Allowed to Connect
component.settings.anyone=Anyone
component.settings.anyone_info=Any component is allowed to connect to this server. Use the table \
......
......@@ -2241,4 +2241,5 @@ sidebar.system-clustering.descr=Haga clic para administrar seteos de cluster
user.roster.filter=Mostrar
user.roster.filter.all=Todos los contactos
user.roster.filter.noshared=Grupos no Compartidos
user.roster.filter.onlyshared=Solo Grupos Compartidos
\ No newline at end of file
user.roster.filter.onlyshared=Solo Grupos Compartidos
component.settings.modification.denied=Operaci\u00f3n requerida no esta permitida.
\ No newline at end of file
......@@ -1807,4 +1807,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -2332,4 +2332,5 @@ httpbind.settings.script.label_disable=Disable
httpbind.settings.script.label_disable_info=Does not allow clients with limited access to connect to the server
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -2196,4 +2196,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -2165,4 +2165,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -2199,4 +2199,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -1976,4 +1976,5 @@ system.clustering.starting=Clustering is being started. It may take up to 30 sec
sidebar.system-clustering=Clustering
sidebar.system-clustering.descr=Click to manage clustering settings
sidebar.stun=STUN Settings
sidebar.user-roster=Roster
\ No newline at end of file
sidebar.user-roster=Roster
component.settings.modification.denied=Requested operation is not allowed.
\ No newline at end of file
......@@ -16,8 +16,10 @@ public class ExternalComponentConfiguration {
private String secret;
public ExternalComponentConfiguration(String subdomain) {
public ExternalComponentConfiguration(String subdomain, Permission permission, String secret) {
this.subdomain = subdomain;
this.permission = permission;
this.secret = secret;
}
public String getSubdomain() {
......@@ -28,7 +30,7 @@ public class ExternalComponentConfiguration {
return permission;
}
public void setPermission(Permission permission) {
void setPermission(Permission permission) {
this.permission = permission;
}
......@@ -36,7 +38,7 @@ public class ExternalComponentConfiguration {
return secret;
}
public void setSecret(String secret) {
void setSecret(String secret) {
this.secret = secret;
}
......
......@@ -13,6 +13,7 @@ package org.jivesoftware.openfire.component;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.ConnectionManager;
import org.jivesoftware.openfire.component.ExternalComponentConfiguration.Permission;
import org.jivesoftware.openfire.session.ComponentSession;
import org.jivesoftware.openfire.session.Session;
......@@ -24,6 +25,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages the connection permissions for external components. When an external component is
......@@ -44,14 +47,53 @@ public class ExternalComponentManager {
private static final String LOAD_CONFIGURATIONS =
"SELECT subdomain,secret FROM jiveExtComponentConf where permission=?";
/**
* List of listeners that will be notified when vCards are created, updated or deleted.
*/
private static List<ExternalComponentManagerListener> listeners =
new CopyOnWriteArrayList<ExternalComponentManagerListener>();
public static void setServiceEnabled(boolean enabled) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.serviceEnabled(enabled);
}
ConnectionManager connectionManager = XMPPServer.getInstance().getConnectionManager();
connectionManager.enableComponentListener(enabled);
}
public static boolean isServiceEnabled() {
ConnectionManager connectionManager = XMPPServer.getInstance().getConnectionManager();
return connectionManager.isComponentListenerEnabled();
}
public static void setServicePort(int port) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.portChanged(port);
}
ConnectionManager connectionManager = XMPPServer.getInstance().getConnectionManager();
connectionManager.setComponentListenerPort(port);
}
public static int getServicePort() {
ConnectionManager connectionManager = XMPPServer.getInstance().getConnectionManager();
return connectionManager.getComponentListenerPort();
}
/**
* Allows an external component to connect to the local server with the specified configuration.
*
* @param configuration the configuration for the external component.
* @throws Exception if the operation was denied.
*/
public static void allowAccess(ExternalComponentConfiguration configuration) {
public static void allowAccess(ExternalComponentConfiguration configuration) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.componentAllowed(configuration.getSubdomain());
}
// Remove any previous configuration for this external component
deleteConfiguration(configuration.getSubdomain());
deleteConfigurationFromDB(configuration.getSubdomain());
// Update the database with the new granted permission and configuration
configuration.setPermission(Permission.allowed);
addConfiguration(configuration);
......@@ -62,13 +104,17 @@ public class ExternalComponentManager {
* connected when the permission was revoked then the connection of the entity will be closed.
*
* @param subdomain the subdomain of the external component that is not allowed to connect.
* @throws Exception if the operation was denied.
*/
public static void blockAccess(String subdomain) {
public static void blockAccess(String subdomain) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.componentBlocked(subdomain);
}
// Remove any previous configuration for this external component
deleteConfiguration(subdomain);
deleteConfigurationFromDB(subdomain);
// Update the database with the new revoked permission
ExternalComponentConfiguration config = new ExternalComponentConfiguration(subdomain);
config.setPermission(Permission.blocked);
ExternalComponentConfiguration config = new ExternalComponentConfiguration(subdomain, Permission.blocked, null);
addConfiguration(config);
// Check if the component was connected and proceed to close the connection
String domain = subdomain + "." + XMPPServer.getInstance().getServerInfo().getXMPPDomain();
......@@ -97,21 +143,11 @@ public class ExternalComponentManager {
if (PermissionPolicy.blacklist == getPermissionPolicy()) {
// Anyone can access except those entities listed in the blacklist
if (Permission.blocked == permission) {
return false;
}
else {
return true;
}
return Permission.blocked != permission;
}
else {
// Access is limited to those present in the whitelist
if (Permission.allowed == permission) {
return true;
}
else {
return false;
}
return Permission.allowed == permission;
}
}
......@@ -137,13 +173,47 @@ public class ExternalComponentManager {
return getConfigurations(Permission.blocked);
}
public static void updateComponentSecret(String subdomain, String secret) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.componentSecretUpdated(subdomain, secret);
}
ExternalComponentConfiguration configuration = getConfiguration(subdomain);
if (configuration != null) {
configuration.setPermission(Permission.allowed);
configuration.setSecret(secret);
// Remove any previous configuration for this external component
deleteConfigurationFromDB(subdomain);
}
else {
configuration = new ExternalComponentConfiguration(subdomain, Permission.allowed, secret);
}
addConfiguration(configuration);
}
/**
* Removes any existing defined permission and configuration for the specified
* external component.
*
* @param subdomain the subdomain of the external component.
* @throws Exception if the operation was denied.
*/
public static void deleteConfiguration(String subdomain) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.componentConfigurationDeleted(subdomain);
}
// Proceed to delete the configuration of the component
deleteConfigurationFromDB(subdomain);
}
/**
* Removes any existing defined permission and configuration for the specified
* external component from the database.
*
* @param subdomain the subdomain of the external component.
*/
public static void deleteConfiguration(String subdomain) {
private static void deleteConfigurationFromDB(String subdomain) {
// Remove the permission for the entity from the database
java.sql.Connection con = null;
PreparedStatement pstmt = null;
......@@ -166,6 +236,8 @@ public class ExternalComponentManager {
/**
* Adds a new permission for the specified external component.
*
* @param configuration the new configuration for a component.
*/
private static void addConfiguration(ExternalComponentConfiguration configuration) {
// Remove the permission for the entity from the database
......@@ -207,9 +279,8 @@ public class ExternalComponentManager {
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
configuration = new ExternalComponentConfiguration(subdomain);
configuration.setSecret(rs.getString(1));
configuration.setPermission(Permission.valueOf(rs.getString(2)));
configuration = new ExternalComponentConfiguration(subdomain, Permission.valueOf(rs.getString(2)),
rs.getString(1));
}
rs.close();
}
......@@ -238,9 +309,7 @@ public class ExternalComponentManager {
ResultSet rs = pstmt.executeQuery();
ExternalComponentConfiguration configuration;
while (rs.next()) {
configuration = new ExternalComponentConfiguration(rs.getString(1));
configuration.setSecret(rs.getString(2));
configuration.setPermission(permission);
configuration = new ExternalComponentConfiguration(rs.getString(1), permission, rs.getString(2));
answer.add(configuration);
}
rs.close();
......@@ -274,8 +343,13 @@ public class ExternalComponentManager {
*
* @param defaultSecret the default secret key to use for those external components that
* don't have an individual configuration.
* @throws Exception if the operation was denied.
*/
public static void setDefaultSecret(String defaultSecret) {
public static void setDefaultSecret(String defaultSecret) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.defaultSecretChanged(defaultSecret);
}
JiveGlobals.setProperty("xmpp.component.defaultSecret", defaultSecret);
}
......@@ -333,8 +407,13 @@ public class ExternalComponentManager {
* the server.
*
* @param policy the new PermissionPolicy to use.
* @throws Exception if the operation was denied.
*/
public static void setPermissionPolicy(PermissionPolicy policy) {
public static void setPermissionPolicy(PermissionPolicy policy) throws Exception {
// Alert listeners about this event
for (ExternalComponentManagerListener listener : listeners) {
listener.permissionPolicyChanged(policy);
}
JiveGlobals.setProperty("xmpp.component.permission", policy.toString());
// Check if connected components can remain connected to the server
for (ComponentSession session : SessionManager.getInstance().getComponentSessions()) {
......@@ -355,11 +434,34 @@ public class ExternalComponentManager {
* the server.
*
* @param policy the new policy to use.
* @throws Exception if the operation was denied.
*/
public static void setPermissionPolicy(String policy) {
public static void setPermissionPolicy(String policy) throws Exception {
setPermissionPolicy(PermissionPolicy.valueOf(policy));
}
/**
* Registers a listener to receive events when a configuration change happens. Listeners
* have the chance to deny the operation from happening.
*
* @param listener the listener.
*/
public static void addListener(ExternalComponentManagerListener listener) {
if (listener == null) {
throw new NullPointerException();
}
listeners.add(listener);
}
/**
* Unregisters a listener to receive events.
*
* @param listener the listener.
*/
public static void removeListener(ExternalComponentManagerListener listener) {
listeners.remove(listener);
}
public enum PermissionPolicy {
/**
* Any XMPP entity is allowed to connect to the server except for those listed in
......
/**
* $Revision: $
* $Date: $
*
* Copyright (C) 2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.component;
import org.jivesoftware.util.ModificationNotAllowedException;
/**
* Listener that will be alerted when an external component is disabled/enabled,
* the port is changed or configuration about an external component is modified.<p>
*
* All listeners of the event will be alerted. Moreover, listeners have the chance
* to deny a change from happening. If a single listener denied the operation then
* it will not be allowed.
*
* @author Gaston Dombiak
*/
public interface ExternalComponentManagerListener {
/**
* Notification indicating whether the service is being enabled or disabled. The
* listener may throw an exception to not allow the change from taking place.
*
* @param enabled true if the service is being enabled.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void serviceEnabled(boolean enabled) throws ModificationNotAllowedException;
/**
* Notification indicating that the port used by external components is being
* modified. The listener may throw an exception to not allow the change from
* taking place.
*
* @param newPort new default secret being set.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void portChanged(int newPort) throws ModificationNotAllowedException;
/**
* Notification indicating that the default secret is being modified. The
* listener may throw an exception to not allow the change from taking place.
*
* @param newSecret new default secret being set.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void defaultSecretChanged(String newSecret) throws ModificationNotAllowedException;
/**
* Notification indicating that the permission policy is being modified. See
* {@link ExternalComponentManager.PermissionPolicy} for more information. The
* listener may throw an exception to not allow the change from taking place.
*
* @param newPolicy new permission policy being set.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void permissionPolicyChanged(ExternalComponentManager.PermissionPolicy newPolicy) throws ModificationNotAllowedException;
/**
* Notification indicating that a new component was allowed to connect using a
* given configuration. The listener may throw an exception to not allow the
* change from taking place.
*
* @param subdomain subdomain of the added component.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void componentAllowed(String subdomain) throws ModificationNotAllowedException;
/**
* Notification indicating that a component was blocked to connect to the server.
* The listener may throw an exception to not allow the change from taking place.
*
* @param subdomain subdomain of the blocked component.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void componentBlocked(String subdomain) throws ModificationNotAllowedException;
/**
* Notification indicating that the configuration of a component, that was either
* blocked or allowed to connect, is being deleted. The listener may throw an exception
* to not allow the change from taking place.
*
* @param subdomain subdomain of the component.
* @param newSecret new secret being set for the component.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void componentSecretUpdated(String subdomain, String newSecret) throws ModificationNotAllowedException;
/**
* Notification indicating that the configuration of a component, that was either
* blocked or allowed to connect, is being deleted. The listener may throw an
* exception to not allow the change from taking place.
*
* @param subdomain subdomain of the component.
* @throws ModificationNotAllowedException if the operation was denied.
*/
void componentConfigurationDeleted(String subdomain) throws ModificationNotAllowedException;
}
/**
* $Revision:$
* $Date:$
*
* Copyright (C) 2008 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.util;
/**
* Exception thrown when a modification was not allowed.
*/
public class ModificationNotAllowedException extends Exception {
public ModificationNotAllowedException() {
super();
}
public ModificationNotAllowedException(String message) {
super(message);
}
public ModificationNotAllowedException(String message, Throwable cause) {
super(message, cause);
}
public ModificationNotAllowedException(Throwable cause) {
super(cause);
}
}
......@@ -44,10 +44,9 @@
boolean allowSuccess = false;
boolean blockSuccess = false;
boolean deleteSuccess = false;
boolean operationFailed = false;
String serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
ConnectionManager connectionManager = XMPPServer.getInstance().getConnectionManager();
// Update the session kick policy if requested
Map<String, String> errors = new HashMap<String, String>();
......@@ -63,26 +62,41 @@
}
// If no errors, continue:
if (errors.isEmpty()) {
if (!componentEnabled) {
connectionManager.enableComponentListener(false);
try {
if (!componentEnabled) {
ExternalComponentManager.setServiceEnabled(false);
}
else {
ExternalComponentManager.setServiceEnabled(true);
ExternalComponentManager.setServicePort(port);
ExternalComponentManager.setDefaultSecret(defaultSecret);
}
updateSucess = true;
}
else {
connectionManager.enableComponentListener(true);
connectionManager.setComponentListenerPort(port);
ExternalComponentManager.setDefaultSecret(defaultSecret);
catch (ModificationNotAllowedException e) {
operationFailed = true;
}
updateSucess = true;
}
}
if (permissionUpdate) {
ExternalComponentManager.setPermissionPolicy(permissionFilter);
updateSucess = true;
try {
ExternalComponentManager.setPermissionPolicy(permissionFilter);
updateSucess = true;
}
catch (ModificationNotAllowedException e) {
operationFailed = true;
}
}
if (configToDelete != null && configToDelete.trim().length() != 0) {
ExternalComponentManager.deleteConfiguration(configToDelete);
deleteSuccess = true;
try {
ExternalComponentManager.deleteConfiguration(configToDelete);
deleteSuccess = true;
}
catch (ModificationNotAllowedException e) {
operationFailed = true;
}
}
if (componentAllowed) {
......@@ -97,11 +111,15 @@
if (errors.isEmpty()) {
// Remove the hostname if the user is not sending just the subdomain
subdomain = subdomain.replace("." + serverName, "");
ExternalComponentConfiguration configuration = new ExternalComponentConfiguration(subdomain);
configuration.setSecret(secret);
configuration.setPermission(ExternalComponentConfiguration.Permission.allowed);
ExternalComponentManager.allowAccess(configuration);
allowSuccess = true;
ExternalComponentConfiguration configuration = new ExternalComponentConfiguration(subdomain,
ExternalComponentConfiguration.Permission.allowed, secret);
try {
ExternalComponentManager.allowAccess(configuration);
allowSuccess = true;
}
catch (ModificationNotAllowedException e) {
operationFailed = true;
}
}
}
......@@ -114,15 +132,20 @@
if (errors.isEmpty()) {
// Remove the hostname if the user is not sending just the subdomain
subdomain = subdomain.replace("." + serverName, "");
ExternalComponentManager.blockAccess(subdomain);
blockSuccess = true;
try {
ExternalComponentManager.blockAccess(subdomain);
blockSuccess = true;
}
catch (ModificationNotAllowedException e) {
operationFailed = true;
}
}
}
// Set page vars
if (errors.size() == 0) {
componentEnabled = connectionManager.isComponentListenerEnabled();
port = connectionManager.getComponentListenerPort();
componentEnabled = ExternalComponentManager.isServiceEnabled();
port = ExternalComponentManager.getServicePort();
defaultSecret = ExternalComponentManager.getDefaultSecret();
permissionFilter = ExternalComponentManager.getPermissionPolicy().toString();
subdomain = "";
......@@ -130,7 +153,7 @@
}
else {
if (port == 0) {
port = connectionManager.getComponentListenerPort();
port = ExternalComponentManager.getServicePort();
}
if (defaultSecret == null) {
defaultSecret = ExternalComponentManager.getDefaultSecret();
......@@ -179,6 +202,22 @@
</div>
<br>
<% } else if (operationFailed) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16" border="0"/></td>
<td class="jive-icon-label">
<fmt:message key="component.settings.modification.denied" />
</td>
</tr>
</tbody>
</table>
</div>
<br>
<% } else if (updateSucess || allowSuccess || blockSuccess || deleteSuccess) { %>
<div class="jive-success">
......
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