Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit e1e6508fec
1095 changed files with 230566 additions and 0 deletions

View File

@@ -0,0 +1,230 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import org.alfresco.error.AlfrescoRuntimeException;
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;
/**
* This class abstract the support required to set up and query the Acegi
* context for security enforcement.
*
* There are some simple default method implementations to support simple
* authentication.
*
* @author Andy Hind
*/
public abstract class AbstractAuthenticationComponent implements AuthenticationComponent
{
// Name of the system user
private static final String SYSTEM_USER_NAME = "System";
public AbstractAuthenticationComponent()
{
super();
}
/**
* Explicitly set the current user to be authenticated.
*
* @param userName
* String
* @return Authentication
*/
public Authentication setCurrentUser(String userName)
{
try
{
UserDetails ud = null;
if (userName.equals(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);
}
else
{
ud = getUserDetails(userName);
}
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud
.getAuthorities());
auth.setDetails(ud);
auth.setAuthenticated(true);
return setCurrentAuthentication(auth);
}
catch (net.sf.acegisecurity.AuthenticationException ae)
{
throw new AuthenticationException(ae.getMessage(), ae);
}
}
/**
* Default implementation that makes an ACEGI object on the fly
*
* @param userName
* @return
*/
protected UserDetails getUserDetails(String userName)
{
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
UserDetails ud = new User(userName, "", true, true, true, true, gas);
return ud;
}
/**
* Explicitly set the current authentication.
*
* @param authentication
* Authentication
*/
public Authentication setCurrentAuthentication(Authentication authentication)
{
Context context = ContextHolder.getContext();
SecureContext sc = null;
if ((context == null) || !(context instanceof SecureContext))
{
sc = new SecureContextImpl();
ContextHolder.setContext(sc);
}
else
{
sc = (SecureContext) context;
}
authentication.setAuthenticated(true);
sc.setAuthentication(authentication);
return authentication;
}
/**
* Get the current authentication context
*
* @return Authentication
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException
{
Context context = ContextHolder.getContext();
if ((context == null) || !(context instanceof SecureContext))
{
return null;
}
return ((SecureContext) context).getAuthentication();
}
/**
* Get the current user name.
*
* @return String
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException
{
Context context = ContextHolder.getContext();
if ((context == null) || !(context instanceof SecureContext))
{
return null;
}
return getUserName(((SecureContext) context).getAuthentication());
}
/**
* Get the current user name
*
* @param authentication
* Authentication
* @return String
*/
private String getUserName(Authentication authentication)
{
String username = authentication.getPrincipal().toString();
if (authentication.getPrincipal() instanceof UserDetails)
{
username = ((UserDetails) authentication.getPrincipal()).getUsername();
}
return username;
}
/**
* Set the system user as the current user.
*
* @return Authentication
*/
public Authentication setSystemUserAsCurrentUser()
{
return setCurrentUser(SYSTEM_USER_NAME);
}
/**
* Get the name of the system user
*
* @return String
*/
public String getSystemUserName()
{
return SYSTEM_USER_NAME;
}
/**
* Remove the current security information
*/
public void clearCurrentSecurityContext()
{
ContextHolder.setContext(null);
}
/**
* The default is not to support Authentication token base authentication
*/
public Authentication authenticate(Authentication token) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Authentication via token not supported");
}
/**
* The should only be supported if getNTLMMode() is NTLMMode.MD4_PROVIDER.
*/
public String getMD4HashedPassword(String userName)
{
throw new UnsupportedOperationException();
}
/**
* Get the NTML mode - none - supports MD4 hash to integrate - or it can
* asct as an NTLM authentication
*/
public NTLMMode getNTLMMode()
{
return NTLMMode.NONE;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationException;
import net.sf.acegisecurity.providers.AuthenticationProvider;
public class AuthenticatedAuthenticationPassthroughProvider implements AuthenticationProvider
{
public AuthenticatedAuthenticationPassthroughProvider()
{
super();
}
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
if (!supports(authentication.getClass())) {
return null;
}
if(authentication.isAuthenticated())
{
return authentication;
}
else
{
return null;
}
}
public boolean supports(Class authentication)
{
return (Authentication.class.isAssignableFrom(authentication));
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import net.sf.acegisecurity.Authentication;
public interface AuthenticationComponent
{
/**
* Authenticate
*
* @param userName
* @param password
* @throws AuthenticationException
*/
public void authenticate(String userName, char[] password) throws AuthenticationException;
/**
* Authenticate using a token
*
* @param token Authentication
* @return Authentication
* @throws AuthenticationException
*/
public Authentication authenticate(Authentication token) throws AuthenticationException;
/**
* Explicitly set the current user to be authenticated.
*/
public Authentication setCurrentUser(String userName);
/**
* Remove the current security information
*
*/
public void clearCurrentSecurityContext();
/**
* Explicitly set the current suthentication.
*/
public Authentication setCurrentAuthentication(Authentication authentication);
/**
*
* @return
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException;
/**
* Set the system user as the current user.
*
* @return
*/
public Authentication setSystemUserAsCurrentUser();
/**
* Get the name of the system user
*
* @return
*/
public String getSystemUserName();
/**
* Get the current user name.
*
* @return
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException;
/**
* Get the enum that describes NTLM integration
*
* @return
*/
public NTLMMode getNTLMMode();
/**
* Get the MD4 password hash, as required by NTLM based authentication methods.
*
* @param userName
* @return
*/
public String getMD4HashedPassword(String userName);
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import net.sf.acegisecurity.AuthenticationManager;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
{
private MutableAuthenticationDao authenticationDao;
AuthenticationManager authenticationManager;
public AuthenticationComponentImpl()
{
super();
}
/**
* IOC
*
* @param authenticationManager
*/
public void setAuthenticationManager(AuthenticationManager authenticationManager)
{
this.authenticationManager = authenticationManager;
}
/**
* IOC
*
* @param authenticationDao
*/
public void setAuthenticationDao(MutableAuthenticationDao authenticationDao)
{
this.authenticationDao = authenticationDao;
}
/**
* Authenticate
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
{
try
{
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userName,
new String(password));
authenticationManager.authenticate(authentication);
setCurrentUser(userName);
}
catch (net.sf.acegisecurity.AuthenticationException ae)
{
throw new AuthenticationException(ae.getMessage(), ae);
}
}
/**
* We actually have an acegi object so override the default method.
*/
protected UserDetails getUserDetails(String userName)
{
return (UserDetails) authenticationDao.loadUserByUsername(userName);
}
/**
* Get the password hash from the DAO
*/
public String getMD4HashedPassword(String userName)
{
return authenticationDao.getMD4HashedPassword(userName);
}
/**
* This implementation supported MD4 password hashes.
*/
public NTLMMode getNTLMMode()
{
return NTLMMode.MD4_PROVIDER;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Alfresco Authentication Exception and wrapper
*
* @author andyh
*
*/
public class AuthenticationException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = 3546647620128092466L;
public AuthenticationException(String msg)
{
super(msg);
}
public AuthenticationException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.service.cmr.security.AuthenticationService;
public class AuthenticationServiceImpl implements AuthenticationService
{
MutableAuthenticationDao authenticationDao;
AuthenticationComponent authenticationComponent;
TicketComponent ticketComponent;
PermissionServiceSPI permissionServiceSPI;
public AuthenticationServiceImpl()
{
super();
}
public void setAuthenticationDao(MutableAuthenticationDao authenticationDao)
{
this.authenticationDao = authenticationDao;
}
public void setTicketComponent(TicketComponent ticketComponent)
{
this.ticketComponent = ticketComponent;
}
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;
}
public void setPermissionServiceSPI(PermissionServiceSPI permissionServiceSPI)
{
this.permissionServiceSPI = permissionServiceSPI;
}
public void createAuthentication(String userName, char[] password) throws AuthenticationException
{
authenticationDao.createUser(userName, password);
}
public void updateAuthentication(String userName, char[] oldPassword, char[] newPassword)
throws AuthenticationException
{
authenticationDao.updateUser(userName, newPassword);
}
public void setAuthentication(String userName, char[] newPassword) throws AuthenticationException
{
authenticationDao.updateUser(userName, newPassword);
}
public void deleteAuthentication(String userName) throws AuthenticationException
{
authenticationDao.deleteUser(userName);
permissionServiceSPI.deletePermissions(authenticationDao.getUserNamesAreCaseSensitive() ? userName: userName.toLowerCase());
}
public boolean getAuthenticationEnabled(String userName) throws AuthenticationException
{
return authenticationDao.getEnabled(userName);
}
public void setAuthenticationEnabled(String userName, boolean enabled) throws AuthenticationException
{
authenticationDao.setEnabled(userName, enabled);
}
public void authenticate(String userName, char[] password) throws AuthenticationException
{
authenticationComponent.authenticate(userName, password);
}
public String getCurrentUserName() throws AuthenticationException
{
return authenticationComponent.getCurrentUserName();
}
public void invalidateUserSession(String userName) throws AuthenticationException
{
ticketComponent.invalidateTicketByUser(userName);
}
public void invalidateTicket(String ticket) throws AuthenticationException
{
ticketComponent.invalidateTicketById(ticket);
}
public void validate(String ticket) throws AuthenticationException
{
authenticationComponent.setCurrentUser(ticketComponent.validateTicket(ticket));
}
public String getCurrentTicket()
{
return ticketComponent.getTicket(getCurrentUserName());
}
public void clearCurrentSecurityContext()
{
authenticationComponent.clearCurrentSecurityContext();
}
public boolean isCurrentUserTheSystemUser()
{
String userName = getCurrentUserName();
if ((userName != null) && userName.equals(authenticationComponent.getSystemUserName()))
{
return true;
}
return false;
}
}

View File

@@ -0,0 +1,711 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import net.sf.acegisecurity.AccountExpiredException;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationManager;
import net.sf.acegisecurity.BadCredentialsException;
import net.sf.acegisecurity.CredentialsExpiredException;
import net.sf.acegisecurity.DisabledException;
import net.sf.acegisecurity.LockedException;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.SaltSource;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
public class AuthenticationTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private NodeService nodeService;
private SearchService searchService;
private NodeRef rootNodeRef;
private NodeRef systemNodeRef;
private NodeRef typesNodeRef;
private NodeRef personAndyNodeRef;
private DictionaryService dictionaryService;
private MD4PasswordEncoder passwordEncoder;
private MutableAuthenticationDao dao;
private AuthenticationManager authenticationManager;
private SaltSource saltSource;
private TicketComponent ticketComponent;
private AuthenticationService authenticationService;
private AuthenticationService pubAuthenticationService;
private AuthenticationComponent authenticationComponent;
private PermissionServiceSPI permissionServiceSPI;
private UserTransaction userTransaction;
public AuthenticationTest()
{
super();
}
public AuthenticationTest(String arg0)
{
super(arg0);
}
public void setUp() throws Exception
{
nodeService = (NodeService) ctx.getBean("nodeService");
searchService = (SearchService) ctx.getBean("searchService");
dictionaryService = (DictionaryService) ctx.getBean("dictionaryService");
passwordEncoder = (MD4PasswordEncoder) ctx.getBean("passwordEncoder");
ticketComponent = (TicketComponent) ctx.getBean("ticketComponent");
authenticationService = (AuthenticationService) ctx.getBean("authenticationService");
pubAuthenticationService = (AuthenticationService) ctx.getBean("AuthenticationService");
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
permissionServiceSPI = (PermissionServiceSPI) ctx.getBean("permissionService");
dao = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager");
saltSource = (SaltSource) ctx.getBean("saltSource");
TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE
.getLocalName());
userTransaction = transactionService.getUserTransaction();
userTransaction.begin();
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
rootNodeRef = nodeService.getRootNode(storeRef);
QName children = ContentModel.ASSOC_CHILDREN;
QName system = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "system");
QName container = ContentModel.TYPE_CONTAINER;
QName types = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "people");
systemNodeRef = nodeService.createNode(rootNodeRef, children, system, container).getChildRef();
typesNodeRef = nodeService.createNode(systemNodeRef, children, types, container).getChildRef();
Map<QName, Serializable> props = createPersonProperties("Andy");
personAndyNodeRef = nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props)
.getChildRef();
assertNotNull(personAndyNodeRef);
deleteAndy();
}
private void deleteAndy()
{
RepositoryAuthenticationDao dao = new RepositoryAuthenticationDao();
dao.setNodeService(nodeService);
dao.setSearchService(searchService);
dao.setDictionaryService(dictionaryService);
dao.setNamespaceService(getNamespacePrefixReolsver(""));
dao.setPasswordEncoder(passwordEncoder);
if(dao.getUserOrNull("andy") != null)
{
dao.deleteUser("andy");
}
}
@Override
protected void tearDown() throws Exception
{
userTransaction.rollback();
super.tearDown();
}
private Map<QName, Serializable> createPersonProperties(String userName)
{
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USERNAME, "Andy");
return properties;
}
public void testCreateAndyUserAndOtherCRUD() throws NoSuchAlgorithmException, UnsupportedEncodingException
{
RepositoryAuthenticationDao dao = new RepositoryAuthenticationDao();
dao.setNodeService(nodeService);
dao.setSearchService(searchService);
dao.setDictionaryService(dictionaryService);
dao.setNamespaceService(getNamespacePrefixReolsver(""));
dao.setPasswordEncoder(passwordEncoder);
dao.createUser("Andy", "cabbage".toCharArray());
assertNotNull(dao.getUserOrNull("Andy"));
byte[] decodedHash = passwordEncoder.decodeHash(dao.getMD4HashedPassword("Andy"));
byte[] testHash = MessageDigest.getInstance("MD4").digest("cabbage".getBytes("UnicodeLittleUnmarked"));
assertEquals(new String(decodedHash), new String(testHash));
UserDetails AndyDetails = (UserDetails) dao.loadUserByUsername("Andy");
assertNotNull(AndyDetails);
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", AndyDetails.getUsername());
// assertNotNull(dao.getSalt(AndyDetails));
assertTrue(AndyDetails.isAccountNonExpired());
assertTrue(AndyDetails.isAccountNonLocked());
assertTrue(AndyDetails.isCredentialsNonExpired());
assertTrue(AndyDetails.isEnabled());
assertNotSame("cabbage", AndyDetails.getPassword());
assertEquals(AndyDetails.getPassword(), passwordEncoder.encodePassword("cabbage", saltSource
.getSalt(AndyDetails)));
assertEquals(1, AndyDetails.getAuthorities().length);
// Object oldSalt = dao.getSalt(AndyDetails);
dao.updateUser("Andy", "carrot".toCharArray());
UserDetails newDetails = (UserDetails) dao.loadUserByUsername("Andy");
assertNotNull(newDetails);
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", newDetails.getUsername());
// assertNotNull(dao.getSalt(newDetails));
assertTrue(newDetails.isAccountNonExpired());
assertTrue(newDetails.isAccountNonLocked());
assertTrue(newDetails.isCredentialsNonExpired());
assertTrue(newDetails.isEnabled());
assertNotSame("carrot", newDetails.getPassword());
assertEquals(1, newDetails.getAuthorities().length);
assertNotSame(AndyDetails.getPassword(), newDetails.getPassword());
// assertNotSame(oldSalt, dao.getSalt(newDetails));
dao.deleteUser("Andy");
assertNull(dao.getUserOrNull("Andy"));
MessageDigest digester;
try
{
digester = MessageDigest.getInstance("MD4");
System.out.println("Digester from " + digester.getProvider());
}
catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("No digester");
}
}
public void testAuthentication()
{
dao.createUser("GUEST", "".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("GUEST", "");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.createUser("Andy", "squash".toCharArray());
token = new UsernamePasswordAuthenticationToken("Andy", "squash");
token.setAuthenticated(false);
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setEnabled("Andy", false);
try
{
result = authenticationManager.authenticate(token);
assertNotNull(result);
assertNotNull(null);
}
catch (DisabledException e)
{
// Expected
}
dao.setEnabled("Andy", true);
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setLocked("Andy", true);
try
{
result = authenticationManager.authenticate(token);
assertNotNull(result);
assertNotNull(null);
}
catch (LockedException e)
{
// Expected
}
dao.setLocked("Andy", false);
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setAccountExpires("Andy", true);
dao.setCredentialsExpire("Andy", true);
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setAccountExpiryDate("Andy", null);
dao.setCredentialsExpiryDate("Andy", null);
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setAccountExpiryDate("Andy", new Date(new Date().getTime() + 10000));
dao.setCredentialsExpiryDate("Andy", new Date(new Date().getTime() + 10000));
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setAccountExpiryDate("Andy", new Date(new Date().getTime() - 10000));
try
{
result = authenticationManager.authenticate(token);
assertNotNull(result);
assertNotNull(null);
}
catch (AccountExpiredException e)
{
// Expected
}
dao.setAccountExpiryDate("Andy", new Date(new Date().getTime() + 10000));
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.setCredentialsExpiryDate("Andy", new Date(new Date().getTime() - 10000));
try
{
result = authenticationManager.authenticate(token);
assertNotNull(result);
assertNotNull(null);
}
catch (CredentialsExpiredException e)
{
// Expected
}
dao.setCredentialsExpiryDate("Andy", new Date(new Date().getTime() + 10000));
result = authenticationManager.authenticate(token);
assertNotNull(result);
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testAuthenticationFailure()
{
dao.createUser("Andy", "squash".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "turnip");
token.setAuthenticated(false);
try
{
Authentication result = authenticationManager.authenticate(token);
assertNotNull(result);
assertNotNull(null);
}
catch (BadCredentialsException e)
{
// Expected
}
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testTicket()
{
dao.createUser("Andy", "ticket".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
result.setAuthenticated(true);
String ticket = ticketComponent.getTicket(getUserName(result));
String user = ticketComponent.validateTicket(ticket);
user = null;
try
{
user = ticketComponent.validateTicket("INVALID");
assertNotNull(null);
}
catch (AuthenticationException e)
{
assertNull(user);
}
ticketComponent.invalidateTicketById(ticket);
try
{
user = ticketComponent.validateTicket(ticket);
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testTicketRepeat()
{
InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
tc.setOneOff(false);
tc.setTicketsExpire(false);
tc.setValidDuration("P0D");
dao.createUser("Andy", "ticket".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
result.setAuthenticated(true);
String ticket = tc.getTicket(getUserName(result));
tc.validateTicket(ticket);
tc.validateTicket(ticket);
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testTicketOneOff()
{
InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
tc.setOneOff(true);
tc.setTicketsExpire(false);
tc.setValidDuration("P0D");
dao.createUser("Andy", "ticket".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
result.setAuthenticated(true);
String ticket = tc.getTicket(getUserName(result));
tc.validateTicket(ticket);
try
{
tc.validateTicket(ticket);
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testTicketExpires()
{
InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
tc.setOneOff(false);
tc.setTicketsExpire(true);
tc.setValidDuration("P5S");
dao.createUser("Andy", "ticket".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
result.setAuthenticated(true);
String ticket = tc.getTicket(getUserName(result));
tc.validateTicket(ticket);
tc.validateTicket(ticket);
tc.validateTicket(ticket);
synchronized (this)
{
try
{
wait(10000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
tc.validateTicket(ticket);
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testTicketDoesNotExpire()
{
InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
tc.setOneOff(false);
tc.setTicketsExpire(true);
tc.setValidDuration("P1D");
dao.createUser("Andy", "ticket".toCharArray());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
token.setAuthenticated(false);
Authentication result = authenticationManager.authenticate(token);
result.setAuthenticated(true);
String ticket = tc.getTicket(getUserName(result));
tc.validateTicket(ticket);
tc.validateTicket(ticket);
tc.validateTicket(ticket);
synchronized (this)
{
try
{
wait(10000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
tc.validateTicket(ticket);
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testAuthenticationService()
{
authenticationService.createAuthentication("GUEST", "".toCharArray());
authenticationService.authenticate("GUEST", "".toCharArray());
// create an authentication object e.g. the user
authenticationService.createAuthentication("Andy", "auth1".toCharArray());
// authenticate with this user details
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
// delete the user authentication object
authenticationService.clearCurrentSecurityContext();
authenticationService.deleteAuthentication("Andy");
// create a new authentication user object
authenticationService.createAuthentication("Andy", "auth2".toCharArray());
// change the password
authenticationService.setAuthentication("Andy", "auth3".toCharArray());
// authenticate again to assert password changed
authenticationService.authenticate("Andy", "auth3".toCharArray());
try
{
authenticationService.authenticate("Andy", "auth1".toCharArray());
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
try
{
authenticationService.authenticate("Andy", "auth2".toCharArray());
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
// get the ticket that represents the current user authentication
// instance
String ticket = authenticationService.getCurrentTicket();
// validate our ticket is still valid
authenticationService.validate(ticket);
// destroy the ticket instance
authenticationService.invalidateTicket(ticket);
try
{
authenticationService.validate(ticket);
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
// clear any context and check we are no longer authenticated
authenticationService.clearCurrentSecurityContext();
assertNull(authenticationService.getCurrentUserName());
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testPubAuthenticationService()
{
pubAuthenticationService.createAuthentication("GUEST", "".toCharArray());
pubAuthenticationService.authenticate("GUEST", "".toCharArray());
// create an authentication object e.g. the user
pubAuthenticationService.createAuthentication("Andy", "auth1".toCharArray());
// authenticate with this user details
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
// delete the user authentication object
pubAuthenticationService.clearCurrentSecurityContext();
pubAuthenticationService.deleteAuthentication("Andy");
// create a new authentication user object
pubAuthenticationService.createAuthentication("Andy", "auth2".toCharArray());
// change the password
pubAuthenticationService.setAuthentication("Andy", "auth3".toCharArray());
// authenticate again to assert password changed
pubAuthenticationService.authenticate("Andy", "auth3".toCharArray());
try
{
pubAuthenticationService.authenticate("Andy", "auth1".toCharArray());
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
try
{
pubAuthenticationService.authenticate("Andy", "auth2".toCharArray());
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
// get the ticket that represents the current user authentication
// instance
String ticket = pubAuthenticationService.getCurrentTicket();
// validate our ticket is still valid
pubAuthenticationService.validate(ticket);
// destroy the ticket instance
pubAuthenticationService.invalidateTicket(ticket);
try
{
pubAuthenticationService.validate(ticket);
assertNotNull(null);
}
catch (AuthenticationException e)
{
}
// clear any context and check we are no longer authenticated
pubAuthenticationService.clearCurrentSecurityContext();
assertNull(pubAuthenticationService.getCurrentUserName());
dao.deleteUser("Andy");
// assertNull(dao.getUserOrNull("Andy"));
}
public void testPassThroughLogin()
{
authenticationService.createAuthentication("Andy", "auth1".toCharArray());
authenticationComponent.setCurrentUser("Andy");
assertEquals(dao.getUserNamesAreCaseSensitive() ? "Andy" : "andy", authenticationService.getCurrentUserName());
//authenticationService.deleteAuthentication("andy");
}
private String getUserName(Authentication authentication)
{
String username = authentication.getPrincipal().toString();
if (authentication.getPrincipal() instanceof UserDetails)
{
username = ((UserDetails) authentication.getPrincipal()).getUsername();
}
return username;
}
private NamespacePrefixResolver getNamespacePrefixReolsver(String defaultURI)
{
DynamicNamespacePrefixResolver nspr = new DynamicNamespacePrefixResolver(null);
nspr.registerNamespace(NamespaceService.SYSTEM_MODEL_PREFIX, NamespaceService.SYSTEM_MODEL_1_0_URI);
nspr.registerNamespace(NamespaceService.CONTENT_MODEL_PREFIX, NamespaceService.CONTENT_MODEL_1_0_URI);
nspr.registerNamespace(ContentModel.USER_MODEL_PREFIX, ContentModel.USER_MODEL_URI);
nspr.registerNamespace("namespace", "namespace");
nspr.registerNamespace(NamespaceService.DEFAULT_PREFIX, defaultURI);
return nspr;
}
}

View File

@@ -0,0 +1,293 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.util.Date;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.dao.DataAccessException;
/**
* An authority DAO that has no implementation and should not be called.
*
* @author Andy Hind
*/
public class DefaultMutableAuthenticationDao implements MutableAuthenticationDao
{
/**
* Create a user with the given userName and password
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void createUser(String userName, char[] rawPassword) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Update a user's password.
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Delete a user.
*
* @param userName
* @throws AuthenticationException
*/
public void deleteUser(String userName) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Check is a user exists.
*
* @param userName
* @return
*/
public boolean userExists(String userName)
{
return true;
}
/**
* Get the store ref where user objects are persisted.
*
* @return
*/
public StoreRef getUserStoreRef()
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Enable/disable a user.
*
* @param userName
* @param enabled
*/
public void setEnabled(String userName, boolean enabled)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Getter for user enabled
*
* @param userName
* @return
*/
public boolean getEnabled(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Set if the account should expire
*
* @param userName
* @param expires
*/
public void setAccountExpires(String userName, boolean expires)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Does the account expire?
*
* @param userName
* @return
*/
public boolean getAccountExpires(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Has the account expired?
*
* @param userName
* @return
*/
public boolean getAccountHasExpired(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Set if the password expires.
*
* @param userName
* @param expires
*/
public void setCredentialsExpire(String userName, boolean expires)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Do the credentials for the user expire?
*
* @param userName
* @return
*/
public boolean getCredentialsExpire(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Have the credentials for the user expired?
*
* @param userName
* @return
*/
public boolean getCredentialsHaveExpired(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Set if the account is locked.
*
* @param userName
* @param locked
*/
public void setLocked(String userName, boolean locked)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Is the account locked?
*
* @param userName
* @return
*/
public boolean getAccountlocked(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Set the date on which the account expires
*
* @param userName
* @param exipryDate
*/
public void setAccountExpiryDate(String userName, Date exipryDate)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Get the date when this account expires.
*
* @param userName
* @return
*/
public Date getAccountExpiryDate(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Set the date when credentials expire.
*
* @param userName
* @param exipryDate
*/
public void setCredentialsExpiryDate(String userName, Date exipryDate)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Get the date when the credentials/password expire.
*
* @param userName
* @return
*/
public Date getCredentialsExpiryDate(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Get the MD4 password hash
*
* @param userName
* @return
*/
public String getMD4HashedPassword(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive()
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Return the user details for the specified user
*
* @param user String
* @return UserDetails
* @exception UsernameNotFoundException
* @exception DataAccessException
*/
public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException, DataAccessException
{
throw new AlfrescoRuntimeException("Not implemented");
}
/**
* Return salt for user
*
* @param user UserDetails
* @return Object
*/
public Object getSalt(UserDetails user)
{
throw new AlfrescoRuntimeException("Not implemented");
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.util.GUID;
public class InMemoryTicketComponentImpl implements TicketComponent
{
public static final String GRANTED_AUTHORITY_TICKET_PREFIX = "TICKET_";
private boolean ticketsExpire;
private Duration validDuration;
private boolean oneOff;
private HashMap<String, Ticket> tickets = new HashMap<String, Ticket>();
public InMemoryTicketComponentImpl()
{
super();
}
public String getTicket(String userName) throws AuthenticationException
{
Date expiryDate = null;
if (ticketsExpire)
{
expiryDate = Duration.add(new Date(), validDuration);
}
Ticket ticket = new Ticket(ticketsExpire, expiryDate, userName);
tickets.put(ticket.getTicketId(), ticket);
return GRANTED_AUTHORITY_TICKET_PREFIX + ticket.getTicketId();
}
public String validateTicket(String ticketString) throws AuthenticationException
{
if (ticketString.length() < GRANTED_AUTHORITY_TICKET_PREFIX.length())
{
throw new AuthenticationException(ticketString + " is an invalid ticket format");
}
String key = ticketString.substring(GRANTED_AUTHORITY_TICKET_PREFIX.length());
Ticket ticket = tickets.get(key);
if (ticket == null)
{
throw new AuthenticationException("Missing ticket for " + ticketString);
}
if (ticket.hasExpired())
{
throw new TicketExpiredException("Ticket expired for " + ticketString);
}
// TODO: Recheck the user details here
// TODO: Strengthen ticket as GUID is predicatble
if(oneOff)
{
tickets.remove(key);
}
return ticket.getUserName();
}
public void invalidateTicketById(String ticketString)
{
String key = ticketString.substring(GRANTED_AUTHORITY_TICKET_PREFIX.length());
tickets.remove(key);
}
public void invalidateTicketByUser(String userName)
{
Set<String> toRemove = new HashSet<String>();
for(String key: tickets.keySet())
{
Ticket ticket = tickets.get(key);
if(ticket.getUserName().equals(userName))
{
toRemove.add(ticket.getTicketId());
}
}
for(String id: toRemove)
{
tickets.remove(id);
}
}
private static class Ticket
{
private boolean expires;
private Date expiryDate;
private String userName;
private String ticketId;
Ticket(boolean expires, Date expiryDate, String userName)
{
this.expires = expires;
this.expiryDate = expiryDate;
this.userName = userName;
this.ticketId = GUID.generate();
}
/**
* Has the tick expired
*
* @return
*/
boolean hasExpired()
{
if (expires && (expiryDate != null) && (expiryDate.compareTo(new Date()) < 0))
{
return true;
}
else
{
return false;
}
}
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (!(o instanceof Ticket))
{
return false;
}
Ticket t = (Ticket) o;
return (this.expires == t.expires) && this.expiryDate.equals(t.expiryDate) && this.userName.equals(t.userName) && this.ticketId.equals(t.ticketId);
}
public int hashCode()
{
return ticketId.hashCode();
}
protected boolean getExpires()
{
return expires;
}
protected Date getExpiryDate()
{
return expiryDate;
}
protected String getTicketId()
{
return ticketId;
}
protected String getUserName()
{
return userName;
}
}
public void setOneOff(boolean oneOff)
{
this.oneOff = oneOff;
}
public void setTicketsExpire(boolean ticketsExpire)
{
this.ticketsExpire = ticketsExpire;
}
public void setValidDuration(String validDuration)
{
this.validDuration = new Duration(validDuration);
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
public interface MD4PasswordEncoder extends PasswordEncoder
{
/**
* Get the MD4 byte array
*
* @param encodedHash
* @return
*/
public byte[] decodeHash(String encodedHash);
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import net.sf.acegisecurity.providers.encoding.BaseDigestPasswordEncoder;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import cryptix.jce.provider.CryptixCrypto;
/**
* <p>
* MD4 implementation of PasswordEncoder.
* </p>
*
* <p>
* If a <code>null</code> password is presented, it will be treated as an
* empty <code>String</code> ("") password.
* </p>
*
* <P>
* As MD4 is a one-way hash, the salt can contain any characters.
* </p>
*/
public class MD4PasswordEncoderImpl extends BaseDigestPasswordEncoder implements MD4PasswordEncoder
{
static
{
try
{
MessageDigest.getInstance("MD4");
}
catch (NoSuchAlgorithmException e)
{
Security.addProvider(new CryptixCrypto());
}
}
public MD4PasswordEncoderImpl()
{
super();
// TODO Auto-generated constructor stub
}
// ~ Methods
// ================================================================
public boolean isPasswordValid(String encPass, String rawPass, Object salt)
{
String pass1 = "" + encPass;
String pass2 = encodeInternal(mergePasswordAndSalt(rawPass, salt, false));
return pass1.equals(pass2);
}
public String encodePassword(String rawPass, Object salt)
{
return encodeInternal(mergePasswordAndSalt(rawPass, salt, false));
}
private String encodeInternal(String input)
{
if (!getEncodeHashAsBase64())
{
return new String(Hex.encodeHex(md4(input)));
}
byte[] encoded = Base64.encodeBase64(md4(input));
try
{
return new String(encoded, "UTF8");
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException("UTF8 not supported!", e);
}
}
private byte[] md4(String input)
{
try
{
MessageDigest digester = MessageDigest.getInstance("MD4");
return digester.digest(input.getBytes("UnicodeLittleUnmarked"));
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException(e.getMessage(), e);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
public byte[] decodeHash(String encodedHash)
{
if (!getEncodeHashAsBase64())
{
try
{
return Hex.decodeHex(encodedHash.toCharArray());
}
catch (DecoderException e)
{
throw new RuntimeException("Unable to decode password hash");
}
}
else
{
return Base64.decodeBase64(encodedHash.getBytes());
}
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.util.Date;
import net.sf.acegisecurity.providers.dao.AuthenticationDao;
import net.sf.acegisecurity.providers.dao.SaltSource;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* A service provider interface to provide both acegi integration via AuthenticationDao and SaltSource
* and mutability support for user definitions.
*
* @author Andy Hind
*/
public interface MutableAuthenticationDao extends AuthenticationDao, SaltSource
{
/**
* Create a user with the given userName and password
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void createUser(String userName, char[] rawPassword) throws AuthenticationException;
/**
* Update a user's password.
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException;
/**
* Delete a user.
*
* @param userName
* @throws AuthenticationException
*/
public void deleteUser(String userName) throws AuthenticationException;
/**
* CHeck is a user exists.
*
* @param userName
* @return
*/
public boolean userExists(String userName);
/**
* Get the store ref where user objects are persisted.
*
* @return
*/
public StoreRef getUserStoreRef();
/**
* Enable/disable a user.
*
* @param userName
* @param enabled
*/
public void setEnabled(String userName, boolean enabled);
/**
* Getter for user enabled
*
* @param userName
* @return
*/
public boolean getEnabled(String userName);
/**
* Set if the account should expire
*
* @param userName
* @param expires
*/
public void setAccountExpires(String userName, boolean expires);
/**
* Does the account expire?
*
* @param userName
* @return
*/
public boolean getAccountExpires(String userName);
/**
* Has the account expired?
*
* @param userName
* @return
*/
public boolean getAccountHasExpired(String userName);
/**
* Set if the password expires.
*
* @param userName
* @param expires
*/
public void setCredentialsExpire(String userName, boolean expires);
/**
* Do the credentials for the user expire?
*
* @param userName
* @return
*/
public boolean getCredentialsExpire(String userName);
/**
* Have the credentials for the user expired?
*
* @param userName
* @return
*/
public boolean getCredentialsHaveExpired(String userName);
/**
* Set if the account is locked.
*
* @param userName
* @param locked
*/
public void setLocked(String userName, boolean locked);
/**
* Is the account locked?
*
* @param userName
* @return
*/
public boolean getAccountlocked(String userName);
/**
* Set the date on which the account expires
*
* @param userName
* @param exipryDate
*/
public void setAccountExpiryDate(String userName, Date exipryDate);
/**
* Get the date when this account expires.
*
* @param userName
* @return
*/
public Date getAccountExpiryDate(String userName);
/**
* Set the date when credentials expire.
*
* @param userName
* @param exipryDate
*/
public void setCredentialsExpiryDate(String userName, Date exipryDate);
/**
* Get the date when the credentials/password expire.
*
* @param userName
* @return
*/
public Date getCredentialsExpiryDate(String userName);
/**
* Get the MD4 password hash
*
* @param userName
* @return
*/
public String getMD4HashedPassword(String userName);
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive();
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
public enum NTLMMode
{
PASS_THROUGH, MD4_PROVIDER, NONE
}

View File

@@ -0,0 +1,510 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.User;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
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.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.springframework.dao.DataAccessException;
public class RepositoryAuthenticationDao implements MutableAuthenticationDao
{
private static final String SYSTEM_FOLDER = "/sys:system";
private static final String PEOPLE_FOLDER = SYSTEM_FOLDER + "/sys:people";
private NodeService nodeService;
private NamespacePrefixResolver namespacePrefixResolver;
private DictionaryService dictionaryService;
private SearchService searchService;
private PasswordEncoder passwordEncoder;
private StoreRef userStoreRef;
private boolean userNamesAreCaseSensitive;
public boolean getUserNamesAreCaseSensitive()
{
return userNamesAreCaseSensitive;
}
public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive)
{
this.userNamesAreCaseSensitive = userNamesAreCaseSensitive;
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
public void setNamespaceService(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setPasswordEncoder(PasswordEncoder passwordEncoder)
{
this.passwordEncoder = passwordEncoder;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public UserDetails loadUserByUsername(String caseSensitiveUserName) throws UsernameNotFoundException, DataAccessException
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName: caseSensitiveUserName.toLowerCase();
NodeRef userRef = getUserOrNull(userNamesAreCaseSensitive ? userName: userName.toLowerCase());
if (userRef == null)
{
throw new UsernameNotFoundException("Could not find user by userName: " + caseSensitiveUserName);
}
Map<QName, Serializable> properties = nodeService.getProperties(userRef);
String password = DefaultTypeConverter.INSTANCE.convert(String.class, properties
.get(ContentModel.PROP_PASSWORD));
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
UserDetails ud = new User(userName, password, getEnabled(userName), !getAccountHasExpired(userName),
!getCredentialsHaveExpired(userName), !getAccountlocked(userName), gas);
return ud;
}
public NodeRef getUserOrNull(String caseSensitiveUserName)
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName: caseSensitiveUserName.toLowerCase();
NodeRef rootNode = nodeService.getRootNode(getUserStoreRef());
QueryParameterDefinition[] defs = new QueryParameterDefinition[1];
DataTypeDefinition text = dictionaryService.getDataType(DataTypeDefinition.TEXT);
defs[0] = new QueryParameterDefImpl(QName.createQName("usr", "var", namespacePrefixResolver), text, true,
userName);
List<NodeRef> results = searchService.selectNodes(rootNode, PEOPLE_FOLDER
+ "/usr:user[@usr:username = $usr:var ]", defs, namespacePrefixResolver, false);
if (results.size() != 1)
{
return null;
}
return results.get(0);
}
public void createUser(String caseSensitiveUserName, char[] rawPassword) throws AuthenticationException
{
String userName = userNamesAreCaseSensitive ? caseSensitiveUserName: caseSensitiveUserName.toLowerCase();
NodeRef userRef = getUserOrNull(userName);
if (userRef != null)
{
throw new AuthenticationException("User already exists: " + userName);
}
NodeRef typesNode = getOrCreateTypeLocation();
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USER_USERNAME, userName);
String salt = null; // GUID.generate();
properties.put(ContentModel.PROP_SALT, salt);
properties.put(ContentModel.PROP_PASSWORD, passwordEncoder.encodePassword(new String(rawPassword), salt));
properties.put(ContentModel.PROP_ACCOUNT_EXPIRES, Boolean.valueOf(false));
properties.put(ContentModel.PROP_CREDENTIALS_EXPIRE, Boolean.valueOf(false));
properties.put(ContentModel.PROP_ENABLED, Boolean.valueOf(true));
properties.put(ContentModel.PROP_ACCOUNT_LOCKED, Boolean.valueOf(false));
nodeService.createNode(typesNode, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_USER, ContentModel.TYPE_USER,
properties);
}
private NodeRef getOrCreateTypeLocation()
{
NodeRef rootNode = nodeService.getRootNode(getUserStoreRef());
List<ChildAssociationRef> results = nodeService.getChildAssocs(
rootNode,
RegexQNamePattern.MATCH_ALL,
QName.createQName("sys", "system", namespacePrefixResolver));
NodeRef sysNode = null;
if (results.size() == 0)
{
sysNode = nodeService.createNode(rootNode, ContentModel.ASSOC_CHILDREN,
QName.createQName("sys", "system", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
.getChildRef();
}
else
{
sysNode = results.get(0).getChildRef();
}
results = nodeService.getChildAssocs(
sysNode,
RegexQNamePattern.MATCH_ALL,
QName.createQName("sys", "people", namespacePrefixResolver));
NodeRef typesNode = null;
if (results.size() == 0)
{
typesNode = nodeService.createNode(sysNode, ContentModel.ASSOC_CHILDREN,
QName.createQName("sys", "people", namespacePrefixResolver), ContentModel.TYPE_CONTAINER)
.getChildRef();
}
else
{
typesNode = results.get(0).getChildRef();
}
return typesNode;
}
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException
{
NodeRef userRef = getUserOrNull(userName);
if (userRef == null)
{
throw new AuthenticationException("User does not exist: " + userName);
}
Map<QName, Serializable> properties = nodeService.getProperties(userRef);
String salt = null; // GUID.generate();
properties.remove(ContentModel.PROP_SALT);
properties.put(ContentModel.PROP_SALT, salt);
properties.remove(ContentModel.PROP_PASSWORD);
properties.put(ContentModel.PROP_PASSWORD, passwordEncoder.encodePassword(new String(rawPassword), salt));
nodeService.setProperties(userRef, properties);
}
public void deleteUser(String userName) throws AuthenticationException
{
NodeRef userRef = getUserOrNull(userName);
if (userRef == null)
{
throw new AuthenticationException("User does not exist: " + userName);
}
nodeService.deleteNode(userRef);
}
public synchronized StoreRef getUserStoreRef()
{
if (userStoreRef == null)
{
userStoreRef = new StoreRef("user", "alfrescoUserStore");
}
if (!nodeService.exists(userStoreRef))
{
nodeService.createStore(userStoreRef.getProtocol(), userStoreRef.getIdentifier());
}
return userStoreRef;
}
public Object getSalt(UserDetails userDetails)
{
// NodeRef userRef = getUserOrNull(userDetails.getUsername());
// if (userRef == null)
// {
// throw new UsernameNotFoundException("Could not find user by userName:
// " + userDetails.getUsername());
// }
//
// Map<QName, Serializable> properties =
// nodeService.getProperties(userRef);
//
// String salt = DefaultTypeConverter.INSTANCE.convert(String.class,
// properties.get(QName.createQName("usr", "salt",
// namespacePrefixResolver)));
//
// return salt;
return null;
}
public boolean userExists(String userName)
{
return (getUserOrNull(userName) != null);
}
public boolean getAccountExpires(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
Serializable ser = nodeService.getProperty(userNode, ContentModel.PROP_ACCOUNT_EXPIRES);
if (ser == null)
{
return false;
}
else
{
return DefaultTypeConverter.INSTANCE.booleanValue(ser);
}
}
public Date getAccountExpiryDate(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return null;
}
if (DefaultTypeConverter.INSTANCE.booleanValue(nodeService.getProperty(userNode,
ContentModel.PROP_ACCOUNT_EXPIRES)))
{
return DefaultTypeConverter.INSTANCE.convert(Date.class, nodeService.getProperty(userNode,
ContentModel.PROP_ACCOUNT_EXPIRY_DATE));
}
else
{
return null;
}
}
public boolean getAccountHasExpired(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
if (DefaultTypeConverter.INSTANCE.booleanValue(nodeService.getProperty(userNode,
ContentModel.PROP_ACCOUNT_EXPIRES)))
{
Date date = DefaultTypeConverter.INSTANCE.convert(Date.class, nodeService.getProperty(userNode,
ContentModel.PROP_ACCOUNT_EXPIRY_DATE));
if (date == null)
{
return false;
}
else
{
return (date.compareTo(new Date()) < 1);
}
}
else
{
return false;
}
}
public boolean getAccountlocked(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
Serializable ser = nodeService.getProperty(userNode, ContentModel.PROP_ACCOUNT_LOCKED);
if (ser == null)
{
return false;
}
else
{
return DefaultTypeConverter.INSTANCE.booleanValue(ser);
}
}
public boolean getCredentialsExpire(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
Serializable ser = nodeService.getProperty(userNode, ContentModel.PROP_CREDENTIALS_EXPIRE);
if (ser == null)
{
return false;
}
else
{
return DefaultTypeConverter.INSTANCE.booleanValue(ser);
}
}
public Date getCredentialsExpiryDate(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return null;
}
if (DefaultTypeConverter.INSTANCE.booleanValue(nodeService.getProperty(userNode,
ContentModel.PROP_CREDENTIALS_EXPIRE)))
{
return DefaultTypeConverter.INSTANCE.convert(Date.class, nodeService.getProperty(userNode,
ContentModel.PROP_CREDENTIALS_EXPIRY_DATE));
}
else
{
return null;
}
}
public boolean getCredentialsHaveExpired(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
if (DefaultTypeConverter.INSTANCE.booleanValue(nodeService.getProperty(userNode,
ContentModel.PROP_CREDENTIALS_EXPIRE)))
{
Date date = DefaultTypeConverter.INSTANCE.convert(Date.class, nodeService.getProperty(userNode,
ContentModel.PROP_CREDENTIALS_EXPIRY_DATE));
if (date == null)
{
return false;
}
else
{
return (date.compareTo(new Date()) < 1);
}
}
else
{
return false;
}
}
public boolean getEnabled(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return false;
}
Serializable ser = nodeService.getProperty(userNode, ContentModel.PROP_ENABLED);
if (ser == null)
{
return true;
}
else
{
return DefaultTypeConverter.INSTANCE.booleanValue(ser);
}
}
public void setAccountExpires(String userName, boolean expires)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_ACCOUNT_EXPIRES, Boolean.valueOf(expires));
}
public void setAccountExpiryDate(String userName, Date exipryDate)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_ACCOUNT_EXPIRY_DATE, exipryDate);
}
public void setCredentialsExpire(String userName, boolean expires)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_CREDENTIALS_EXPIRE, Boolean.valueOf(expires));
}
public void setCredentialsExpiryDate(String userName, Date exipryDate)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_CREDENTIALS_EXPIRY_DATE, exipryDate);
}
public void setEnabled(String userName, boolean enabled)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_ENABLED, Boolean.valueOf(enabled));
}
public void setLocked(String userName, boolean locked)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
throw new AuthenticationException("User not found: " + userName);
}
nodeService.setProperty(userNode, ContentModel.PROP_ACCOUNT_LOCKED, Boolean.valueOf(locked));
}
public String getMD4HashedPassword(String userName)
{
NodeRef userNode = getUserOrNull(userName);
if (userNode == null)
{
return null;
}
else
{
String password = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(userNode,
ContentModel.PROP_PASSWORD));
return password;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
/**
* Manage authentication tickets
*
* @author andyh
*
*/
public interface TicketComponent
{
/**
* Register a ticket
*
* @param authentication
* @return
* @throws AuthenticationException
*/
public String getTicket(String userName) throws AuthenticationException;
/**
* Check that a certificate is valid and can be used in place of a login.
*
* Tickets may be rejected because:
* <ol>
* <li> The certificate does not exists
* <li> The status of the user has changed
* <ol>
* <li> The user is locked
* <li> The account has expired
* <li> The credentials have expired
* <li> The account is disabled
* </ol>
* <li> The ticket may have expired
* <ol>
* <li> The ticked my be invalid by timed expiry
* <li> An attemp to reuse a once only ticket
* </ol>
* </ol>
*
* @param authentication
* @return
* @throws AuthenticationException
*/
public String validateTicket(String ticket) throws AuthenticationException;
public void invalidateTicketById(String ticket);
public void invalidateTicketByUser(String userName);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.security.authentication;
public class TicketExpiredException extends AuthenticationException
{
/**
*
*/
private static final long serialVersionUID = 3257572801815590969L;
public TicketExpiredException(String msg)
{
super(msg);
}
public TicketExpiredException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,90 @@
<model name="usr:usermodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Alfresco User Model</description>
<author>Alfresco</author>
<published>2005-08-16</published>
<version>0.1</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/user/1.0" prefix="usr"/>
</namespaces>
<types>
<type name="usr:authority">
<title>Alfreco Authority Abstract Type</title>
<parent>sys:base</parent>
</type>
<type name="usr:user">
<title>Alfresco User Type</title>
<parent>usr:authority</parent>
<properties>
<property name="usr:username">
<type>d:text</type>
</property>
<property name="usr:password">
<type>d:text</type>
</property>
<property name="usr:enabled">
<type>d:boolean</type>
</property>
<property name="usr:accountExpires">
<type>d:boolean</type>
</property>
<property name="usr:accountExpiryDate">
<type>d:datetime</type>
</property>
<property name="usr:credentialsExpire">
<type>d:boolean</type>
</property>
<property name="usr:credentialsExpiryDate">
<type>d:datetime</type>
</property>
<property name="usr:accountLocked">
<type>d:boolean</type>
</property>
<property name="usr:salt">
<type>d:text</type>
</property>
</properties>
</type>
<type name="usr:authorityContainer">
<title>Alfresco Authority Type</title>
<parent>usr:authority</parent>
<properties>
<property name="usr:authorityName">
<type>d:text</type>
</property>
<property name="usr:members">
<type>d:text</type>
<multiple>true</multiple>
</property>
</properties>
<associations>
<child-association name="usr:member">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>usr:authority</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
<duplicate>false</duplicate>
</child-association>
</associations>
</type>
</types>
</model>