/**********************************************************************************
*
* $Id: RequireLocalAccountLegacyAuthenticationTest.java 129441 2013-09-06 22:55:50Z matthew@longsight.com $
*
***********************************************************************************
*
* Copyright (c) 2007, 2008 Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* 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.sakaiproject.user.impl.test;
import java.util.Collection;
import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.event.api.EventTrackingService;
import org.sakaiproject.memory.api.MemoryPermissionException;
import org.sakaiproject.test.SakaiKernelTestBase;
import org.sakaiproject.thread_local.api.ThreadLocalManager;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryProvider;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserEdit;
import org.sakaiproject.user.impl.DbUserService;
/**
* Some institutions want to have an authentication-only service that authenticates
* login IDs for local Sakai-maintained user records. (In other words, they do not
* want to provide user data externally; they only want control over authentication.)
*
* For 2.5.* development, the best way to do this is with the AuthenticatedUserProvider
* interface. This test code confirms backwards compatibility for legacy UserDirectoryProvider
* implementations which build this capability on the legacy
* authenticateUser(loginId, userEdit, password) method instead.
*
*/
public class RequireLocalAccountLegacyAuthenticationTest extends SakaiKernelTestBase {
private static Log log = LogFactory.getLog(RequireLocalAccountLegacyAuthenticationTest.class);
private UserDirectoryService userDirectoryService;
private static TestProvider userDirectoryProvider;
// This service is only used to clear out various caches to make sure
// we're fetching from the DB.
private ThreadLocalManager threadLocalManager;
private EventTrackingService eventTrackingService;
private static String LOCALLY_STORED_EID = "locallystoreduser";
private static String LOCALLY_STORED_PWD = "locallystoreduser-pwd";
private static String LOCALLY_STORED_EMAIL = "locallystoreduser@somewhere.edu";
private static String PROVIDED_EID = "provideduser";
private static String PROVIDED_PWD = "provideduser-pwd";
private static String PROVIDED_EMAIL = "provideduser@somewhere.edu";
/**
* A complete integration test run is a lot of overhead to take on for
* such a small suite of tests. But since the tests rely on being set up with
* specially tailored providers, there's not much choice....
*
* @throws Exception
*/
public static Test suite() {
TestSetup setup = new TestSetup(new TestSuite(RequireLocalAccountLegacyAuthenticationTest.class)) {
protected void setUp() throws Exception {
if (log.isDebugEnabled()) log.debug("starting setup");
try {
oneTimeSetup("disable_user_cache");
oneTimeSetupAfter();
} catch (Exception e) {
log.warn(e);
}
if (log.isDebugEnabled()) log.debug("finished setup");
}
protected void tearDown() throws Exception {
oneTimeTearDown();
}
};
return setup;
}
private static void oneTimeSetupAfter() throws Exception {
userDirectoryProvider = new TestProvider();
// This is a workaround until we can make it easier to load sakai.properties
// for specific integration tests.
DbUserService dbUserService = (DbUserService)getService(UserDirectoryService.class.getName());
dbUserService.setProvider(userDirectoryProvider);
User user = dbUserService.addUser(null, LOCALLY_STORED_EID, "J. " + LOCALLY_STORED_EID, "de " + LOCALLY_STORED_EID,
LOCALLY_STORED_EMAIL, null, "Guest", null);
log.debug("addUser eid=" + LOCALLY_STORED_EID + ", id=" + user.getId());
}
public void setUp() throws Exception {
log.debug("Setting up UserDirectoryServiceIntegrationTest");
userDirectoryService = (UserDirectoryService)getService(UserDirectoryService.class.getName());
threadLocalManager = (ThreadLocalManager)getService(ThreadLocalManager.class.getName());
eventTrackingService = (EventTrackingService)getService(EventTrackingService.class);
}
public void testWithProvidedUserRequired() throws Exception {
userDirectoryProvider.setRequireLocalAccount(true);
User user = userDirectoryService.authenticate(LOCALLY_STORED_EID, LOCALLY_STORED_PWD);
assertTrue(user.getEmail().equals(LOCALLY_STORED_EMAIL));
clearUserFromServiceCaches(user.getId());
user = userDirectoryService.authenticate(PROVIDED_EID, PROVIDED_PWD);
assertTrue(user == null);
}
public void testWithProvidedUserGood() throws Exception {
userDirectoryProvider.setRequireLocalAccount(false);
User user = userDirectoryService.authenticate(LOCALLY_STORED_EID, LOCALLY_STORED_PWD);
assertTrue(user.getEmail().equals(LOCALLY_STORED_EMAIL));
clearUserFromServiceCaches(user.getId());
user = userDirectoryService.authenticate(PROVIDED_EID, PROVIDED_PWD);
assertTrue(user.getEmail().equals(PROVIDED_EMAIL));
clearUserFromServiceCaches(user.getId());
}
private void clearUserFromServiceCaches(String userId) throws MemoryPermissionException {
((DbUserService)userDirectoryService).getIdEidCache().removeAll();
String ref = "/user/" + userId;
threadLocalManager.set(ref, null);
// Clear all caches, as it's a test its easier todo this than
// set up thread to be a super user which is needed for the MemoryService.resetCachers()
eventTrackingService.post(eventTrackingService.newEvent("memory.reset", "", true));
}
public static class TestProvider implements UserDirectoryProvider {
private boolean requireLocalAccount = false;
public boolean authenticateUser(String eid, UserEdit user, String password) {
return (password.equals(eid + "-pwd"));
}
public boolean authenticateWithProviderFirst(String loginId) {
return false;
}
public boolean findUserByEmail(UserEdit edit, String email) {
return false;
}
public boolean getUser(UserEdit user) {
if (requireLocalAccount) {
return false;
} else {
if (user.getEid().equals(PROVIDED_EID)) {
user.setEmail(PROVIDED_EMAIL);
return true;
} else {
return false;
}
}
}
@SuppressWarnings("rawtypes")
public void getUsers(Collection users) {
}
public void setRequireLocalAccount(boolean requireLocalAccount) {
this.requireLocalAccount = requireLocalAccount;
}
}
}