mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged V2.1 to HEAD
6466: Xml metadata. Support for pulling collections of values from XML 6470: Fix for AWC-1321 - Using zero as items per page gives error for Alfresco repos in OpenSearch 6471: Fix for AWC-1496 - OpenSearch dashlet can get in a state where search queries are not executed 6472: Fix for AWC-1495. Searching additional attributes now working correctly for folders. 6473: Fix for AR-1251 (Version error when saving new content via CIFS) 6474: Updated bundles and installers - added missing files back into Linux bundle 6475: LDAP and chainging authentication Resolved conflicted state of 'root\projects\repository\source\java\org\alfresco\repo\security\authentication\AuthenticationUtil.java' 6477: XForms WCM-696. 6478: Fix for WCM-567 (IndexOutOfBoundsException when stepping through wizard rapidly) 6480: Fix to issue when removing locks on directories. 6481: Updated installer and config wizard to fix download option and config behaviour when called from installer. 6482: Fix for WCM-1229 (properties sheet does not refresh) 6483: Fix for AR-1511 6484: Fix for AR-1351 6485: Missed a unit test update git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6737 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -74,7 +74,6 @@
|
||||
<!-- The authroity DAO implements an interface extended from the Acegi -->
|
||||
<!-- DAO that supports CRUD. -->
|
||||
|
||||
<alias name="authenticationDao" alias="alfDaoImpl"/> <!-- TODO: Remove -->
|
||||
<bean id="authenticationDao" class="org.alfresco.repo.security.authentication.RepositoryAuthenticationDao">
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService" />
|
||||
@@ -118,7 +117,6 @@
|
||||
<!-- The permissions service is required so that permissions can be -->
|
||||
<!-- cleaned up when a user is deleted. -->
|
||||
|
||||
<alias name="authenticationService" alias="authenticationServiceImpl"/> <!-- TODO: Remove -->
|
||||
<bean id="authenticationService" class="org.alfresco.repo.security.authentication.AuthenticationServiceImpl">
|
||||
<property name="authenticationDao">
|
||||
<ref bean="authenticationDao" />
|
||||
|
@@ -519,7 +519,7 @@
|
||||
<ref bean="policyComponent" />
|
||||
</property>
|
||||
<property name="authenticationService">
|
||||
<ref bean="authenticationServiceImpl"></ref>
|
||||
<ref bean="authenticationService"></ref>
|
||||
</property>
|
||||
<property name="ownableService">
|
||||
<ref bean="ownableService"></ref>
|
||||
|
@@ -5,9 +5,9 @@
|
||||
|
||||
|
||||
|
||||
<!-- Chaining -->
|
||||
<!-- Chaining of both the services and components -->
|
||||
|
||||
<bean id="authenticationServiceImpl" class="org.alfresco.repo.security.authentication.ChainingAuthenticationServiceImpl">
|
||||
<bean id="authenticationService" class="org.alfresco.repo.security.authentication.ChainingAuthenticationServiceImpl">
|
||||
<property name="authenticationServices">
|
||||
<list>
|
||||
<ref bean="authenticationServiceImplJAAS"/>
|
||||
@@ -18,6 +18,17 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationComponent" class="org.alfresco.repo.security.authentication.ChainingAuthenticationComponentImpl">
|
||||
<property name="authenticationComponentss">
|
||||
<list>
|
||||
<ref bean="authenticationComponentImplJAAS"/>
|
||||
</list>
|
||||
</property>
|
||||
<property name="mutableAuthenticationComponent">
|
||||
<ref bean="authenticationComponentImplAlfresco"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Alfresco Auth -->
|
||||
|
||||
<bean id="authenticationServiceImplAlfresco" class="org.alfresco.repo.security.authentication.AuthenticationServiceImpl">
|
||||
|
@@ -3,6 +3,17 @@
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- The main configuration has moved into a properties file -->
|
||||
|
||||
<bean name="ldapAuthenticationPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
||||
<property name="ignoreUnresolvablePlaceholders">
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="locations">
|
||||
<value>classpath:alfresco/extension/ldap-authentication.properties</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- DAO that rejects changes - LDAP is read only at the moment. It does allow users to be deleted with out warnings from the UI. -->
|
||||
|
||||
<bean name="authenticationDao" class="org.alfresco.repo.security.authentication.DefaultMutableAuthenticationDao" >
|
||||
@@ -34,11 +45,11 @@
|
||||
"%s" - the user id is passed through without modification.
|
||||
Used for LDAP authentication such as DIGEST-MD5, anything that is not "simple".
|
||||
|
||||
"cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the authentricate as "cn=Joe Bloggs,ou=London,dc=company,dc=com"
|
||||
Usually for simple authentication.
|
||||
"cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the authenticate as "cn=Joe Bloggs,ou=London,dc=company,dc=com"
|
||||
Usually for simple authentication. Simple authentication always uses the DN for the user.
|
||||
|
||||
-->
|
||||
<value>%s</value>
|
||||
<value>${ldap.authentication.userNameFormat}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -54,14 +65,14 @@
|
||||
<map>
|
||||
<!-- The LDAP provider -->
|
||||
<entry key="java.naming.factory.initial">
|
||||
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
|
||||
<value>${ldap.authentication.java.naming.factory.initial}</value>
|
||||
</entry>
|
||||
|
||||
<!-- The url to the LDAP server -->
|
||||
<!-- Note you can use space separated urls - they will be tried in turn until one works -->
|
||||
<!-- This could be used to authenticate against one or more ldap servers (you will not know which one ....) -->
|
||||
<entry key="java.naming.provider.url">
|
||||
<value>ldap://openldap.domain.com:389</value>
|
||||
<value>${ldap.authentication.java.naming.provider.url}</value>
|
||||
</entry>
|
||||
|
||||
<!-- The authentication mechanism to use -->
|
||||
@@ -69,390 +80,21 @@
|
||||
<!-- java.naming.security.sasl.realm -->
|
||||
<!-- The available options will depend on your LDAP provider -->
|
||||
<entry key="java.naming.security.authentication">
|
||||
<value>DIGEST-MD5</value>
|
||||
<value>${ldap.authentication.java.naming.security.authentication}</value>
|
||||
</entry>
|
||||
|
||||
<!-- The id of a user who can read group and user information -->
|
||||
<!-- This does not go through the pattern substitution defined above and is used "as is" -->
|
||||
<entry key="java.naming.security.principal">
|
||||
<value>reader</value>
|
||||
<value>${ldap.authentication.java.naming.security.principal}</value>
|
||||
</entry>
|
||||
|
||||
<!-- The password for the user defined above -->
|
||||
<entry key="java.naming.security.credentials">
|
||||
<value>secret</value>
|
||||
<value>${ldap.authentication.java.naming.security.credentials}</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Ldap Syncronisation support -->
|
||||
|
||||
<!--
|
||||
|
||||
There can be more than one stack of beans that import users or groups. For example, it may be easier
|
||||
to have a version of ldapPeopleExportSource, and associated beans, for each sub-tree of your ldap directory
|
||||
from which you want to import users. You could then limit users to be imported from two or more sub tress and ignore
|
||||
users found else where. The same applies to the import of groups.
|
||||
|
||||
The defaults shown below are for OpenLDAP.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<!-- Extract user information from LDAP and transform this to XML -->
|
||||
|
||||
<bean id="ldapPeopleExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPPersonExportSource">
|
||||
<!--
|
||||
The query to select objects that represent the users to import.
|
||||
|
||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||
(objectclass=inetOrgPerson)
|
||||
|
||||
For Active Directory:
|
||||
(objectclass=user)
|
||||
-->
|
||||
<property name="personQuery">
|
||||
<value>(objectclass=inetOrgPerson)</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
|
||||
-->
|
||||
<property name="searchBase">
|
||||
<value>dc=alfresco,dc=org</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The unique identifier for the user.
|
||||
|
||||
THIS MUST MATCH WHAT THE USER TYPES IN AT THE LOGIN PROMPT
|
||||
|
||||
For simple LDAP authentication this is likely to be "cn" or, less friendly, "distinguishedName"
|
||||
|
||||
In OpenLDAP, using other authentication mechanisms "uid", but this depends on how you map
|
||||
from the id in the LDAP authentication request to search for the inetOrgPerson against which
|
||||
to authenticate.
|
||||
|
||||
In Active Directory this is most likely to be "sAMAccountName"
|
||||
|
||||
This property is mandatory and must appear on all users found by the query defined above.
|
||||
|
||||
-->
|
||||
<property name="userIdAttributeName">
|
||||
<value>uid</value>
|
||||
</property>
|
||||
|
||||
<!-- Services -->
|
||||
<property name="LDAPInitialDirContextFactory">
|
||||
<ref bean="ldapInitialDirContextFactory"/>
|
||||
</property>
|
||||
<property name="personService">
|
||||
<ref bean="personService"></ref>
|
||||
</property>
|
||||
<property name="namespaceService">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
This property defines a mapping between attributes held on LDAP user objects and
|
||||
the properties of user objects held in the repository. The key is the QName of an attribute in
|
||||
the repository, the value is the attribute name from the user/inetOrgPerson/.. object in the
|
||||
LDAP repository.
|
||||
-->
|
||||
<property name="attributeMapping">
|
||||
<map>
|
||||
<entry key="cm:userName">
|
||||
<!-- Must match the same attribute as userIdAttributeName -->
|
||||
<value>uid</value>
|
||||
</entry>
|
||||
<entry key="cm:firstName">
|
||||
<!-- OpenLDAP: "givenName" -->
|
||||
<!-- Active Directory: "givenName" -->
|
||||
<value>givenName</value>
|
||||
</entry>
|
||||
<entry key="cm:lastName">
|
||||
<!-- OpenLDAP: "sn" -->
|
||||
<!-- Active Directory: "sn" -->
|
||||
<value>sn</value>
|
||||
</entry>
|
||||
<entry key="cm:email">
|
||||
<!-- OpenLDAP: "mail" -->
|
||||
<!-- Active Directory: "???" -->
|
||||
<value>mail</value>
|
||||
</entry>
|
||||
<entry key="cm:organizationId">
|
||||
<!-- OpenLDAP: "o" -->
|
||||
<!-- Active Directory: "???" -->
|
||||
<value>o</value>
|
||||
</entry>
|
||||
<!-- Always use the default -->
|
||||
<entry key="cm:homeFolderProvider">
|
||||
<null/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
<!-- Set a default home folder provider -->
|
||||
<!-- Defaults only apply for values above -->
|
||||
<property name="attributeDefaults">
|
||||
<map>
|
||||
<entry key="cm:homeFolderProvider">
|
||||
<value>personalHomeFolderProvider</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Extract group information from LDAP and transform this to XML -->
|
||||
|
||||
<bean id="ldapGroupExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPGroupExportSource">
|
||||
<!--
|
||||
The query to select objects that represent the groups to import.
|
||||
|
||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||
(objectclass=groupOfNames)
|
||||
|
||||
For Active Directory:
|
||||
(objectclass=group)
|
||||
-->
|
||||
<property name="groupQuery">
|
||||
<value>(objectclass=groupOfNames)</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
|
||||
-->
|
||||
<property name="searchBase">
|
||||
<value>dc=alfresco,dc=org</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The unique identifier for the user. This must match the userIdAttributeName on the ldapPeopleExportSource bean above.
|
||||
-->
|
||||
<property name="userIdAttributeName">
|
||||
<value>uid</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
An attribute that is a unique identifier for each group found.
|
||||
This is also the name of the group with the current group implementation.
|
||||
This is mandatory for any groups found.
|
||||
|
||||
OpenLDAP: "cn" as it is mandatory on groupOfNames
|
||||
Active Directory: "cn"
|
||||
|
||||
-->
|
||||
<property name="groupIdAttributeName">
|
||||
<value>cn</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The objectClass attribute for group members.
|
||||
For each member of a group, the distinguished name is given.
|
||||
The object is looked up by its DN. If the object is of this class it is treated as a group.
|
||||
-->
|
||||
<property name="groupType">
|
||||
<value>groupOfNames</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The objectClass attribute for person members.
|
||||
For each member of a group, the distinguished name is given.
|
||||
The object is looked up by its DN. If the object is of this class it is treated as a person.
|
||||
-->
|
||||
<property name="personType">
|
||||
<value>inetOrgPerson</value>
|
||||
</property>
|
||||
<property name="LDAPInitialDirContextFactory">
|
||||
<ref bean="ldapInitialDirContextFactory"/>
|
||||
</property>
|
||||
<property name="namespaceService">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The repeating attribute on group objects (found by query or as sub groups)
|
||||
used to define membership of the group. This is assumed to hold distinguished names of
|
||||
other groups or users/people; the above types are used to determine this.
|
||||
|
||||
OpenLDAP: "member" as it is mandatory on groupOfNames
|
||||
Active Directory: "member"
|
||||
|
||||
-->
|
||||
<property name="memberAttribute">
|
||||
<value>member</value>
|
||||
</property>
|
||||
|
||||
<property name="authorityDAO">
|
||||
<ref bean="authorityDAO"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Job definitions to import LDAP people and groups -->
|
||||
<!-- The triggers register themselves with the scheduler -->
|
||||
<!-- You may comment in the default scheduler to enable these triggers -->
|
||||
<!-- If a cron base trigger is what you want seee scheduled-jobs-context.xml for examples. -->
|
||||
|
||||
<!-- Trigger to load poeple -->
|
||||
<!-- Note you can have more than one initial (context, trigger, import job and export source) set -->
|
||||
<!-- This would allow you to load people from more than one ldap store -->
|
||||
|
||||
<bean id="ldapPeopleTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean id="ldapPeopleJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.importer.ImporterJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="bean">
|
||||
<ref bean="ldapPeopleImport"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<!-- Start after 5 minutes of starting the repository -->
|
||||
<property name="startDelay">
|
||||
<value>300000</value>
|
||||
</property>
|
||||
<!-- Repeat every hour -->
|
||||
<property name="repeatInterval">
|
||||
<value>3600000</value>
|
||||
</property>
|
||||
<!-- Commented out to disable
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
-->
|
||||
</bean>
|
||||
|
||||
<bean id="ldapGroupTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean id="ldapGroupJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.importer.ImporterJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="bean">
|
||||
<ref bean="ldapGroupImport"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<!-- Start after 5 minutes of starting the repository -->
|
||||
<property name="startDelay">
|
||||
<value>300000</value>
|
||||
</property>
|
||||
<!-- Repeat every hour -->
|
||||
<property name="repeatInterval">
|
||||
<value>3600000</value>
|
||||
</property>
|
||||
<!-- Commented out to disable
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
-->
|
||||
</bean>
|
||||
|
||||
<!-- The bean that imports xml describing people -->
|
||||
|
||||
<bean id="ldapPeopleImport" class="org.alfresco.repo.importer.ExportSourceImporter">
|
||||
<property name="importerService">
|
||||
<ref bean="importerComponentWithBehaviour"/>
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="transactionComponent"/>
|
||||
</property>
|
||||
<property name="authenticationComponent">
|
||||
<ref bean="authenticationComponent"/>
|
||||
</property>
|
||||
<property name="exportSource">
|
||||
<ref bean="ldapPeopleExportSource"/>
|
||||
</property>
|
||||
|
||||
<!-- The store that contains people - this should not be changed -->
|
||||
<property name="storeRef">
|
||||
<value>${spaces.store}</value>
|
||||
</property>
|
||||
|
||||
<!-- The location of people nodes within the store defined above - this should not be changed -->
|
||||
<property name="path">
|
||||
<value>/${system.system_container.childname}/${system.people_container.childname}</value>
|
||||
</property>
|
||||
|
||||
<!-- If true, clear all existing people before import, if false update/add people from the xml -->
|
||||
<property name="clearAllChildren">
|
||||
<value>false</value>
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="searchService"/>
|
||||
</property>
|
||||
<property name="namespacePrefixResolver">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
|
||||
<property name="caches">
|
||||
<set>
|
||||
<ref bean="permissionsAccessCache"/>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The bean that imports xml descibing groups -->
|
||||
|
||||
<bean id="ldapGroupImport" class="org.alfresco.repo.importer.ExportSourceImporter">
|
||||
<property name="importerService">
|
||||
<ref bean="importerComponentWithBehaviour"/>
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="transactionComponent"/>
|
||||
</property>
|
||||
<property name="authenticationComponent">
|
||||
<ref bean="authenticationComponent"/>
|
||||
</property>
|
||||
<property name="exportSource">
|
||||
<ref bean="ldapGroupExportSource"/>
|
||||
</property>
|
||||
<!-- The store that contains group information - this should not be changed -->
|
||||
<property name="storeRef">
|
||||
<value>${alfresco_user_store.store}</value>
|
||||
</property>
|
||||
|
||||
<!-- The location of group information in the store above - this should not be changed -->
|
||||
<property name="path">
|
||||
<value>/${alfresco_user_store.system_container.childname}/${alfresco_user_store.authorities_container.childname}</value>
|
||||
</property>
|
||||
|
||||
<!-- If true, clear all existing groups before import, if false update/add groups from the xml -->
|
||||
<property name="clearAllChildren">
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="searchService"/>
|
||||
</property>
|
||||
<property name="namespacePrefixResolver">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!-- caches to clear on import of groups -->
|
||||
<property name="caches">
|
||||
<set>
|
||||
<ref bean="userToAuthorityCache"/>
|
||||
<ref bean="permissionsAccessCache"/>
|
||||
</set>
|
||||
</property>
|
||||
|
||||
<!-- userToAuthorityCache -->
|
||||
</bean>
|
||||
|
||||
</beans>
|
27
config/alfresco/extension/ldap-authentication.properties
Normal file
27
config/alfresco/extension/ldap-authentication.properties
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# This properties file brings together the common options for LDAP authentication rather than editing the bean definitions
|
||||
#
|
||||
|
||||
# How to map the user id entered by the user to taht passed through to LDAP
|
||||
# - simple
|
||||
# - this must be a DN and would be something like
|
||||
# CN=%s,DC=company,DC=com
|
||||
# - digest
|
||||
# - usually pass through what is entered
|
||||
# %s
|
||||
ldap.authentication.userNameFormat=%s
|
||||
|
||||
# The LDAP context factory to use
|
||||
ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
|
||||
|
||||
# The URL to connect to the LDAP server
|
||||
ldap.authentication.java.naming.provider.url=ldap://openldap.domain.com:389
|
||||
|
||||
# The authentication mechanism to use
|
||||
ldap.authentication.java.naming.security.authentication=DIGEST-MD5
|
||||
|
||||
# The default principal to use (only used for LDAP sync)
|
||||
ldap.authentication.java.naming.security.principal=reader
|
||||
|
||||
# The password for the default principal (only used for LDAP sync)
|
||||
ldap.authentication.java.naming.security.credentials=secret
|
@@ -0,0 +1,377 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
|
||||
<bean name="ldapSynchronisationPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
||||
<property name="ignoreUnresolvablePlaceholders">
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="locations">
|
||||
<value>classpath:alfresco/extension/ldap-synchronisation.properties</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Wire up the same context as used for LDAP authentication. You could use another context: just replace this
|
||||
alias with the bean definition
|
||||
-->
|
||||
|
||||
<alias alias="ldapSyncInitialDirContextFactory" name="ldapInitialDirContextFactory"/>
|
||||
|
||||
<!-- Ldap Syncronisation support -->
|
||||
|
||||
<!--
|
||||
|
||||
There can be more than one stack of beans that import users or groups. For example, it may be easier
|
||||
to have a version of ldapPeopleExportSource, and associated beans, for each sub-tree of your ldap directory
|
||||
from which you want to import users. You could then limit users to be imported from two or more sub tress and ignore
|
||||
users found else where. The same applies to the import of groups.
|
||||
|
||||
The defaults shown below are for OpenLDAP.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<!-- Extract user information from LDAP and transform this to XML -->
|
||||
|
||||
<bean id="ldapPeopleExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPPersonExportSource">
|
||||
<!--
|
||||
The query to select objects that represent the users to import.
|
||||
|
||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||
(objectclass=inetOrgPerson)
|
||||
|
||||
For Active Directory:
|
||||
(objectclass=user)
|
||||
-->
|
||||
<property name="personQuery">
|
||||
<value>${ldap.synchronisation.personQuery}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
|
||||
-->
|
||||
<property name="searchBase">
|
||||
<value>${ldap.synchronisation.personSearchBase}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The unique identifier for the user.
|
||||
|
||||
THIS MUST MATCH WHAT THE USER TYPES IN AT THE LOGIN PROMPT
|
||||
|
||||
For simple LDAP authentication this is likely to be "cn" or, less friendly, "distinguishedName"
|
||||
|
||||
In OpenLDAP, using other authentication mechanisms "uid", but this depends on how you map
|
||||
from the id in the LDAP authentication request to search for the inetOrgPerson against which
|
||||
to authenticate.
|
||||
|
||||
In Active Directory this is most likely to be "sAMAccountName"
|
||||
|
||||
This property is mandatory and must appear on all users found by the query defined above.
|
||||
|
||||
-->
|
||||
<property name="userIdAttributeName">
|
||||
<value>${ldap.synchronisation.userIdAttributeName]</value>
|
||||
</property>
|
||||
|
||||
<!-- Services -->
|
||||
<property name="LDAPInitialDirContextFactory">
|
||||
<ref bean="ldapSyncInitialDirContextFactory"/>
|
||||
</property>
|
||||
<property name="personService">
|
||||
<ref bean="personService"></ref>
|
||||
</property>
|
||||
<property name="namespaceService">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
This property defines a mapping between attributes held on LDAP user objects and
|
||||
the properties of user objects held in the repository. The key is the QName of an attribute in
|
||||
the repository, the value is the attribute name from the user/inetOrgPerson/.. object in the
|
||||
LDAP repository.
|
||||
-->
|
||||
<property name="attributeMapping">
|
||||
<map>
|
||||
<entry key="cm:userName">
|
||||
<!-- Must match the same attribute as userIdAttributeName -->
|
||||
<value>${ldap.synchronisation.userIdAttributeName}</value>
|
||||
</entry>
|
||||
<entry key="cm:firstName">
|
||||
<!-- OpenLDAP: "givenName" -->
|
||||
<!-- Active Directory: "givenName" -->
|
||||
<value>${ldap.synchronisation.userFirstNameAttributeName}</value>
|
||||
</entry>
|
||||
<entry key="cm:lastName">
|
||||
<!-- OpenLDAP: "sn" -->
|
||||
<!-- Active Directory: "sn" -->
|
||||
<value>${ldap.synchronisation.userLastNameAttributeName}</value>
|
||||
</entry>
|
||||
<entry key="cm:email">
|
||||
<!-- OpenLDAP: "mail" -->
|
||||
<!-- Active Directory: "???" -->
|
||||
<value>${ldap.synchronisation.userEmailAttributeName}</value>
|
||||
</entry>
|
||||
<entry key="cm:organizationId">
|
||||
<!-- OpenLDAP: "o" -->
|
||||
<!-- Active Directory: "???" -->
|
||||
<value>${ldap.synchronisation.userOrganizationalIdAttributeName}</value>
|
||||
</entry>
|
||||
<!-- Always use the default -->
|
||||
<entry key="cm:homeFolderProvider">
|
||||
<null/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
<!-- Set a default home folder provider -->
|
||||
<!-- Defaults only apply for values above -->
|
||||
<property name="attributeDefaults">
|
||||
<map>
|
||||
<entry key="cm:homeFolderProvider">
|
||||
<value>${ldap.synchronisation.defaultHomeFolderProvider}</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Extract group information from LDAP and transform this to XML -->
|
||||
|
||||
<bean id="ldapGroupExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPGroupExportSource">
|
||||
<!--
|
||||
The query to select objects that represent the groups to import.
|
||||
|
||||
For Open LDAP, using a basic schema, the following is probably what you want:
|
||||
(objectclass=groupOfNames)
|
||||
|
||||
For Active Directory:
|
||||
(objectclass=group)
|
||||
-->
|
||||
<property name="groupQuery">
|
||||
<value>${ldap.synchronisation.groupQuery}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
|
||||
-->
|
||||
<property name="searchBase">
|
||||
<value>${ldap.synchronisation.groupSearchBase}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The unique identifier for the user. This must match the userIdAttributeName on the ldapPeopleExportSource bean above.
|
||||
-->
|
||||
<property name="userIdAttributeName">
|
||||
<value>${ldap.synchronisation.userIdAttributeName}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
An attribute that is a unique identifier for each group found.
|
||||
This is also the name of the group with the current group implementation.
|
||||
This is mandatory for any groups found.
|
||||
|
||||
OpenLDAP: "cn" as it is mandatory on groupOfNames
|
||||
Active Directory: "cn"
|
||||
|
||||
-->
|
||||
<property name="groupIdAttributeName">
|
||||
<value>${ldap.synchronisation.groupIdAttributeName}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The objectClass attribute for group members.
|
||||
For each member of a group, the distinguished name is given.
|
||||
The object is looked up by its DN. If the object is of this class it is treated as a group.
|
||||
-->
|
||||
<property name="groupType">
|
||||
<value>${ldap.synchronisation.groupType}</value>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The objectClass attribute for person members.
|
||||
For each member of a group, the distinguished name is given.
|
||||
The object is looked up by its DN. If the object is of this class it is treated as a person.
|
||||
-->
|
||||
<property name="personType">
|
||||
<value>${ldap.synchronisation.personType}</value>
|
||||
</property>
|
||||
<property name="LDAPInitialDirContextFactory">
|
||||
<ref bean="ldapSyncInitialDirContextFactory"/>
|
||||
</property>
|
||||
<property name="namespaceService">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
The repeating attribute on group objects (found by query or as sub groups)
|
||||
used to define membership of the group. This is assumed to hold distinguished names of
|
||||
other groups or users/people; the above types are used to determine this.
|
||||
|
||||
OpenLDAP: "member" as it is mandatory on groupOfNames
|
||||
Active Directory: "member"
|
||||
|
||||
-->
|
||||
<property name="memberAttribute">
|
||||
<value>${ldap.synchronisation.groupMemberAttributeName}</value>
|
||||
</property>
|
||||
|
||||
<property name="authorityDAO">
|
||||
<ref bean="authorityDAO"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Job definitions to import LDAP people and groups -->
|
||||
<!-- The triggers register themselves with the scheduler -->
|
||||
<!-- You may comment in the default scheduler to enable these triggers -->
|
||||
<!-- If a cron base trigger is what you want seee scheduled-jobs-context.xml for examples. -->
|
||||
|
||||
<!-- Trigger to load poeple -->
|
||||
<!-- Note you can have more than one initial (context, trigger, import job and export source) set -->
|
||||
<!-- This would allow you to load people from more than one ldap store -->
|
||||
|
||||
<bean id="ldapPeopleTrigger" class="org.alfresco.util.CronTriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean id="ldapPeopleJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.importer.ImporterJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="bean">
|
||||
<ref bean="ldapPeopleImport"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="cronExpression">
|
||||
<value>${ldap.synchronisation.import.person.cron}</value>
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="ldapGroupTrigger" class="org.alfresco.util.CronTriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean id="ldapGroupJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.importer.ImporterJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="bean">
|
||||
<ref bean="ldapGroupImport"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="cronExpression">
|
||||
<value>${ldap.synchronisation.import.group.cron}</value>
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The bean that imports xml describing people -->
|
||||
|
||||
<bean id="ldapPeopleImport" class="org.alfresco.repo.importer.ExportSourceImporter">
|
||||
<property name="importerService">
|
||||
<ref bean="importerComponentWithBehaviour"/>
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="transactionComponent"/>
|
||||
</property>
|
||||
<property name="authenticationComponent">
|
||||
<ref bean="authenticationComponent"/>
|
||||
</property>
|
||||
<property name="exportSource">
|
||||
<ref bean="ldapPeopleExportSource"/>
|
||||
</property>
|
||||
|
||||
<!-- The store that contains people - this should not be changed -->
|
||||
<property name="storeRef">
|
||||
<value>${spaces.store}</value>
|
||||
</property>
|
||||
|
||||
<!-- The location of people nodes within the store defined above - this should not be changed -->
|
||||
<property name="path">
|
||||
<value>/${system.system_container.childname}/${system.people_container.childname}</value>
|
||||
</property>
|
||||
|
||||
<!-- If true, clear all existing people before import, if false update/add people from the xml -->
|
||||
<property name="clearAllChildren">
|
||||
<value>false</value>
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="searchService"/>
|
||||
</property>
|
||||
<property name="namespacePrefixResolver">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
|
||||
<property name="caches">
|
||||
<set>
|
||||
<ref bean="permissionsAccessCache"/>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The bean that imports xml descibing groups -->
|
||||
|
||||
<bean id="ldapGroupImport" class="org.alfresco.repo.importer.ExportSourceImporter">
|
||||
<property name="importerService">
|
||||
<ref bean="importerComponentWithBehaviour"/>
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="transactionComponent"/>
|
||||
</property>
|
||||
<property name="authenticationComponent">
|
||||
<ref bean="authenticationComponent"/>
|
||||
</property>
|
||||
<property name="exportSource">
|
||||
<ref bean="ldapGroupExportSource"/>
|
||||
</property>
|
||||
<!-- The store that contains group information - this should not be changed -->
|
||||
<property name="storeRef">
|
||||
<value>${alfresco_user_store.store}</value>
|
||||
</property>
|
||||
|
||||
<!-- The location of group information in the store above - this should not be changed -->
|
||||
<property name="path">
|
||||
<value>/${alfresco_user_store.system_container.childname}/${alfresco_user_store.authorities_container.childname}</value>
|
||||
</property>
|
||||
|
||||
<!-- If true, clear all existing groups before import, if false update/add groups from the xml -->
|
||||
<property name="clearAllChildren">
|
||||
<value>${ldap.synchronisation.import.group.clearAllChildren}</value>
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="searchService"/>
|
||||
</property>
|
||||
<property name="namespacePrefixResolver">
|
||||
<ref bean="namespaceService"/>
|
||||
</property>
|
||||
|
||||
<!-- caches to clear on import of groups -->
|
||||
<property name="caches">
|
||||
<set>
|
||||
<ref bean="userToAuthorityCache"/>
|
||||
<ref bean="permissionsAccessCache"/>
|
||||
</set>
|
||||
</property>
|
||||
|
||||
<!-- userToAuthorityCache -->
|
||||
</bean>
|
||||
|
||||
</beans>
|
59
config/alfresco/extension/ldap-synchronisation.properties
Normal file
59
config/alfresco/extension/ldap-synchronisation.properties
Normal file
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# This properties file is used to configure LDAP syncronisation
|
||||
#
|
||||
|
||||
# The query to find the people to import
|
||||
ldap.synchronisation.personQuery=(objectclass=inetOrgPerson)
|
||||
|
||||
# The search base of the query to find people to import
|
||||
ldap.synchronisation.personSearchBase=dc=company,dc=com
|
||||
|
||||
# The attribute name on people objects found in LDAP to use as the uid in Alfresco
|
||||
ldap.synchronisation.userIdAttributeName=uid
|
||||
|
||||
# The attribute on person objects in LDAP to map to the first name property in Alfresco
|
||||
ldap.synchronisation.userFirstNameAttributeName=givenName
|
||||
|
||||
# The attribute on person objects in LDAP to map to the last name property in Alfresco
|
||||
ldap.synchronisation.userLastNameAttributeName=sn
|
||||
|
||||
# The attribute on person objects in LDAP to map to the email property in Alfresco
|
||||
ldap.synchronisation.userEmailAttributeName=mail
|
||||
|
||||
# The attribute on person objects in LDAP to map to the organizational id property in Alfresco
|
||||
ldap.synchronisation.userOrganizationalIdAttributeName=o
|
||||
|
||||
# The default home folder provider to use for people created via LDAP import
|
||||
ldap.synchronisation.defaultHomeFolderProvider=personalHomeFolderProvider
|
||||
|
||||
# The query to find group objects
|
||||
ldap.synchronisation.groupQuery=(objectclass=groupOfNames)
|
||||
|
||||
# The search base to use to find group objects
|
||||
ldap.synchronisation.groupSearchBase=dc=company,dc=com
|
||||
|
||||
# The attribute on LDAP group objects to map to the gid property in Alfrecso
|
||||
ldap.synchronisation.groupIdAttributeName=cn
|
||||
|
||||
# The group type in LDAP
|
||||
ldap.synchronisation.groupType=groupOfNames
|
||||
|
||||
# The person type in LDAP
|
||||
ldap.synchronisation.personType=inetOrgPerson
|
||||
|
||||
# The attribute in LDAP on group objects that defines the DN for its members
|
||||
ldap.synchronisation.groupMemberAttributeName=member
|
||||
|
||||
# The cron expression defining when people imports should take place
|
||||
ldap.synchronisation.import.person.cron=0 0 * * * ?
|
||||
|
||||
# The cron expression defining when group imports should take place
|
||||
ldap.synchronisation.import.group.cron=0 30 * * * ?
|
||||
|
||||
# Should all groups be cleared out at import time?
|
||||
# - this is safe as groups are not used in Alfresco for other things (unlike person objects which you should never clear out during an import)
|
||||
# - setting this to true means old group definitions will be tidied up.
|
||||
ldap.synchronisation.import.group.clearAllChildren=true
|
||||
|
||||
|
||||
|
@@ -219,6 +219,7 @@
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</target>
|
||||
<duplicate>false</duplicate>
|
||||
</child-association>
|
||||
</associations>
|
||||
</type>
|
||||
|
@@ -7,10 +7,13 @@
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="authenticationService">
|
||||
<ref bean="authenticationServiceImpl"/>
|
||||
<ref bean="authenticationService"/>
|
||||
</property>
|
||||
<property name="nodeOwnerCache">
|
||||
<ref bean="nodeOwnerCache"/>
|
||||
</property>
|
||||
<property name="policyComponent">
|
||||
<ref bean="policyComponent" />
|
||||
</property>
|
||||
</bean>
|
||||
</beans>
|
@@ -204,7 +204,7 @@
|
||||
<ref bean="nodeService"></ref>
|
||||
</property>
|
||||
<property name="authenticationService">
|
||||
<ref bean="authenticationServiceImpl" />
|
||||
<ref bean="authenticationService" />
|
||||
</property>
|
||||
<property name="maxPermissionCheckTimeMillis">
|
||||
<value>${system.acl.maxPermissionCheckTimeMillis}</value>
|
||||
|
@@ -101,6 +101,9 @@
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService"/>
|
||||
</property>
|
||||
<property name="contentService">
|
||||
<ref bean="contentService"/>
|
||||
</property>
|
||||
<property name="authenticationComponent">
|
||||
<ref bean="authenticationComponent"/>
|
||||
</property>
|
||||
@@ -166,7 +169,7 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="on-content-update-trigger" class="org.alfresco.repo.rule.ruletrigger.OnContentUpdateRuleTrigger" parent="rule-trigger-base">
|
||||
<bean id="on-content-update-trigger" class="org.alfresco.repo.rule.ruletrigger.OnContentUpdateRuleTrigger" parent="rule-trigger-base">
|
||||
<property name="onNewContent">
|
||||
<value>false</value>
|
||||
</property>
|
||||
|
@@ -76,7 +76,7 @@ public class TestData
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Bootstrap Users
|
||||
MutableAuthenticationDao authDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
|
||||
MutableAuthenticationDao authDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
|
||||
if (authDAO.userExists("superuser") == false)
|
||||
{
|
||||
authDAO.createUser("superuser", "".toCharArray());
|
||||
|
@@ -120,7 +120,7 @@ public class AuditServiceTest extends BaseSpringTest
|
||||
authorityService = (AuthorityService) applicationContext.getBean("authorityService");
|
||||
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
|
||||
|
||||
auditService = (AuditService) applicationContext.getBean("AuditService");
|
||||
auditEntry = (AuditEntry) applicationContext.getBean("auditModel");
|
||||
|
@@ -177,7 +177,7 @@ public class AVMSubmitPackageHandler
|
||||
Map<String, AVMNodeDescriptor> list = fAVMService.getDirectoryListing(desc, true);
|
||||
for (AVMNodeDescriptor child : list.values())
|
||||
{
|
||||
recursivelyRemoveLocks(webProject, child.getVersionID(), child.getPath());
|
||||
recursivelyRemoveLocks(webProject, version, child.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -57,6 +57,8 @@ import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* An extracter that pulls values from XML documents using configurable XPath
|
||||
@@ -248,7 +250,30 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
|
||||
String documentProperty = element.getKey();
|
||||
XPathExpression xpathExpression = element.getValue();
|
||||
// Execute it
|
||||
String value = (String) xpathExpression.evaluate(document, XPathConstants.STRING);
|
||||
NodeList nodeList = (NodeList) xpathExpression.evaluate(document, XPathConstants.NODESET);
|
||||
// Convert the value
|
||||
Serializable value = null;
|
||||
int nodeCount = nodeList.getLength();
|
||||
if (nodeCount == 0)
|
||||
{
|
||||
// No result
|
||||
}
|
||||
else if (nodeCount == 1)
|
||||
{
|
||||
Node node = nodeList.item(0);
|
||||
// Get the string value
|
||||
value = node.getTextContent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make a collection of the values
|
||||
ArrayList<String> stringValues = new ArrayList<String>(5);
|
||||
for (int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
stringValues.add(nodeList.item(i).getTextContent());
|
||||
}
|
||||
value = stringValues;
|
||||
}
|
||||
// Put the value
|
||||
rawProperties.put(documentProperty, value);
|
||||
}
|
||||
@@ -305,7 +330,7 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
|
||||
xpathExpressionMapping.put(documentProperty, xpathExpression);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Added mapping from " + documentProperty + " to " + xpathExpression);
|
||||
logger.debug("Added mapping from " + documentProperty + " to " + xpathStr);
|
||||
}
|
||||
}
|
||||
// Done
|
||||
|
@@ -26,49 +26,65 @@ package org.alfresco.repo.ownable.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Ownership service support. Use in permissions framework as dynamic authority.
|
||||
* Ownership service support. Use in permissions framework as dynamic authority.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public class OwnableServiceImpl implements OwnableService, InitializingBean
|
||||
public class OwnableServiceImpl implements OwnableService, InitializingBean, NodeServicePolicies.OnAddAspectPolicy, NodeServicePolicies.OnUpdatePropertiesPolicy,
|
||||
NodeServicePolicies.OnRemoveAspectPolicy, NodeServicePolicies.OnDeleteNodePolicy
|
||||
{
|
||||
private NodeService nodeService;
|
||||
|
||||
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
|
||||
private SimpleCache<NodeRef, String> nodeOwnerCache;
|
||||
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
public OwnableServiceImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
// IOC
|
||||
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ownerCache a transactionally-safe cache of node owners
|
||||
* @param ownerCache
|
||||
* a transactionally-safe cache of node owners
|
||||
*/
|
||||
public void setNodeOwnerCache(SimpleCache<NodeRef, String> ownerCache)
|
||||
{
|
||||
@@ -89,14 +105,31 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
|
||||
{
|
||||
throw new IllegalArgumentException("Property 'nodeOwnerCache' has not been set");
|
||||
}
|
||||
if (policyComponent == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Property 'policyComponent' has not been set");
|
||||
}
|
||||
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onAddAspect"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onUpdateProperties"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this,
|
||||
"onRemoveAspect"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onDeleteNode"));
|
||||
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onAddAspect"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onUpdateProperties"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this,
|
||||
"onRemoveAspect"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onDeleteNode"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
// OwnableService implmentation
|
||||
|
||||
|
||||
public String getOwner(NodeRef nodeRef)
|
||||
{
|
||||
String userName = nodeOwnerCache.get(nodeRef);
|
||||
|
||||
|
||||
if (userName == null)
|
||||
{
|
||||
// If ownership is not explicitly set then we fall back to the creator
|
||||
@@ -104,13 +137,13 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
|
||||
{
|
||||
userName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, ContentModel.PROP_OWNER));
|
||||
}
|
||||
else if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE))
|
||||
else if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE))
|
||||
{
|
||||
userName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, ContentModel.PROP_CREATOR));
|
||||
}
|
||||
nodeOwnerCache.put(nodeRef, userName);
|
||||
}
|
||||
|
||||
|
||||
return userName;
|
||||
}
|
||||
|
||||
@@ -138,4 +171,41 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
|
||||
{
|
||||
return getOwner(nodeRef) != null;
|
||||
}
|
||||
|
||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
nodeOwnerCache.remove(nodeRef);
|
||||
}
|
||||
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
nodeOwnerCache.remove(nodeRef);
|
||||
}
|
||||
|
||||
public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isNodeArchived)
|
||||
{
|
||||
nodeOwnerCache.remove(childAssocRef.getChildRef());
|
||||
}
|
||||
|
||||
public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||
{
|
||||
Serializable pb = before.get(ContentModel.PROP_OWNER);
|
||||
Serializable pa = after.get(ContentModel.PROP_OWNER);
|
||||
|
||||
if (!EqualsHelper.nullSafeEquals(pb, pa))
|
||||
{
|
||||
nodeOwnerCache.remove(nodeRef);
|
||||
return;
|
||||
}
|
||||
|
||||
pb = before.get(ContentModel.PROP_CREATOR);
|
||||
pa = after.get(ContentModel.PROP_CREATOR);
|
||||
|
||||
if (!EqualsHelper.nullSafeEquals(pb, pa))
|
||||
{
|
||||
nodeOwnerCache.remove(nodeRef);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,9 @@
|
||||
*/
|
||||
package org.alfresco.repo.ownable.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
@@ -40,6 +43,7 @@ import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -85,7 +89,7 @@ public class OwnableServiceTest extends TestCase
|
||||
permissionService = (PermissionService) ctx.getBean("permissionService");
|
||||
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
|
||||
|
||||
|
||||
TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
|
||||
@@ -147,6 +151,14 @@ public class OwnableServiceTest extends TestCase
|
||||
assertFalse(nodeService.hasAspect(testNode, ContentModel.ASPECT_OWNABLE));
|
||||
assertTrue(dynamicAuthority.hasAuthority(testNode, "andy"));
|
||||
|
||||
assertEquals("andy", ownableService.getOwner(testNode));
|
||||
|
||||
nodeService.setProperty(testNode, ContentModel.PROP_CREATOR, "woof");
|
||||
assertEquals("woof", ownableService.getOwner(testNode));
|
||||
|
||||
nodeService.setProperty(testNode, ContentModel.PROP_CREATOR, "andy");
|
||||
assertEquals("andy", ownableService.getOwner(testNode));
|
||||
|
||||
permissionService.setInheritParentPermissions(testNode, false);
|
||||
|
||||
|
||||
@@ -189,6 +201,16 @@ public class OwnableServiceTest extends TestCase
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(testNode, PermissionService.TAKE_OWNERSHIP));
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(testNode, PermissionService.SET_OWNER));
|
||||
|
||||
nodeService.setProperty(testNode, ContentModel.PROP_OWNER, "muppet");
|
||||
assertEquals("muppet", ownableService.getOwner(testNode));
|
||||
nodeService.removeAspect(testNode, ContentModel.ASPECT_OWNABLE);
|
||||
assertEquals("andy", ownableService.getOwner(testNode));
|
||||
|
||||
HashMap<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>();
|
||||
aspectProperties.put(ContentModel.PROP_OWNER, "muppet");
|
||||
nodeService.addAspect(testNode, ContentModel.ASPECT_OWNABLE, aspectProperties);
|
||||
assertEquals("muppet", ownableService.getOwner(testNode));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -26,9 +26,12 @@ package org.alfresco.repo.rule.ruletrigger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.ContentServicePolicies;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -87,9 +90,24 @@ public class OnContentUpdateRuleTrigger extends RuleTriggerAbstractBase
|
||||
*/
|
||||
public void onContentUpdate(NodeRef nodeRef, boolean newContent)
|
||||
{
|
||||
if (newContent == this.onNewContent)
|
||||
|
||||
// Check the new content and make sure that we do indeed want to trigger the rule
|
||||
boolean fail = false;
|
||||
if (newContent == true)
|
||||
{
|
||||
ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
if (contentReader == null ||
|
||||
contentReader.exists() == false ||
|
||||
isZeroLengthOfficeDoc(contentReader) == true)
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the rules in the appropriate way
|
||||
if (fail == false && newContent == this.onNewContent)
|
||||
{
|
||||
if (triggerParentRules == true)
|
||||
if (triggerParentRules == true)
|
||||
{
|
||||
if (logger.isDebugEnabled() == true)
|
||||
{
|
||||
@@ -108,5 +126,24 @@ public class OnContentUpdateRuleTrigger extends RuleTriggerAbstractBase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether we are dealing with a zero length office document or not
|
||||
*
|
||||
* @param contentReader the content reader
|
||||
* @return boolean true if zero length office document, false otherwise
|
||||
*/
|
||||
private boolean isZeroLengthOfficeDoc(ContentReader contentReader)
|
||||
{
|
||||
boolean result = false;
|
||||
if (contentReader.getSize() == 0 &&
|
||||
(MimetypeMap.MIMETYPE_WORD.equals(contentReader.getMimetype()) == true ||
|
||||
MimetypeMap.MIMETYPE_EXCEL.equals(contentReader.getMimetype()) == true ||
|
||||
MimetypeMap.MIMETYPE_PPT.equals(contentReader.getMimetype()) == true))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -30,12 +30,13 @@ import java.util.Set;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
|
||||
/**
|
||||
* Rule trigger abstract base
|
||||
* Rule trigger abstract base
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
@@ -55,6 +56,11 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
* The node service
|
||||
*/
|
||||
protected NodeService nodeService;
|
||||
|
||||
/**
|
||||
* The content service
|
||||
*/
|
||||
protected ContentService contentService;
|
||||
|
||||
/**
|
||||
* The authentication Component
|
||||
@@ -91,6 +97,16 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content service
|
||||
*
|
||||
* @param contentService the content service
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authenticationComponent
|
||||
@@ -123,6 +139,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
|
||||
/**
|
||||
* Registration of an interested rule type
|
||||
*
|
||||
*/
|
||||
public void registerRuleType(RuleType ruleType)
|
||||
{
|
||||
@@ -131,7 +148,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
|
||||
|
||||
/**
|
||||
* Trigger the rules that relate to any interested rule types for the node
|
||||
* references passed.
|
||||
* references passed.
|
||||
*
|
||||
* @param nodeRef
|
||||
* the node reference who rules are to be triggered
|
||||
|
@@ -98,7 +98,7 @@ public class SearchServiceTest extends TestCase
|
||||
nodeService = (NodeService) ctx.getBean("dbNodeService");
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
authenticationService = (AuthenticationService) ctx.getBean("authenticationService");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
|
||||
pubSearchService = (SearchService) ctx.getBean("SearchService");
|
||||
pubPermissionService = (PermissionService) ctx.getBean("PermissionService");
|
||||
|
||||
|
@@ -28,10 +28,6 @@ import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
import net.sf.acegisecurity.context.Context;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.security.SecureContext;
|
||||
import net.sf.acegisecurity.context.security.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
@@ -46,11 +42,9 @@ import org.alfresco.service.cmr.security.PermissionService;
|
||||
*/
|
||||
public abstract class AbstractAuthenticationComponent implements AuthenticationComponent
|
||||
{
|
||||
|
||||
// Name of the system user
|
||||
|
||||
static final String SYSTEM_USER_NAME = "System";
|
||||
|
||||
/**
|
||||
* The abstract class keeps track of support for guest login
|
||||
*/
|
||||
private Boolean allowGuestLogin = null;
|
||||
|
||||
public AbstractAuthenticationComponent()
|
||||
@@ -58,6 +52,11 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if guest login is supported.
|
||||
*
|
||||
* @param allowGuestLogin
|
||||
*/
|
||||
public void setAllowGuestLogin(Boolean allowGuestLogin)
|
||||
{
|
||||
this.allowGuestLogin = allowGuestLogin;
|
||||
@@ -65,6 +64,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
|
||||
public void authenticate(String userName, char[] password) throws AuthenticationException
|
||||
{
|
||||
// Support guest login from the login screen
|
||||
if ((userName != null) && (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY)))
|
||||
{
|
||||
setGuestUserAsCurrentUser();
|
||||
@@ -75,6 +75,14 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default unsupported authentication implementation
|
||||
* - as of 2.1 this is the best way to implement your own authentication component as it will support guest login
|
||||
* - prior to this direct over ride for authenticate(String , char[]) was used. This will still work.
|
||||
*
|
||||
* @param userName
|
||||
* @param password
|
||||
*/
|
||||
protected void authenticateImpl(String userName, char[] password)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -97,11 +105,11 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
try
|
||||
{
|
||||
UserDetails ud = null;
|
||||
if (userName.equals(SYSTEM_USER_NAME))
|
||||
if (userName.equals(AuthenticationUtil.SYSTEM_USER_NAME))
|
||||
{
|
||||
GrantedAuthority[] gas = new GrantedAuthority[1];
|
||||
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
|
||||
ud = new User(SYSTEM_USER_NAME, "", true, true, true, true, gas);
|
||||
ud = new User(AuthenticationUtil.SYSTEM_USER_NAME, "", true, true, true, true, gas);
|
||||
}
|
||||
else if (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY))
|
||||
{
|
||||
@@ -173,28 +181,6 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
return AuthenticationUtil.getCurrentUserName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user name
|
||||
*
|
||||
* @param authentication
|
||||
* Authentication
|
||||
* @return String
|
||||
*/
|
||||
private String getUserName(Authentication authentication)
|
||||
{
|
||||
String username;
|
||||
if (authentication.getPrincipal() instanceof UserDetails)
|
||||
{
|
||||
username = ((UserDetails) authentication.getPrincipal()).getUsername();
|
||||
}
|
||||
else
|
||||
{
|
||||
username = authentication.getPrincipal().toString();
|
||||
}
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the system user as the current user.
|
||||
*
|
||||
@@ -202,7 +188,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
*/
|
||||
public Authentication setSystemUserAsCurrentUser()
|
||||
{
|
||||
return setCurrentUser(SYSTEM_USER_NAME);
|
||||
return setCurrentUser(AuthenticationUtil.SYSTEM_USER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,7 +198,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
|
||||
*/
|
||||
public String getSystemUserName()
|
||||
{
|
||||
return SYSTEM_USER_NAME;
|
||||
return AuthenticationUtil.SYSTEM_USER_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -135,7 +135,7 @@ public class AuthenticationTest extends TestCase
|
||||
// ctx.getBean("permissionService");
|
||||
ticketsCache = (SimpleCache<String, Ticket>) ctx.getBean("ticketsCache");
|
||||
|
||||
dao = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
|
||||
dao = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
|
||||
authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager");
|
||||
saltSource = (SaltSource) ctx.getBean("saltSource");
|
||||
|
||||
|
@@ -231,7 +231,6 @@ public abstract class AuthenticationUtil
|
||||
private static String getUserName(Authentication authentication)
|
||||
{
|
||||
String username;
|
||||
|
||||
if (authentication.getPrincipal() instanceof UserDetails)
|
||||
{
|
||||
username = ((UserDetails) authentication.getPrincipal()).getUsername();
|
||||
|
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
|
||||
/**
|
||||
* A chaining authentication component is required for all the beans that qire 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 asthe
|
||||
* chaining authentication service wires up services.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class ChainingAuthenticationComponentImpl implements AuthenticationComponent
|
||||
{
|
||||
/**
|
||||
* NLTM authentication mode - if unset - finds the first component that supports NTLM - if set - finds the first
|
||||
* component that supports the specified mode.
|
||||
*/
|
||||
private NTLMMode ntlmMode = null;
|
||||
|
||||
/**
|
||||
* The authentication components
|
||||
*/
|
||||
private List<AuthenticationComponent> authenticationComponents;
|
||||
|
||||
/**
|
||||
* An authentication service that supports change (as wired in to the authentication service). It is never used for
|
||||
* change it is to ensure it is at the top of the list (as required by the chaining authentication service)
|
||||
*/
|
||||
private AuthenticationComponent mutableAuthenticationComponent;
|
||||
|
||||
/**
|
||||
* Get the authentication components
|
||||
*
|
||||
* @return - a list of authentication components
|
||||
*/
|
||||
public List<AuthenticationComponent> getAuthenticationComponents()
|
||||
{
|
||||
return authenticationComponents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a list of authentication components
|
||||
*
|
||||
* @param authenticationComponents
|
||||
*/
|
||||
public void setAuthenticationComponents(List<AuthenticationComponent> authenticationComponents)
|
||||
{
|
||||
this.authenticationComponents = authenticationComponents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authentication service thta must be at the top of the list (this may be null)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public AuthenticationComponent getMutableAuthenticationComponent()
|
||||
{
|
||||
return mutableAuthenticationComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication component at the top of the list.
|
||||
*
|
||||
* @param mutableAuthenticationComponent
|
||||
*/
|
||||
public void setMutableAuthenticationComponent(AuthenticationComponent mutableAuthenticationComponent)
|
||||
{
|
||||
this.mutableAuthenticationComponent = mutableAuthenticationComponent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setNtlmMode(NTLMMode ntlmMode)
|
||||
{
|
||||
this.ntlmMode = ntlmMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain authentication with user name and password - tries all in order until one works, or fails.
|
||||
*/
|
||||
public void authenticate(String userName, char[] password) throws AuthenticationException
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
try
|
||||
{
|
||||
authComponent.authenticate(userName, password);
|
||||
return;
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
// Ignore and chain
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("Failed to authenticate");
|
||||
}
|
||||
|
||||
/**
|
||||
* NTLM passthrough authentication - if a mode is defined - the first PASS_THROUGH provider is used - if not, the
|
||||
* first component that supports NTLM is used if it supports PASS_THROUGH
|
||||
*/
|
||||
public Authentication authenticate(Authentication token) throws AuthenticationException
|
||||
{
|
||||
if (ntlmMode != null)
|
||||
{
|
||||
switch (ntlmMode)
|
||||
{
|
||||
case NONE:
|
||||
throw new AuthenticationException("NTLM is not supported");
|
||||
case MD4_PROVIDER:
|
||||
throw new AuthenticationException("NTLM passthrough is not supported then configured for MD4 hashing");
|
||||
case PASS_THROUGH:
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
|
||||
{
|
||||
return authComponent.authenticate(token);
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("No NTLM passthrough authentication to use");
|
||||
default:
|
||||
throw new AuthenticationException("No NTLM passthrough authentication to use");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() != NTLMMode.NONE)
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
|
||||
{
|
||||
return authComponent.authenticate(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AuthenticationException("The first authentication component to support NTLM supports MD4 hashing");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("No NTLM passthrough authentication to use");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the security context
|
||||
*/
|
||||
public void clearCurrentSecurityContext()
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current authentication
|
||||
*/
|
||||
public Authentication getCurrentAuthentication() throws AuthenticationException
|
||||
{
|
||||
return AuthenticationUtil.getCurrentAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user name
|
||||
*/
|
||||
public String getCurrentUserName() throws AuthenticationException
|
||||
{
|
||||
return AuthenticationUtil.getCurrentUserName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guest user name
|
||||
*/
|
||||
public String getGuestUserName()
|
||||
{
|
||||
return PermissionService.GUEST_AUTHORITY.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MD4 password hash
|
||||
*/
|
||||
public String getMD4HashedPassword(String userName)
|
||||
{
|
||||
if (ntlmMode != null)
|
||||
{
|
||||
switch (ntlmMode)
|
||||
{
|
||||
case NONE:
|
||||
throw new AuthenticationException("NTLM is not supported");
|
||||
case PASS_THROUGH:
|
||||
throw new AuthenticationException("NTLM passthrough is not supported then configured for MD4 hashing");
|
||||
case MD4_PROVIDER:
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
|
||||
{
|
||||
return authComponent.getMD4HashedPassword(userName);
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("No MD4 provider available");
|
||||
default:
|
||||
throw new AuthenticationException("No MD4 provider available");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() != NTLMMode.NONE)
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
|
||||
{
|
||||
throw new AuthenticationException("The first authentication component to support NTLM supports passthrough");
|
||||
}
|
||||
else
|
||||
{
|
||||
return authComponent.getMD4HashedPassword(userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("No MD4 provider available");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NTLM mode - this is only what is set if one of the implementations provides support for that mode.
|
||||
*/
|
||||
public NTLMMode getNTLMMode()
|
||||
{
|
||||
if (ntlmMode != null)
|
||||
{
|
||||
switch (ntlmMode)
|
||||
{
|
||||
case NONE:
|
||||
return NTLMMode.NONE;
|
||||
case PASS_THROUGH:
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
|
||||
{
|
||||
return NTLMMode.PASS_THROUGH;
|
||||
}
|
||||
}
|
||||
return NTLMMode.NONE;
|
||||
case MD4_PROVIDER:
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
|
||||
{
|
||||
return NTLMMode.MD4_PROVIDER;
|
||||
}
|
||||
}
|
||||
return NTLMMode.NONE;
|
||||
default:
|
||||
return NTLMMode.NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.getNTLMMode() != NTLMMode.NONE)
|
||||
{
|
||||
return authComponent.getNTLMMode();
|
||||
}
|
||||
}
|
||||
return NTLMMode.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the system user name
|
||||
*/
|
||||
public String getSystemUserName()
|
||||
{
|
||||
return AuthenticationUtil.SYSTEM_USER_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* If any implementation supoprts guest then huest is allowed
|
||||
*/
|
||||
public boolean guestUserAuthenticationAllowed()
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
if (authComponent.guestUserAuthenticationAllowed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ste the current authentication
|
||||
*/
|
||||
public Authentication setCurrentAuthentication(Authentication authentication)
|
||||
{
|
||||
return AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current user - try all implementations - as some may check the user exists
|
||||
*/
|
||||
public Authentication setCurrentUser(String userName)
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
try
|
||||
{
|
||||
return authComponent.setCurrentUser(userName);
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
// Ignore and chain
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("Failed to set current user " + userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate as guest - try all in the cahin
|
||||
*/
|
||||
public Authentication setGuestUserAsCurrentUser()
|
||||
{
|
||||
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
|
||||
{
|
||||
try
|
||||
{
|
||||
return authComponent.setGuestUserAsCurrentUser();
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
// Ignore and chain
|
||||
}
|
||||
}
|
||||
throw new AuthenticationException("Guest authentication is not allowed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the system user
|
||||
*/
|
||||
public Authentication setSystemUserAsCurrentUser()
|
||||
{
|
||||
return setCurrentUser(getSystemUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get authentication components
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<AuthenticationComponent> getUsableAuthenticationComponents()
|
||||
{
|
||||
if (mutableAuthenticationComponent == null)
|
||||
{
|
||||
return authenticationComponents;
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList<AuthenticationComponent> services = new ArrayList<AuthenticationComponent>(authenticationComponents == null ? 1 : (authenticationComponents.size() + 1));
|
||||
services.add(mutableAuthenticationComponent);
|
||||
if (authenticationComponents != null)
|
||||
{
|
||||
services.addAll(authenticationComponents);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -72,7 +72,7 @@ public class SimpleAuthorityServiceTest extends TestCase
|
||||
authorityService = (AuthorityService) ctx.getBean("authorityService");
|
||||
pubAuthorityService = (AuthorityService) ctx.getBean("AuthorityService");
|
||||
personService = (PersonService) ctx.getBean("personService");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
|
||||
|
||||
this.authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
|
@@ -90,7 +90,7 @@ public class LockOwnerDynamicAuthorityTest extends TestCase
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
lockService = (LockService) ctx.getBean("lockService");
|
||||
permissionService = (PermissionService) ctx.getBean("permissionService");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
|
||||
|
||||
checkOutCheckInService = (CheckOutCheckInService) ctx.getBean("checkOutCheckInService");
|
||||
ownableService = (OwnableService) ctx.getBean("ownableService");
|
||||
|
@@ -102,7 +102,7 @@ public class AbstractPermissionTest extends BaseSpringTest
|
||||
authorityService = (AuthorityService) applicationContext.getBean("authorityService");
|
||||
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
|
||||
authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
|
||||
|
||||
|
||||
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.nanoTime());
|
||||
|
@@ -70,8 +70,8 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
public class PermissionServiceImpl implements PermissionServiceSPI, InitializingBean
|
||||
{
|
||||
|
||||
static SimplePermissionReference OLD_ALL_PERMISSIONS_REFERENCE = new SimplePermissionReference(QName.createQName(
|
||||
"", PermissionService.ALL_PERMISSIONS), PermissionService.ALL_PERMISSIONS);
|
||||
static SimplePermissionReference OLD_ALL_PERMISSIONS_REFERENCE = new SimplePermissionReference(QName.createQName("", PermissionService.ALL_PERMISSIONS),
|
||||
PermissionService.ALL_PERMISSIONS);
|
||||
|
||||
private static Log log = LogFactory.getLog(PermissionServiceImpl.class);
|
||||
|
||||
@@ -228,8 +228,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
throw new IllegalArgumentException("Property 'policyComponent' has not been set");
|
||||
}
|
||||
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"),
|
||||
ContentModel.TYPE_BASE, new JavaBehaviour(this, "onMoveNode"));
|
||||
policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"), ContentModel.TYPE_BASE, new JavaBehaviour(this, "onMoveNode"));
|
||||
|
||||
}
|
||||
|
||||
@@ -263,8 +262,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
NodePermissionEntry nodePremissionEntry = getSetPermissions(nodeRef);
|
||||
for (PermissionEntry pe : nodePremissionEntry.getPermissionEntries())
|
||||
{
|
||||
accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe
|
||||
.getAccessStatus(), pe.getAuthority()));
|
||||
accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe.getAccessStatus(), pe.getAuthority()));
|
||||
}
|
||||
return accessPermissions;
|
||||
}
|
||||
@@ -390,8 +388,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Permission <"
|
||||
+ perm + "> is " + (result ? "allowed" : "denied") + " for "
|
||||
+ authenticationComponent.getCurrentUserName() + " on node " + nodeService.getPath(nodeRef));
|
||||
+ perm + "> is " + (result ? "allowed" : "denied") + " for " + authenticationComponent.getCurrentUserName() + " on node " + nodeService.getPath(nodeRef));
|
||||
}
|
||||
|
||||
status = result ? AccessStatus.ALLOWED : AccessStatus.DENIED;
|
||||
@@ -649,21 +646,16 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
// Set the required node permissions
|
||||
if (required.equals(getPermissionReference(ALL_PERMISSIONS)))
|
||||
{
|
||||
nodeRequirements = modelDAO.getRequiredPermissions(
|
||||
getPermissionReference(PermissionService.FULL_CONTROL), typeQName, aspectQNames,
|
||||
RequiredPermission.On.NODE);
|
||||
nodeRequirements = modelDAO.getRequiredPermissions(getPermissionReference(PermissionService.FULL_CONTROL), typeQName, aspectQNames, RequiredPermission.On.NODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
|
||||
RequiredPermission.On.NODE);
|
||||
nodeRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.NODE);
|
||||
}
|
||||
|
||||
parentRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
|
||||
RequiredPermission.On.PARENT);
|
||||
parentRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.PARENT);
|
||||
|
||||
childrenRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
|
||||
RequiredPermission.On.CHILDREN);
|
||||
childrenRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.CHILDREN);
|
||||
|
||||
// Find all the permissions that grant the allowed permission
|
||||
// All permissions are treated specially.
|
||||
@@ -695,8 +687,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
* @param recursiveIn
|
||||
* @return
|
||||
*/
|
||||
boolean evaluate(Set<String> authorisations, NodeRef nodeRef, Set<Pair<String, PermissionReference>> denied,
|
||||
MutableBoolean recursiveIn)
|
||||
boolean evaluate(Set<String> authorisations, NodeRef nodeRef, Set<Pair<String, PermissionReference>> denied, MutableBoolean recursiveIn)
|
||||
{
|
||||
// Do we defer our required test to a parent (yes if not null)
|
||||
MutableBoolean recursiveOut = null;
|
||||
@@ -771,8 +762,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
if (pr.equals(required))
|
||||
{
|
||||
// Recursive permission
|
||||
success &= this.evaluate(authorisations, car.getParentRef(), locallyDenied,
|
||||
recursiveOut);
|
||||
success &= this.evaluate(authorisations, car.getParentRef(), locallyDenied, recursiveOut);
|
||||
if ((recursiveOut != null) && recursiveOut.getValue())
|
||||
{
|
||||
if (recursiveIn != null)
|
||||
@@ -848,8 +838,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
|
||||
}
|
||||
|
||||
public boolean hasSinglePermission(Set<String> authorisations, NodeRef nodeRef,
|
||||
Set<Pair<String, PermissionReference>> denied)
|
||||
public boolean hasSinglePermission(Set<String> authorisations, NodeRef nodeRef, Set<Pair<String, PermissionReference>> denied)
|
||||
{
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
@@ -974,8 +963,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
// All the sets that grant this permission must be
|
||||
// denied
|
||||
// Note that granters includes the orginal permission
|
||||
Set<PermissionReference> granters = modelDAO
|
||||
.getGrantingPermissions(pe.getPermissionReference());
|
||||
Set<PermissionReference> granters = modelDAO.getGrantingPermissions(pe.getPermissionReference());
|
||||
for (PermissionReference granter : granters)
|
||||
{
|
||||
deniedSet.add(new Pair<String, PermissionReference>(pe.getAuthority(), granter));
|
||||
@@ -991,8 +979,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
|
||||
// All permission excludes all permissions available for
|
||||
// the node.
|
||||
if (pe.getPermissionReference().equals(getAllPermissionReference())
|
||||
|| pe.getPermissionReference().equals(OLD_ALL_PERMISSIONS_REFERENCE))
|
||||
if (pe.getPermissionReference().equals(getAllPermissionReference()) || pe.getPermissionReference().equals(OLD_ALL_PERMISSIONS_REFERENCE))
|
||||
{
|
||||
for (PermissionReference deny : modelDAO.getAllPermissions(nodeRef))
|
||||
{
|
||||
@@ -1048,8 +1035,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
* the set of denied permissions/authority pais
|
||||
* @return
|
||||
*/
|
||||
private boolean isGranted(PermissionEntry pe, Set<String> authorisations,
|
||||
Set<Pair<String, PermissionReference>> denied)
|
||||
private boolean isGranted(PermissionEntry pe, Set<String> authorisations, Set<Pair<String, PermissionReference>> denied)
|
||||
{
|
||||
// If the permission entry denies then we just deny
|
||||
if (pe.isDenied())
|
||||
@@ -1059,16 +1045,41 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
|
||||
// The permission is allowed but we deny it as it is in the denied
|
||||
// set
|
||||
|
||||
if (denied != null)
|
||||
{
|
||||
Pair<String, PermissionReference> specific = new Pair<String, PermissionReference>(pe.getAuthority(),
|
||||
required);
|
||||
Pair<String, PermissionReference> specific = new Pair<String, PermissionReference>(pe.getAuthority(), required);
|
||||
if (denied.contains(specific))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// any deny denies
|
||||
|
||||
if (false)
|
||||
{
|
||||
if (denied != null)
|
||||
{
|
||||
for (String auth : authorisations)
|
||||
{
|
||||
Pair<String, PermissionReference> specific = new Pair<String, PermissionReference>(auth, required);
|
||||
if (denied.contains(specific))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (PermissionReference perm : granters)
|
||||
{
|
||||
specific = new Pair<String, PermissionReference>(auth, perm);
|
||||
if (denied.contains(specific))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the permission has a match in both the authorities and
|
||||
// granters list it is allowed
|
||||
// It applies to the current user and it is granted
|
||||
@@ -1124,8 +1135,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
return false;
|
||||
}
|
||||
Pair other = (Pair) o;
|
||||
return EqualsHelper.nullSafeEquals(this.getA(), other.getA())
|
||||
&& EqualsHelper.nullSafeEquals(this.getB(), other.getB());
|
||||
return EqualsHelper.nullSafeEquals(this.getA(), other.getA()) && EqualsHelper.nullSafeEquals(this.getB(), other.getB());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1167,15 +1177,13 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
return permissionsDaoComponent.getAllSetPermissions(authority);
|
||||
}
|
||||
|
||||
public Set<NodeRef> findNodesByAssignedPermissionForCurrentUser(String permission, boolean allow, boolean includeContainingAuthorities,
|
||||
boolean exactPermissionMatch)
|
||||
public Set<NodeRef> findNodesByAssignedPermissionForCurrentUser(String permission, boolean allow, boolean includeContainingAuthorities, boolean exactPermissionMatch)
|
||||
{
|
||||
String currentUser = authenticationComponent.getCurrentUserName();
|
||||
return findNodesByAssignedPermission(currentUser, permission, allow, includeContainingAuthorities, exactPermissionMatch);
|
||||
}
|
||||
|
||||
public Set<NodeRef> findNodesByAssignedPermission(String authority, String permission, boolean allow,
|
||||
boolean includeContainingAuthorities, boolean includeContainingPermissions)
|
||||
public Set<NodeRef> findNodesByAssignedPermission(String authority, String permission, boolean allow, boolean includeContainingAuthorities, boolean includeContainingPermissions)
|
||||
{
|
||||
// TODO: owned nodes and add owner rights ??
|
||||
// Does not include dynamic permissions (they would have to be done by query - e.g. owership and OWNER rights)
|
||||
|
@@ -149,7 +149,7 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
this.txnHelper = (RetryingTransactionHelper) applicationContext.getBean("retryingTransactionHelper");
|
||||
this.authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
|
||||
this.authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
|
||||
this.nodeArchiveService = (NodeArchiveService) applicationContext.getBean("nodeArchiveService");
|
||||
this.nodeService = (NodeService)applicationContext.getBean("nodeService");
|
||||
|
||||
|
@@ -5,7 +5,11 @@
|
||||
|
||||
# Namespaces
|
||||
namespace.prefix.cm=http://www.alfresco.org/model/content/1.0
|
||||
namespace.prefix.test=http://www.alfresco.org/model/test/1.0
|
||||
|
||||
# Mappings
|
||||
name=cm:title
|
||||
description=cm:description
|
||||
multi-value-text=test:multi-value-text
|
||||
multi-value-node=test:multi-value-node
|
||||
complex-node=test:complex-node
|
||||
|
@@ -8,3 +8,6 @@
|
||||
# Mappings
|
||||
name=/projectDescription/name/text()
|
||||
description=/projectDescription/comment/text()
|
||||
multi-value-text=/projectDescription/natures/nature/text()
|
||||
multi-value-node=/projectDescription/natures/nature
|
||||
complex-node=/projectDescription/natures
|
Reference in New Issue
Block a user