mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merge of BRANCHES/DEV/4.2_ENT_DEV/ADMIN_CONSOLE - Admin Console 46247-46672
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@46677 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -456,6 +456,7 @@
|
|||||||
<value>alfresco.messages.subscription-service</value>
|
<value>alfresco.messages.subscription-service</value>
|
||||||
<value>alfresco.messages.replication</value>
|
<value>alfresco.messages.replication</value>
|
||||||
<value>alfresco.messages.categories</value>
|
<value>alfresco.messages.categories</value>
|
||||||
|
<value>alfresco.messages.authentication</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
34
config/alfresco/messages/authentication.properties
Normal file
34
config/alfresco/messages/authentication.properties
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# authentication error messages
|
||||||
|
authentication.err.validation.authenticator.notfound=Failed to authenticate, authenticator with name, {0}, not found
|
||||||
|
authentication.err.validation.authenticator.notactive=The authenticator is not active
|
||||||
|
|
||||||
|
authentication.err.authentication=Failed to authenticate, username or password is wrong. User name:{0} Reason {1}
|
||||||
|
authentication.err.connection=Failed to connect to {0}. Reason {1}
|
||||||
|
authentication.err.communication=Failed to communicate with {0}. Reason {1}
|
||||||
|
|
||||||
|
# LDAP error messages
|
||||||
|
authentication.err.connection.ldap.authenticator.unknownhost=Failed to connect, the ldap host {0} is unknown
|
||||||
|
authentication.err.connection.ldap.user.notfound=LDAP User {0} not found
|
||||||
|
authentication.err.connection.ldap.manager.notfound=LDAP Manager User {0} not found
|
||||||
|
authentication.err.connection.ldap.search=Unable to search LDAP. Reason {0}
|
||||||
|
|
||||||
|
# PASSTHRU
|
||||||
|
authentication.err.connection.passthru.server=Failed to open session to passthru server
|
||||||
|
authentication.err.passthru.token.unsupported=Unsupported authentication token type
|
||||||
|
authentication.err.passthru.guest.notenabled=Guest logons disabled
|
||||||
|
authentication.err.passthru.user.disabled=Account disabled
|
||||||
|
authentication.err.passthru.user.notfound=Passthru user {0} not found
|
||||||
|
|
||||||
|
# Authentication Diagnostic Steps
|
||||||
|
authentication.step.ldap.validation=Validation of request
|
||||||
|
authentication.step.ldap.connecting=Connecting to LDAP Server {0}
|
||||||
|
authentication.step.ldap.connected=Connected to LDAP server {0} with principal: {1}
|
||||||
|
authentication.step.ldap.lookup=Lookup Test User userId:{0} with query: {1}
|
||||||
|
authentication.step.ldap.lookedup=Looked up Test User userId:{0}, found distinguished name (DN):{1}
|
||||||
|
authentication.step.ldap.format.user=User Name Format specified, userNameFormat:{2} Format user userId:{0} to make Distinguished name (DN):{1}
|
||||||
|
authentication.step.ldap.authentication=Authenticate userId:{0}
|
||||||
|
|
||||||
|
# Error messages
|
||||||
|
authentication.ldap.validation.authenticator.notfound=Authenticator not found
|
||||||
|
|
||||||
|
|
@@ -23,3 +23,5 @@ email.server.err.parse_message=Failed to parse the email message: {0}
|
|||||||
email.server.err.usupported_encoding=Encoding ''{0}'' is not supported
|
email.server.err.usupported_encoding=Encoding ''{0}'' is not supported
|
||||||
email.server.err.failed_to_read_content_stream=Failed to read the message part content: {0}
|
email.server.err.failed_to_read_content_stream=Failed to read the message part content: {0}
|
||||||
email.server.err.incorrect_message_part=Incorrect message part: {0}
|
email.server.err.incorrect_message_part=Incorrect message part: {0}
|
||||||
|
|
||||||
|
email.outbound.err.send.failed=Failed to send email to: {0} cause {1}
|
||||||
|
@@ -14,6 +14,13 @@
|
|||||||
store if it supports other authentication routes, like Active Directory.
|
store if it supports other authentication routes, like Active Directory.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<bean id="monitor" class="org.alfresco.repo.security.authentication.ldap.Monitor" >
|
||||||
|
<property name="LDAPAuthenticationComponent">
|
||||||
|
<ref bean="authenticationComponent" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
<bean id="authenticationComponent" class="org.alfresco.repo.security.authentication.ldap.LDAPAuthenticationComponentImpl"
|
<bean id="authenticationComponent" class="org.alfresco.repo.security.authentication.ldap.LDAPAuthenticationComponentImpl"
|
||||||
parent="authenticationComponentBase">
|
parent="authenticationComponentBase">
|
||||||
<property name="active">
|
<property name="active">
|
||||||
|
@@ -89,4 +89,10 @@
|
|||||||
<value>${mail.testmessage.text}</value>
|
<value>${mail.testmessage.text}</value>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="monitor" class="org.alfresco.repo.action.executer.MailActionExecuterMonitor" >
|
||||||
|
<property name="mailActionExecuter">
|
||||||
|
<ref bean="mail"></ref>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
</beans>
|
</beans>
|
@@ -174,4 +174,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="urlDecodeMethodExtension" parent="baseTemplateImplementation" class="org.alfresco.repo.template.URLDecodeMethod">
|
||||||
|
<property name="extensionName">
|
||||||
|
<value>urldecode</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -25,6 +25,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
@@ -96,7 +97,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
/**
|
/**
|
||||||
* The java mail sender
|
* The java mail sender
|
||||||
*/
|
*/
|
||||||
private JavaMailSender javaMailSender;
|
private JavaMailSender mailService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Template service
|
* The Template service
|
||||||
@@ -169,7 +170,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
*/
|
*/
|
||||||
public void setMailService(JavaMailSender javaMailSender)
|
public void setMailService(JavaMailSender javaMailSender)
|
||||||
{
|
{
|
||||||
this.javaMailSender = javaMailSender;
|
this.mailService = javaMailSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,10 +263,56 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
this.sendTestMessage = sendTestMessage;
|
this.sendTestMessage = sendTestMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a test message
|
||||||
|
*
|
||||||
|
* @return true, message sent
|
||||||
|
* @throws AlfrescoRuntimeException
|
||||||
|
*/
|
||||||
|
public boolean sendTestMessage()
|
||||||
|
{
|
||||||
|
Map<String, Serializable> params = new HashMap<String, Serializable>();
|
||||||
|
params.put(PARAM_TO, testMessageTo);
|
||||||
|
params.put(PARAM_SUBJECT, testMessageSubject);
|
||||||
|
params.put(PARAM_TEXT, testMessageText);
|
||||||
|
|
||||||
|
Action ruleAction = serviceRegistry.getActionService().createAction(NAME, params);
|
||||||
|
|
||||||
|
MimeMessageHelper message = prepareEmail(ruleAction, null);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mailService.send(message.getMimeMessage());
|
||||||
|
onSend();
|
||||||
|
}
|
||||||
|
catch (MailException me)
|
||||||
|
{
|
||||||
|
onFail();
|
||||||
|
StringBuffer txt = new StringBuffer();
|
||||||
|
|
||||||
|
txt.append(me.getClass().getName() + ", " + me.getMessage());
|
||||||
|
|
||||||
|
Throwable cause = me.getCause();
|
||||||
|
while (cause != null)
|
||||||
|
{
|
||||||
|
txt.append(", ");
|
||||||
|
txt.append(cause.getClass().getName() + ", " + cause.getMessage());
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] args = {testMessageTo, txt.toString()};
|
||||||
|
throw new AlfrescoRuntimeException("email.outbound.err.send.failed", args, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
|
numberSuccessfulSends.set(0);
|
||||||
|
numberFailedSends.set(0);
|
||||||
|
|
||||||
super.init();
|
super.init();
|
||||||
if (sendTestMessage)
|
if (sendTestMessage)
|
||||||
{
|
{
|
||||||
@@ -323,7 +370,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
if (finalMessage != null)
|
if (finalMessage != null)
|
||||||
{
|
{
|
||||||
sendEmail(ruleAction, actionedUponNodeRef, finalMessage);
|
sendEmail(ruleAction, finalMessage);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -335,7 +382,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
if (validNodeRefIfPresent(actionedUponNodeRef))
|
if (validNodeRefIfPresent(actionedUponNodeRef))
|
||||||
{
|
{
|
||||||
sendEmail(ruleAction, actionedUponNodeRef, finalMessage);
|
sendEmail(ruleAction, finalMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,7 +651,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
MimeMessage mimeMessage = mailService.createMimeMessage();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mailPreparer.prepare(mimeMessage);
|
mailPreparer.prepare(mimeMessage);
|
||||||
@@ -620,7 +667,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
return messageRef[0];
|
return messageRef[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendEmail(final Action ruleAction, final NodeRef actionedUponNodeRef, MimeMessageHelper preparedMessage)
|
private void sendEmail(final Action ruleAction, MimeMessageHelper preparedMessage)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -629,7 +676,8 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
if (!testMode)
|
if (!testMode)
|
||||||
{
|
{
|
||||||
javaMailSender.send(preparedMessage.getMimeMessage());
|
mailService.send(preparedMessage.getMimeMessage());
|
||||||
|
onSend();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -639,6 +687,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
}
|
}
|
||||||
catch (MailException e)
|
catch (MailException e)
|
||||||
{
|
{
|
||||||
|
onFail();
|
||||||
String to = (String)ruleAction.getParameterValue(PARAM_TO);
|
String to = (String)ruleAction.getParameterValue(PARAM_TO);
|
||||||
if (to == null)
|
if (to == null)
|
||||||
{
|
{
|
||||||
@@ -656,7 +705,8 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
Boolean ignoreError = (Boolean)ruleAction.getParameterValue(PARAM_IGNORE_SEND_FAILURE);
|
Boolean ignoreError = (Boolean)ruleAction.getParameterValue(PARAM_IGNORE_SEND_FAILURE);
|
||||||
if (ignoreError == null || ignoreError.booleanValue() == false)
|
if (ignoreError == null || ignoreError.booleanValue() == false)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to send email to:" + to, e);
|
Object[] args = {to, e.toString()};
|
||||||
|
throw new AlfrescoRuntimeException("email.outbound.err.send.failed", args, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -815,4 +865,26 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
|
|||||||
+ sysAdminParams.getAlfrescoPort();
|
+ sysAdminParams.getAlfrescoPort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AtomicInteger numberSuccessfulSends = new AtomicInteger(0);
|
||||||
|
static AtomicInteger numberFailedSends = new AtomicInteger(0);
|
||||||
|
protected void onSend()
|
||||||
|
{
|
||||||
|
numberSuccessfulSends.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onFail()
|
||||||
|
{
|
||||||
|
numberFailedSends.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberSuccessfulSends()
|
||||||
|
{
|
||||||
|
return numberSuccessfulSends.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberFailedSends()
|
||||||
|
{
|
||||||
|
return numberFailedSends.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,36 @@
|
|||||||
|
package org.alfresco.repo.action.executer;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
|
public class MailActionExecuterMonitor
|
||||||
|
{
|
||||||
|
private MailActionExecuter mailActionExceuter;
|
||||||
|
|
||||||
|
public String sendTestMessage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mailActionExceuter.sendTestMessage();
|
||||||
|
return "email message sent";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
(AlfrescoRuntimeException are)
|
||||||
|
{
|
||||||
|
return (are.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int getNumberFailedSends()
|
||||||
|
{
|
||||||
|
return mailActionExceuter.getNumberFailedSends();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberSuccessfulSends()
|
||||||
|
{
|
||||||
|
return mailActionExceuter.getNumberSuccessfulSends();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMailActionExecuter(MailActionExecuter mailActionExceuter)
|
||||||
|
{
|
||||||
|
this.mailActionExceuter = mailActionExceuter;
|
||||||
|
}
|
||||||
|
}
|
@@ -384,6 +384,26 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the application context. Will not start a subsystem.
|
||||||
|
*
|
||||||
|
* @return the application context or null
|
||||||
|
*/
|
||||||
|
public ApplicationContext getReadOnlyApplicationContext()
|
||||||
|
{
|
||||||
|
this.lock.readLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ((ApplicationContextState) getState(false)).getApplicationContext();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.management.ManagedApplicationContextFactory#getApplicationContext()
|
* @see org.alfresco.repo.management.ManagedApplicationContextFactory#getApplicationContext()
|
||||||
@@ -770,6 +790,16 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the application context. Will not start a subsystem.
|
||||||
|
*
|
||||||
|
* @return the application context or null
|
||||||
|
*/
|
||||||
|
public ApplicationContext getReadOnlyApplicationContext()
|
||||||
|
{
|
||||||
|
return this.applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the application context.
|
* Gets the application context.
|
||||||
*
|
*
|
||||||
|
@@ -43,7 +43,7 @@ public interface ChildApplicationContextManager
|
|||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* the identifier of the application context to retrieve
|
* the identifier of the application context to retrieve
|
||||||
* @return the application context with the given identifier
|
* @return the application context with the given identifier or null if it does not exist
|
||||||
*/
|
*/
|
||||||
public ApplicationContext getApplicationContext(String id);
|
public ApplicationContext getApplicationContext(String id);
|
||||||
}
|
}
|
||||||
|
@@ -347,6 +347,36 @@ public class ModuleComponentHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all registered modules.
|
||||||
|
*
|
||||||
|
* @return A Collection of module IDs
|
||||||
|
*/
|
||||||
|
Collection<String> getRegistryModuleIDs()
|
||||||
|
{
|
||||||
|
// Get the IDs of all modules from the registry
|
||||||
|
RegistryKey moduleKeyAllIds = new RegistryKey(
|
||||||
|
ModuleComponentHelper.URI_MODULES_1_0,
|
||||||
|
REGISTRY_PATH_MODULES, null);
|
||||||
|
|
||||||
|
return registryService.getChildElements(moduleKeyAllIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version number of a module from the Registry.
|
||||||
|
*
|
||||||
|
* @param moduleId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
VersionNumber getVersion(String moduleId)
|
||||||
|
{
|
||||||
|
RegistryKey moduleKeyCurrentVersion = new RegistryKey(
|
||||||
|
ModuleComponentHelper.URI_MODULES_1_0,
|
||||||
|
REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_CURRENT_VERSION);
|
||||||
|
VersionNumber versionCurrent = (VersionNumber) registryService.getProperty(moduleKeyCurrentVersion);
|
||||||
|
return versionCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if there are any modules registered as installed that aren't in the
|
* Checks to see if there are any modules registered as installed that aren't in the
|
||||||
* list of modules taken from the WAR.
|
* list of modules taken from the WAR.
|
||||||
@@ -356,10 +386,7 @@ public class ModuleComponentHelper
|
|||||||
private void checkForMissingModules()
|
private void checkForMissingModules()
|
||||||
{
|
{
|
||||||
// Get the IDs of all modules from the registry
|
// Get the IDs of all modules from the registry
|
||||||
RegistryKey moduleKeyAllIds = new RegistryKey(
|
Collection<String> moduleIds = getRegistryModuleIDs();
|
||||||
ModuleComponentHelper.URI_MODULES_1_0,
|
|
||||||
REGISTRY_PATH_MODULES, null);
|
|
||||||
Collection<String> moduleIds = registryService.getChildElements(moduleKeyAllIds);
|
|
||||||
|
|
||||||
// Check that each module is present in the distribution
|
// Check that each module is present in the distribution
|
||||||
for (String moduleId : moduleIds)
|
for (String moduleId : moduleIds)
|
||||||
@@ -375,10 +402,8 @@ public class ModuleComponentHelper
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get the specifics of the missing module
|
// Get the specifics of the missing module
|
||||||
RegistryKey moduleKeyCurrentVersion = new RegistryKey(
|
|
||||||
ModuleComponentHelper.URI_MODULES_1_0,
|
VersionNumber versionCurrent = getVersion(moduleId);
|
||||||
REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_CURRENT_VERSION);
|
|
||||||
VersionNumber versionCurrent = (VersionNumber) registryService.getProperty(moduleKeyCurrentVersion);
|
|
||||||
// The module is missing, so warn
|
// The module is missing, so warn
|
||||||
loggerService.warn(I18NUtil.getMessage(MSG_MISSING, moduleId, versionCurrent));
|
loggerService.warn(I18NUtil.getMessage(MSG_MISSING, moduleId, versionCurrent));
|
||||||
}
|
}
|
||||||
|
@@ -247,6 +247,24 @@ public class ModuleComponentHelperTest extends BaseAlfrescoTestCase
|
|||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ModuleDetails> getMissingModules()
|
||||||
|
{
|
||||||
|
// Create some module details
|
||||||
|
List<ModuleDetails> details = new ArrayList<ModuleDetails>(3);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
ModuleDetails moduleDetails = new ModuleDetailsImpl(
|
||||||
|
MODULE_IDS[i],
|
||||||
|
currentVersion,
|
||||||
|
"Module-" + i,
|
||||||
|
"Description-" + i);
|
||||||
|
details.add(moduleDetails);
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
return details;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Keep track of the execution count */
|
/** Keep track of the execution count */
|
||||||
|
@@ -27,14 +27,17 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.repo.admin.registry.RegistryKey;
|
||||||
import org.alfresco.repo.admin.registry.RegistryService;
|
import org.alfresco.repo.admin.registry.RegistryService;
|
||||||
import org.alfresco.repo.tenant.TenantAdminService;
|
import org.alfresco.repo.tenant.TenantAdminService;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.module.ModuleDetails;
|
import org.alfresco.service.cmr.module.ModuleDetails;
|
||||||
import org.alfresco.service.cmr.module.ModuleService;
|
import org.alfresco.service.cmr.module.ModuleService;
|
||||||
import org.alfresco.service.descriptor.DescriptorService;
|
import org.alfresco.service.descriptor.DescriptorService;
|
||||||
|
import org.alfresco.util.VersionNumber;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@@ -43,6 +46,7 @@ import org.springframework.context.ApplicationContextAware;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component controls the execution of
|
* This component controls the execution of
|
||||||
@@ -162,6 +166,35 @@ public class ModuleServiceImpl implements ApplicationContextAware, ModuleService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<ModuleDetails> getMissingModules()
|
||||||
|
{
|
||||||
|
cacheModuleDetails();
|
||||||
|
|
||||||
|
// Get the IDs of all modules from the registry
|
||||||
|
Collection<String> moduleIds = moduleComponentHelper.getRegistryModuleIDs();
|
||||||
|
|
||||||
|
List<ModuleDetails> result = new ArrayList<ModuleDetails>();
|
||||||
|
|
||||||
|
//Check for missing modules
|
||||||
|
for (String moduleId : moduleIds)
|
||||||
|
{
|
||||||
|
ModuleDetails moduleDetails = getModule(moduleId);
|
||||||
|
if (moduleDetails == null)
|
||||||
|
{
|
||||||
|
// Get the specifics of the missing module and add them to the list.
|
||||||
|
VersionNumber currentVersion = moduleComponentHelper.getVersion(moduleId);
|
||||||
|
|
||||||
|
ModuleDetails newModuleDetails = new ModuleDetailsImpl(moduleId, currentVersion, "", "");
|
||||||
|
|
||||||
|
result.add(newModuleDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that the {@link #moduleDetailsById module details} are populated.
|
* Ensure that the {@link #moduleDetailsById module details} are populated.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
import net.sf.acegisecurity.GrantedAuthority;
|
import net.sf.acegisecurity.GrantedAuthority;
|
||||||
@@ -160,9 +161,11 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
authenticateImpl(userName, password);
|
authenticateImpl(userName, password);
|
||||||
|
onAuthenticate();
|
||||||
}
|
}
|
||||||
catch (RuntimeException e)
|
catch (RuntimeException e)
|
||||||
{
|
{
|
||||||
|
onFail();
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("Failed to authenticate user \"" + userName + '"', e);
|
logger.debug("Failed to authenticate user \"" + userName + '"', e);
|
||||||
@@ -661,4 +664,26 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
|||||||
{
|
{
|
||||||
return authenticationContext.setUserDetails(ud);
|
return authenticationContext.setUserDetails(ud);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AtomicInteger numberSuccessfulAuthentications = new AtomicInteger(0);
|
||||||
|
AtomicInteger numberFailedAuthentications = new AtomicInteger(0);
|
||||||
|
protected void onAuthenticate()
|
||||||
|
{
|
||||||
|
numberSuccessfulAuthentications.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onFail()
|
||||||
|
{
|
||||||
|
numberFailedAuthentications.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberSuccessfulAuthentications()
|
||||||
|
{
|
||||||
|
return numberSuccessfulAuthentications.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberFailedAuthentications()
|
||||||
|
{
|
||||||
|
return numberFailedAuthentications.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,8 @@ import java.util.Collection;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||||
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +43,13 @@ public abstract class AbstractChainingAuthenticationComponent extends AbstractAu
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the authentication component with the specified name
|
||||||
|
* @param name
|
||||||
|
* @return the authentication component or null if it does not exist
|
||||||
|
*/
|
||||||
|
protected abstract AuthenticationComponent getAuthenticationComponent(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the authentication components across which methods will chain.
|
* Gets the authentication components across which methods will chain.
|
||||||
*
|
*
|
||||||
@@ -55,6 +64,8 @@ public abstract class AbstractChainingAuthenticationComponent extends AbstractAu
|
|||||||
* the user name
|
* the user name
|
||||||
* @param password
|
* @param password
|
||||||
* the password
|
* the password
|
||||||
|
*
|
||||||
|
* @throws AuthenticationException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void authenticateImpl(String userName, char[] password)
|
protected void authenticateImpl(String userName, char[] password)
|
||||||
@@ -74,6 +85,44 @@ public abstract class AbstractChainingAuthenticationComponent extends AbstractAu
|
|||||||
throw new AuthenticationException("Failed to authenticate");
|
throw new AuthenticationException("Failed to authenticate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test authenticate with a specific authenticator and user name and password.
|
||||||
|
*
|
||||||
|
* @param authenticatorName
|
||||||
|
* the name of the authenticator to use
|
||||||
|
* @param userName
|
||||||
|
* the user name
|
||||||
|
* @param password
|
||||||
|
* the password
|
||||||
|
* @throws AuthenticationException including diagnostic information about the failure
|
||||||
|
*/
|
||||||
|
public void testAuthenticate(String authenticatorName, String userName, char[] password)
|
||||||
|
{
|
||||||
|
|
||||||
|
AuthenticationComponent authenticationComponent = getAuthenticationComponent(authenticatorName);
|
||||||
|
if(authenticationComponent != null)
|
||||||
|
{
|
||||||
|
if (authenticationComponent instanceof ActivateableBean)
|
||||||
|
{
|
||||||
|
if(!((ActivateableBean) authenticationComponent).isActive())
|
||||||
|
{
|
||||||
|
AuthenticationDiagnostic diagnostic = new AuthenticationDiagnostic();
|
||||||
|
Object[] args = {authenticatorName};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION_AUTHENTICATOR_NOT_ACTIVE, false, args);
|
||||||
|
throw new AuthenticationException("authentication.err.validation.authenticator.notactive", args , diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticationComponent.authenticate(userName, password);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthenticationDiagnostic diagnostic = new AuthenticationDiagnostic();
|
||||||
|
Object[] args = {authenticatorName};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION_AUTHENTICATOR_NOT_FOUND, false, args);
|
||||||
|
throw new AuthenticationException("authentication.err.validation.authenticator.notfound", args , diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If any implementation supports guest then guest is allowed.
|
* If any implementation supports guest then guest is allowed.
|
||||||
*
|
*
|
||||||
|
@@ -27,7 +27,7 @@ import net.sf.acegisecurity.Authentication;
|
|||||||
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
|
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A chaining authentication component is required for all the beans that qire up an authentication component and not an
|
* A chaining authentication component is required for all the beans that wire up an authentication component and not an
|
||||||
* authentication service. It supports chaining in much the same way and wires up components in the same way as the
|
* authentication service. It supports chaining in much the same way and wires up components in the same way as the
|
||||||
* chaining authentication service wires up services.
|
* chaining authentication service wires up services.
|
||||||
*
|
*
|
||||||
@@ -306,4 +306,11 @@ public class ChainingAuthenticationComponentImpl extends AbstractChainingAuthent
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthenticationComponent getAuthenticationComponent(String name)
|
||||||
|
{
|
||||||
|
// not implemented
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import javax.naming.directory.InitialDirContext;
|
|||||||
|
|
||||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||||
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
|
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
import org.alfresco.repo.security.sync.ldap.LDAPNameResolver;
|
import org.alfresco.repo.security.sync.ldap.LDAPNameResolver;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@@ -108,18 +109,36 @@ public class LDAPAuthenticationComponentImpl extends AbstractAuthenticationCompo
|
|||||||
* Implement the authentication method
|
* Implement the authentication method
|
||||||
*/
|
*/
|
||||||
protected void authenticateImpl(String userName, char[] password) throws AuthenticationException
|
protected void authenticateImpl(String userName, char[] password) throws AuthenticationException
|
||||||
|
{
|
||||||
|
// Distinguished name of user.
|
||||||
|
String userDN;
|
||||||
|
|
||||||
|
AuthenticationDiagnostic diagnostic = new AuthenticationDiagnostic();
|
||||||
|
|
||||||
|
if(userNameFormat == null)
|
||||||
{
|
{
|
||||||
// If we aren't using a fixed name format, do a search to resolve the user DN
|
// If we aren't using a fixed name format, do a search to resolve the user DN
|
||||||
String userDN = userNameFormat == null ? ldapNameResolver.resolveDistinguishedName(userName) : String.format(
|
userDN = ldapNameResolver.resolveDistinguishedName(userName, diagnostic);
|
||||||
|
|
||||||
|
Object[] params = {userName, userDN};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_LOOKEDUP_USER, true, params);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we are using a fixed name format,
|
||||||
|
userDN = String.format(
|
||||||
userNameFormat, new Object[]
|
userNameFormat, new Object[]
|
||||||
{
|
{
|
||||||
escapeUserName(userName, escapeCommasInBind)
|
escapeUserName(userName, escapeCommasInBind)
|
||||||
});
|
});
|
||||||
|
Object[] params = {userName, userDN, userNameFormat};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_FORMAT_USER, true, params);
|
||||||
|
}
|
||||||
|
|
||||||
InitialDirContext ctx = null;
|
InitialDirContext ctx = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ctx = ldapInitialContextFactory.getInitialDirContext(userDN, new String(password));
|
ctx = ldapInitialContextFactory.getInitialDirContext(userDN, new String(password), diagnostic);
|
||||||
|
|
||||||
// Authentication has been successful.
|
// Authentication has been successful.
|
||||||
// Set the current user, they are now authenticated.
|
// Set the current user, they are now authenticated.
|
||||||
|
@@ -23,6 +23,7 @@ import java.util.Map;
|
|||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.directory.InitialDirContext;
|
import javax.naming.directory.InitialDirContext;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +40,20 @@ public interface LDAPInitialDirContextFactory
|
|||||||
*/
|
*/
|
||||||
public void setInitialDirContextEnvironment(Map<String, String> environment);
|
public void setInitialDirContextEnvironment(Map<String, String> environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the environment properties and connect to the LDAP server, optionally configuring RFC 2696 paged results.
|
||||||
|
* Used to obtain read only access to the LDAP server.
|
||||||
|
*
|
||||||
|
* @param pageSize
|
||||||
|
* if a positive value, indicates that a LDAP v3 RFC 2696 paged results control should be used. The
|
||||||
|
* results of a search operation should be returned by the LDAP server in batches of the specified size.
|
||||||
|
* @param diagnostic
|
||||||
|
* @return the default intial dir context
|
||||||
|
* @throws AuthenticationException
|
||||||
|
* the authentication exception
|
||||||
|
*/
|
||||||
|
public InitialDirContext getDefaultIntialDirContext(int pageSize, AuthenticationDiagnostic diagnostic) throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the environment properties and connect to the LDAP server, optionally configuring RFC 2696 paged results.
|
* Use the environment properties and connect to the LDAP server, optionally configuring RFC 2696 paged results.
|
||||||
* Used to obtain read only access to the LDAP server.
|
* Used to obtain read only access to the LDAP server.
|
||||||
@@ -61,6 +76,15 @@ public interface LDAPInitialDirContextFactory
|
|||||||
*/
|
*/
|
||||||
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException;
|
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the environment properties and connect to the LDAP server.
|
||||||
|
* Used to obtain read only access to the LDAP server.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws AuthenticationException
|
||||||
|
*/
|
||||||
|
public InitialDirContext getDefaultIntialDirContext(AuthenticationDiagnostic diagnostic) throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether there is another page to fetch from the last search to be run in this context. Also prepares
|
* Determines whether there is another page to fetch from the last search to be run in this context. Also prepares
|
||||||
* the request controls so that the appropriate cookie will be passed in the next search.
|
* the request controls so that the appropriate cookie will be passed in the next search.
|
||||||
@@ -84,4 +108,16 @@ public interface LDAPInitialDirContextFactory
|
|||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
*/
|
*/
|
||||||
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException;
|
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment the connection environment with the identity and credentials and bind to the ldap server.
|
||||||
|
* Mainly used to validate a user's credentials during authentication.
|
||||||
|
*
|
||||||
|
* @param principal
|
||||||
|
* @param credentials
|
||||||
|
* @param diagnostic
|
||||||
|
* @return
|
||||||
|
* @throws AuthenticationException
|
||||||
|
*/
|
||||||
|
public InitialDirContext getInitialDirContext(String principal, String credentials, AuthenticationDiagnostic diagnostic) throws AuthenticationException;
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.naming.AuthenticationNotSupportedException;
|
import javax.naming.AuthenticationNotSupportedException;
|
||||||
|
import javax.naming.CommunicationException;
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.naming.directory.Attribute;
|
import javax.naming.directory.Attribute;
|
||||||
@@ -40,6 +41,7 @@ import javax.naming.ldap.LdapContext;
|
|||||||
import javax.naming.ldap.PagedResultsControl;
|
import javax.naming.ldap.PagedResultsControl;
|
||||||
import javax.naming.ldap.PagedResultsResponseControl;
|
import javax.naming.ldap.PagedResultsResponseControl;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@@ -84,19 +86,38 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
|||||||
|
|
||||||
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException
|
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException
|
||||||
{
|
{
|
||||||
return getDefaultIntialDirContext(0);
|
return getDefaultIntialDirContext(0, new AuthenticationDiagnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InitialDirContext getDefaultIntialDirContext(int pageSize) throws AuthenticationException
|
public InitialDirContext getDefaultIntialDirContext(int pageSize) throws AuthenticationException
|
||||||
{
|
{
|
||||||
Hashtable<String, String> env = new Hashtable<String, String>(defaultEnvironment.size());
|
return getDefaultIntialDirContext(pageSize, new AuthenticationDiagnostic());
|
||||||
env.putAll(defaultEnvironment);
|
|
||||||
return buildInitialDirContext(env, pageSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InitialDirContext buildInitialDirContext(Hashtable<String, String> env, int pageSize)
|
@Override
|
||||||
|
public InitialDirContext getDefaultIntialDirContext(
|
||||||
|
AuthenticationDiagnostic diagnostic) throws AuthenticationException
|
||||||
|
{
|
||||||
|
return getDefaultIntialDirContext(0, diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InitialDirContext getDefaultIntialDirContext(int pageSize, AuthenticationDiagnostic diagnostic) throws AuthenticationException
|
||||||
|
{
|
||||||
|
Hashtable<String, String> env = new Hashtable<String, String>(defaultEnvironment.size());
|
||||||
|
env.putAll(defaultEnvironment);
|
||||||
|
return buildInitialDirContext(env, pageSize, diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InitialDirContext buildInitialDirContext(Hashtable<String, String> env, int pageSize, AuthenticationDiagnostic diagnostic)
|
||||||
throws AuthenticationException
|
throws AuthenticationException
|
||||||
{
|
{
|
||||||
|
String securityPrincipal = env.get(Context.SECURITY_PRINCIPAL);
|
||||||
|
String providerURL = env.get(Context.PROVIDER_URL);
|
||||||
|
|
||||||
|
if(diagnostic == null)
|
||||||
|
{
|
||||||
|
diagnostic = new AuthenticationDiagnostic();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// If a page size has been requested, use LDAP v3 paging
|
// If a page size has been requested, use LDAP v3 paging
|
||||||
@@ -111,20 +132,71 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new InitialDirContext(env);
|
InitialDirContext ret = new InitialDirContext(env);
|
||||||
|
Object[] args = {providerURL, securityPrincipal};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_CONNECTED, true, args);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (javax.naming.AuthenticationException ax)
|
catch (javax.naming.AuthenticationException ax)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("LDAP authentication failed.", ax);
|
Object[] args1 = {securityPrincipal};
|
||||||
|
Object[] args = {providerURL, securityPrincipal};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_CONNECTED, true, args);
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_AUTHENTICATION, false, args1);
|
||||||
|
|
||||||
|
// wrong user/password - if we get this far the connection is O.K
|
||||||
|
Object[] args2 = {securityPrincipal, ax.getLocalizedMessage()};
|
||||||
|
throw new AuthenticationException("authentication.err.authentication", diagnostic, args2, ax);
|
||||||
|
}
|
||||||
|
catch (CommunicationException ce)
|
||||||
|
{
|
||||||
|
Object[] args1 = {providerURL};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_CONNECTING, false, args1);
|
||||||
|
|
||||||
|
StringBuffer message = new StringBuffer();
|
||||||
|
|
||||||
|
message.append(ce.getClass().getName() + ", " + ce.getMessage());
|
||||||
|
|
||||||
|
Throwable cause = ce.getCause();
|
||||||
|
while (cause != null)
|
||||||
|
{
|
||||||
|
message.append(", ");
|
||||||
|
message.append(cause.getClass().getName() + ", " + cause.getMessage());
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// failed to connect
|
||||||
|
Object[] args = {providerURL, message.toString()};
|
||||||
|
throw new AuthenticationException("authentication.err.communication", diagnostic, args, cause);
|
||||||
}
|
}
|
||||||
catch (NamingException nx)
|
catch (NamingException nx)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("Unable to connect to LDAP Server; check LDAP configuration", nx);
|
Object[] args = {providerURL};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_CONNECTING, false, args);
|
||||||
|
|
||||||
|
StringBuffer message = new StringBuffer();
|
||||||
|
|
||||||
|
message.append(nx.getClass().getName() + ", " + nx.getMessage());
|
||||||
|
|
||||||
|
Throwable cause = nx.getCause();
|
||||||
|
while (cause != null)
|
||||||
|
{
|
||||||
|
message.append(", ");
|
||||||
|
message.append(cause.getClass().getName() + ", " + cause.getMessage());
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// failed to connect
|
||||||
|
Object[] args1 = {providerURL, message.toString()};
|
||||||
|
throw new AuthenticationException("authentication.err.connection", diagnostic, args1, nx);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("Unable to encode LDAP v3 request controls; check LDAP configuration", e);
|
Object[] args = {providerURL, securityPrincipal};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_CONNECTED, true, args);
|
||||||
|
|
||||||
|
throw new AuthenticationException("Unable to encode LDAP v3 request controls", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,36 +244,58 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException
|
@Override
|
||||||
|
public InitialDirContext getInitialDirContext(String principal,
|
||||||
|
String credentials)
|
||||||
|
throws AuthenticationException
|
||||||
{
|
{
|
||||||
|
return getInitialDirContext(principal, credentials, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InitialDirContext getInitialDirContext(String principal, String credentials, AuthenticationDiagnostic diagnostic) throws AuthenticationException
|
||||||
|
{
|
||||||
|
if(diagnostic == null)
|
||||||
|
{
|
||||||
|
diagnostic = new AuthenticationDiagnostic();
|
||||||
|
}
|
||||||
|
|
||||||
if (principal == null)
|
if (principal == null)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("Null user name provided.");
|
// failed before we tried to do anything
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION, false, null);
|
||||||
|
throw new AuthenticationException("Null user name provided.", diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (principal.length() == 0)
|
if (principal.length() == 0)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("Empty user name provided.");
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION, false, null);
|
||||||
|
throw new AuthenticationException("Empty user name provided.", diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (credentials == null)
|
if (credentials == null)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("No credentials provided.");
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION, false, null);
|
||||||
|
throw new AuthenticationException("No credentials provided.", diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (credentials.length() == 0)
|
if (credentials.length() == 0)
|
||||||
{
|
{
|
||||||
throw new AuthenticationException("Empty credentials provided.");
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION, false, null);
|
||||||
|
throw new AuthenticationException("Empty credentials provided.", diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_VALIDATION, true, null);
|
||||||
|
|
||||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||||
env.putAll(authenticatedEnvironment);
|
env.putAll(authenticatedEnvironment);
|
||||||
env.put(Context.SECURITY_PRINCIPAL, principal);
|
env.put(Context.SECURITY_PRINCIPAL, principal);
|
||||||
env.put(Context.SECURITY_CREDENTIALS, credentials);
|
env.put(Context.SECURITY_CREDENTIALS, credentials);
|
||||||
|
|
||||||
return buildInitialDirContext(env, 0);
|
return buildInitialDirContext(env, 0, diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
// ....build a pyramid selling scheme .....
|
// ....build a pyramid selling scheme .....
|
||||||
@@ -291,6 +385,7 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
|||||||
|
|
||||||
public void afterPropertiesSet() throws Exception
|
public void afterPropertiesSet() throws Exception
|
||||||
{
|
{
|
||||||
|
logger.debug("after Properties Set");
|
||||||
// Check Anonymous bind
|
// Check Anonymous bind
|
||||||
|
|
||||||
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
Hashtable<String, String> env = new Hashtable<String, String>(authenticatedEnvironment.size());
|
||||||
@@ -417,4 +512,8 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.authentication.ldap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.management.openmbean.CompositeData;
|
||||||
|
import javax.management.openmbean.CompositeDataSupport;
|
||||||
|
import javax.management.openmbean.CompositeType;
|
||||||
|
import javax.management.openmbean.OpenDataException;
|
||||||
|
import javax.management.openmbean.OpenType;
|
||||||
|
import javax.management.openmbean.SimpleType;
|
||||||
|
import javax.management.openmbean.TabularData;
|
||||||
|
import javax.management.openmbean.TabularDataSupport;
|
||||||
|
import javax.management.openmbean.TabularType;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationStep;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitoring methods and properties to be exposed via the
|
||||||
|
* JMX admin console.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Monitor
|
||||||
|
{
|
||||||
|
LDAPAuthenticationComponentImpl component;
|
||||||
|
|
||||||
|
private static Log logger = LogFactory.getLog(Monitor.class);
|
||||||
|
|
||||||
|
public void setLDAPAuthenticationComponent(LDAPAuthenticationComponentImpl component)
|
||||||
|
{
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthenticatorType()
|
||||||
|
{
|
||||||
|
return "ldap";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test authenticate
|
||||||
|
*
|
||||||
|
* @param userName
|
||||||
|
* @param credentials
|
||||||
|
* @throws AuthenticationException
|
||||||
|
*/
|
||||||
|
public CompositeData testAuthenticate(String userName, String credentials)
|
||||||
|
{
|
||||||
|
String stepKeys[] = {"id", "stepMessage", "success"};
|
||||||
|
String stepDescriptions[] = {"id", "stepMessage", "success"};
|
||||||
|
OpenType<?> stepTypes[] = {SimpleType.INTEGER, SimpleType.STRING, SimpleType.BOOLEAN };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String[] key = {"id"};
|
||||||
|
CompositeType sType = new CompositeType("Authentication Step", "Step", stepKeys, stepDescriptions, stepTypes);
|
||||||
|
TabularType tType = new TabularType("Diagnostic", "Authentication Steps", sType, key);
|
||||||
|
TabularData table = new TabularDataSupport(tType);
|
||||||
|
|
||||||
|
String attributeKeys[] = {"authenticationMessage", "success", "diagnostic"};
|
||||||
|
String attributeDescriptions[] = {"authenticationMessage", "success", "diagnostic"};
|
||||||
|
OpenType<?> attributeTypes[] = {SimpleType.STRING, SimpleType.BOOLEAN, tType};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
component.authenticate(userName, credentials.toCharArray());
|
||||||
|
|
||||||
|
CompositeType cType = new CompositeType("Authentication Result", "Result Success", attributeKeys, attributeDescriptions, attributeTypes);
|
||||||
|
Map<String, Object> value = new HashMap<String, Object>();
|
||||||
|
value.put("authenticationMessage", "Test Passed");
|
||||||
|
value.put("success", true);
|
||||||
|
value.put("diagnostic", table);
|
||||||
|
CompositeDataSupport row = new CompositeDataSupport(cType, value);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
catch (AuthenticationException ae)
|
||||||
|
{
|
||||||
|
CompositeType cType = new CompositeType("Authentication Result", "Result Failed", attributeKeys, attributeDescriptions, attributeTypes);
|
||||||
|
Map<String, Object> value = new HashMap<String, Object>();
|
||||||
|
value.put("authenticationMessage", ae.getMessage());
|
||||||
|
value.put("success", false);
|
||||||
|
|
||||||
|
if(ae.getDiagnostic() != null)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for(AuthenticationStep step : ae.getDiagnostic().getSteps())
|
||||||
|
{
|
||||||
|
Map<String, Object> x = new HashMap<String, Object>();
|
||||||
|
x.put("id", i++);
|
||||||
|
x.put("stepMessage", step.getMessage());
|
||||||
|
x.put("success", step.isSuccess());
|
||||||
|
CompositeDataSupport row = new CompositeDataSupport(sType, x);
|
||||||
|
table.put(row);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value.put("diagnostic", table);
|
||||||
|
|
||||||
|
CompositeDataSupport row = new CompositeDataSupport(cType, value);
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (OpenDataException oe)
|
||||||
|
{
|
||||||
|
logger.error("", oe);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberFailedAuthentications()
|
||||||
|
{
|
||||||
|
return component.getNumberFailedAuthentications();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberSuccessfulAuthentications()
|
||||||
|
{
|
||||||
|
return component.getNumberSuccessfulAuthentications();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.authentication.ldap;
|
||||||
|
|
||||||
|
import java.beans.BeanInfo;
|
||||||
|
import java.beans.SimpleBeanInfo;
|
||||||
|
/**
|
||||||
|
* A BeanInfo providing metadata for the Monitor class
|
||||||
|
*
|
||||||
|
* @author mrogers
|
||||||
|
*/
|
||||||
|
public class MonitorBeanInfo extends SimpleBeanInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the beans <code>BeanDescriptor</code>.
|
||||||
|
*
|
||||||
|
* @return A BeanDescriptor providing overall information about
|
||||||
|
* the bean, such as its displayName, its customizer, etc. May
|
||||||
|
* return null if the information should be obtained by automatic
|
||||||
|
* analysis.
|
||||||
|
*/
|
||||||
|
// BeanDescriptor getBeanDescriptor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the beans <code>EventSetDescriptor</code>s.
|
||||||
|
*
|
||||||
|
* @return An array of EventSetDescriptors describing the kinds of
|
||||||
|
* events fired by this bean. May return null if the information
|
||||||
|
* should be obtained by automatic analysis.
|
||||||
|
*/
|
||||||
|
// EventSetDescriptor[] getEventSetDescriptors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bean may have a "default" event that is the event that will
|
||||||
|
* mostly commonly be used by humans when using the bean.
|
||||||
|
* @return Index of default event in the EventSetDescriptor array
|
||||||
|
* returned by getEventSetDescriptors.
|
||||||
|
* <P> Returns -1 if there is no default event.
|
||||||
|
*/
|
||||||
|
// int getDefaultEventIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns descriptors for all properties of the bean.
|
||||||
|
* May return {@code null} if the information
|
||||||
|
* should be obtained by automatic analysis.
|
||||||
|
* <p>
|
||||||
|
* If a property is indexed, then its entry in the result array
|
||||||
|
* will belong to the {@link IndexedPropertyDescriptor} subclass
|
||||||
|
* of the {@link PropertyDescriptor} class.
|
||||||
|
* A client of the {@code getPropertyDescriptors} method
|
||||||
|
* can use "{@code instanceof}" to check
|
||||||
|
* whether a given {@code PropertyDescriptor}
|
||||||
|
* is an {@code IndexedPropertyDescriptor}.
|
||||||
|
*
|
||||||
|
* @return an array of {@code PropertyDescriptor}s
|
||||||
|
* describing all properties supported by the bean
|
||||||
|
* or {@code null}
|
||||||
|
*/
|
||||||
|
// PropertyDescriptor[] getPropertyDescriptors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bean may have a "default" property that is the property that will
|
||||||
|
* mostly commonly be initially chosen for update by human's who are
|
||||||
|
* customizing the bean.
|
||||||
|
* @return Index of default property in the PropertyDescriptor array
|
||||||
|
* returned by getPropertyDescriptors.
|
||||||
|
* <P> Returns -1 if there is no default property.
|
||||||
|
*/
|
||||||
|
// int getDefaultPropertyIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the beans <code>MethodDescriptor</code>s.
|
||||||
|
*
|
||||||
|
* @return An array of MethodDescriptors describing the externally
|
||||||
|
* visible methods supported by this bean. May return null if
|
||||||
|
* the information should be obtained by automatic analysis.
|
||||||
|
*/
|
||||||
|
// MethodDescriptor[] getMethodDescriptors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method allows a BeanInfo object to return an arbitrary collection
|
||||||
|
* of other BeanInfo objects that provide additional information on the
|
||||||
|
* current bean.
|
||||||
|
* <P>
|
||||||
|
* If there are conflicts or overlaps between the information provided
|
||||||
|
* by different BeanInfo objects, then the current BeanInfo takes precedence
|
||||||
|
* over the getAdditionalBeanInfo objects, and later elements in the array
|
||||||
|
* take precedence over earlier ones.
|
||||||
|
*
|
||||||
|
* @return an array of BeanInfo objects. May return null.
|
||||||
|
*/
|
||||||
|
// BeanInfo[] getAdditionalBeanInfo();
|
||||||
|
|
||||||
|
}
|
@@ -92,4 +92,25 @@ public class SubsystemChainingAuthenticationComponent extends AbstractChainingAu
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthenticationComponent getAuthenticationComponent(String instanceId)
|
||||||
|
{
|
||||||
|
ApplicationContext context = this.applicationContextManager.getApplicationContext(instanceId);
|
||||||
|
if(context != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AuthenticationComponent authenticationComponent = (AuthenticationComponent) context
|
||||||
|
.getBean(sourceBeanName);
|
||||||
|
return authenticationComponent;
|
||||||
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.security.sync.ldap;
|
package org.alfresco.repo.security.sync.ldap;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,5 +38,5 @@ public interface LDAPNameResolver
|
|||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* if the user ID cannot be resolved
|
* if the user ID cannot be resolved
|
||||||
*/
|
*/
|
||||||
public String resolveDistinguishedName(String userId) throws AuthenticationException;
|
public String resolveDistinguishedName(String userId, AuthenticationDiagnostic diagnostic) throws AuthenticationException;
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,7 @@ import javax.naming.ldap.LdapName;
|
|||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationDiagnostic;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
import org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactory;
|
import org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactory;
|
||||||
import org.alfresco.repo.security.sync.NodeDescription;
|
import org.alfresco.repo.security.sync.NodeDescription;
|
||||||
@@ -920,8 +921,12 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.security.sync.ldap.LDAPNameResolver#resolveDistinguishedName(java.lang.String)
|
* @see org.alfresco.repo.security.sync.ldap.LDAPNameResolver#resolveDistinguishedName(java.lang.String)
|
||||||
*/
|
*/
|
||||||
public String resolveDistinguishedName(String userId) throws AuthenticationException
|
public String resolveDistinguishedName(String userId, AuthenticationDiagnostic diagnostic) throws AuthenticationException
|
||||||
{
|
{
|
||||||
|
if(logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("resolveDistinguishedName userId:" + userId);
|
||||||
|
}
|
||||||
SearchControls userSearchCtls = new SearchControls();
|
SearchControls userSearchCtls = new SearchControls();
|
||||||
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||||
|
|
||||||
@@ -931,13 +936,18 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
|
|||||||
this.userIdAttributeName
|
this.userIdAttributeName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
String query = this.userSearchBase + "(&" + this.personQuery
|
||||||
|
+ "(" + this.userIdAttributeName + "= userId))";
|
||||||
|
|
||||||
|
|
||||||
InitialDirContext ctx = null;
|
InitialDirContext ctx = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ctx = this.ldapInitialContextFactory.getDefaultIntialDirContext();
|
ctx = this.ldapInitialContextFactory.getDefaultIntialDirContext(diagnostic);
|
||||||
|
|
||||||
// Execute the user query with an additional condition that ensures only the user with the required ID is
|
// Execute the user query with an additional condition that ensures only the user with the required ID is
|
||||||
// returned. Force RFC 2254 escaping of the user ID in the filter to avoid any manipulation
|
// returned. Force RFC 2254 escaping of the user ID in the filter to avoid any manipulation
|
||||||
|
|
||||||
NamingEnumeration<SearchResult> searchResults = ctx.search(this.userSearchBase, "(&" + this.personQuery
|
NamingEnumeration<SearchResult> searchResults = ctx.search(this.userSearchBase, "(&" + this.personQuery
|
||||||
+ "(" + this.userIdAttributeName + "={0}))", new Object[]
|
+ "(" + this.userIdAttributeName + "={0}))", new Object[]
|
||||||
{
|
{
|
||||||
@@ -948,11 +958,22 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
|
|||||||
{
|
{
|
||||||
return searchResults.next().getNameInNamespace();
|
return searchResults.next().getNameInNamespace();
|
||||||
}
|
}
|
||||||
throw new AuthenticationException("Failed to resolve user: " + userId);
|
|
||||||
|
Object[] args = {userId, query};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_LOOKUP_USER, false, args);
|
||||||
|
|
||||||
|
throw new AuthenticationException("authentication.err.connection.ldap.user.notfound", args, diagnostic);
|
||||||
}
|
}
|
||||||
catch (NamingException e)
|
catch (NamingException e)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to resolve user ID: " + userId, e);
|
// Connection is good here - AuthenticationException would be thrown by ldapInitialContextFactory
|
||||||
|
|
||||||
|
Object[] args1 = {userId, query};
|
||||||
|
diagnostic.addStep(AuthenticationDiagnostic.STEP_KEY_LDAP_SEARCH, false, args1);
|
||||||
|
|
||||||
|
// failed to search
|
||||||
|
Object[] args = {e.getLocalizedMessage()};
|
||||||
|
throw new AuthenticationException("authentication.err.connection.ldap.search", diagnostic, args, e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -964,6 +985,7 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
|
|||||||
}
|
}
|
||||||
catch (NamingException e)
|
catch (NamingException e)
|
||||||
{
|
{
|
||||||
|
logger.debug("error when closing ldap context", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
source/java/org/alfresco/repo/template/URLDecodeMethod.java
Normal file
65
source/java/org/alfresco/repo/template/URLDecodeMethod.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.template;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.extensions.surf.util.URLDecoder;
|
||||||
|
|
||||||
|
import freemarker.template.TemplateMethodModelEx;
|
||||||
|
import freemarker.template.TemplateModelException;
|
||||||
|
import freemarker.template.TemplateScalarModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kevin Roast
|
||||||
|
* @since 4.2
|
||||||
|
*
|
||||||
|
* Custom FreeMarker Template language method.
|
||||||
|
* <p>
|
||||||
|
* Decodes a URL encoded string. The empty string is returned for invalid input values.
|
||||||
|
* <p>
|
||||||
|
* Usage: urldecode(String s)
|
||||||
|
*/
|
||||||
|
public class URLDecodeMethod extends BaseTemplateProcessorExtension implements TemplateMethodModelEx
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
|
||||||
|
*/
|
||||||
|
public Object exec(List args) throws TemplateModelException
|
||||||
|
{
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
if (args.size() != 0)
|
||||||
|
{
|
||||||
|
String s = "";
|
||||||
|
Object arg0 = args.get(0);
|
||||||
|
if (arg0 instanceof TemplateScalarModel)
|
||||||
|
{
|
||||||
|
s = ((TemplateScalarModel)arg0).getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
result = URLDecoder.decode(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@@ -19,6 +19,7 @@
|
|||||||
package org.alfresco.service.cmr.module;
|
package org.alfresco.service.cmr.module;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.module.ModuleComponent;
|
import org.alfresco.repo.module.ModuleComponent;
|
||||||
|
|
||||||
@@ -47,6 +48,13 @@ public interface ModuleService
|
|||||||
*/
|
*/
|
||||||
List<ModuleDetails> getAllModules();
|
List<ModuleDetails> getAllModules();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of the modules missing from the system.
|
||||||
|
*
|
||||||
|
* @return module details of the modules missing from the system.
|
||||||
|
*/
|
||||||
|
List<ModuleDetails> getMissingModules();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a component of a module for execution.
|
* Register a component of a module for execution.
|
||||||
*
|
*
|
||||||
|
@@ -37,4 +37,10 @@ public interface WebDavService
|
|||||||
* @return true if activity generation is enabled.
|
* @return true if activity generation is enabled.
|
||||||
*/
|
*/
|
||||||
public boolean activitiesEnabled();
|
public boolean activitiesEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the web dav service enabled?
|
||||||
|
* @return true, is enabled
|
||||||
|
*/
|
||||||
|
public boolean getEnabled();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user