package org.pac4j.mongo.profile.service; import com.mongodb.MongoClient; import org.bson.types.ObjectId; import org.junit.*; import org.pac4j.core.exception.*; import org.pac4j.core.profile.CommonProfile; import org.pac4j.core.profile.service.AbstractProfileService; import org.pac4j.core.util.TestsConstants; import org.pac4j.core.credentials.UsernamePasswordCredentials; import org.pac4j.core.util.TestsHelper; import org.pac4j.mongo.credentials.authenticator.MongoAuthenticator; import org.pac4j.mongo.profile.MongoProfile; import org.pac4j.mongo.test.tools.MongoServer; import java.util.List; import java.util.Map; import static org.junit.Assert.*; /** * Tests the {@link MongoAuthenticator}. * * @author Jerome Leleu * @since 1.8.0 */ public final class MongoProfileServiceIT implements TestsConstants { private static final int PORT = 37017; private static final String MONGO_ID = "mongoId"; private static final String MONGO_LINKEDID = "mongoLinkedId"; private static final String MONGO_LINKEDID2 = "mongoLinkedId2"; private static final String MONGO_USER = "mongoUser"; private static final String MONGO_PASS = "mongoPass"; private static final String MONGO_PASS2 = "mongoPass2"; private final MongoServer mongoServer = new MongoServer(); @Before public void setUp() { mongoServer.start(PORT); } @After public void tearDown() { mongoServer.stop(); } @Test public void testNullPasswordEncoder() { final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), FIRSTNAME); authenticator.setPasswordEncoder(null); TestsHelper.expectException(() -> authenticator.init(null), TechnicalException.class, "passwordEncoder cannot be null"); } @Test public void testNullMongoClient() { final MongoAuthenticator authenticator = new MongoAuthenticator(null, FIRSTNAME, MongoServer.PASSWORD_ENCODER); TestsHelper.expectException(() -> authenticator.init(null), TechnicalException.class, "mongoClient cannot be null"); } @Test public void testNullDatabase() { final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), FIRSTNAME, MongoServer.PASSWORD_ENCODER); authenticator.setUsersDatabase(null); TestsHelper.expectException(() -> authenticator.init(null), TechnicalException.class, "usersDatabase cannot be blank"); } @Test public void testNullCollection() { final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), FIRSTNAME, MongoServer.PASSWORD_ENCODER); authenticator.setUsersCollection(null); TestsHelper.expectException(() -> authenticator.init(null), TechnicalException.class, "usersCollection cannot be blank"); } @Test public void testNullUsername() { final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), FIRSTNAME, MongoServer.PASSWORD_ENCODER); authenticator.setUsernameAttribute(null); TestsHelper.expectException(() -> authenticator.init(null), TechnicalException.class, "usernameAttribute cannot be blank"); } @Test public void testNullPassword() { final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), FIRSTNAME, MongoServer.PASSWORD_ENCODER); authenticator.setPasswordAttribute(null); final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(GOOD_USERNAME, PASSWORD, CLIENT_NAME); TestsHelper.expectException(() -> authenticator.validate(credentials, null), TechnicalException.class, "passwordAttribute cannot be blank"); } private MongoClient getClient() { return new MongoClient("localhost", PORT); } private UsernamePasswordCredentials login(final String username, final String password, final String attribute) throws HttpAction, CredentialsException{ final MongoAuthenticator authenticator = new MongoAuthenticator(getClient(), attribute); authenticator.setPasswordEncoder(MongoServer.PASSWORD_ENCODER); final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password, CLIENT_NAME); authenticator.validate(credentials, null); return credentials; } @Test public void testGoodUsernameAttribute() throws HttpAction, CredentialsException { final UsernamePasswordCredentials credentials = login(GOOD_USERNAME, PASSWORD, FIRSTNAME); final CommonProfile profile = credentials.getUserProfile(); assertNotNull(profile); assertTrue(profile instanceof MongoProfile); final MongoProfile dbProfile = (MongoProfile) profile; assertEquals(GOOD_USERNAME, dbProfile.getId()); assertEquals(FIRSTNAME_VALUE, dbProfile.getAttribute(FIRSTNAME)); } @Test public void testGoodUsernameNoAttribute() throws HttpAction, CredentialsException { final UsernamePasswordCredentials credentials = login(GOOD_USERNAME, PASSWORD, ""); final CommonProfile profile = credentials.getUserProfile(); assertNotNull(profile); assertTrue(profile instanceof MongoProfile); final MongoProfile dbProfile = (MongoProfile) profile; assertEquals(GOOD_USERNAME, dbProfile.getId()); assertNull(dbProfile.getAttribute(FIRSTNAME)); } @Test public void testMultipleUsername() throws HttpAction, CredentialsException { TestsHelper.expectException(() -> login(MULTIPLE_USERNAME, PASSWORD, ""), MultipleAccountsFoundException.class, "Too many accounts found for: misagh"); } @Test public void testBadUsername() throws HttpAction, CredentialsException { TestsHelper.expectException(() -> login(BAD_USERNAME, PASSWORD, ""), AccountNotFoundException.class, "No account found for: michael"); } @Test public void testBadPassword() throws HttpAction, CredentialsException { TestsHelper.expectException(() ->login(GOOD_USERNAME, PASSWORD + "bad", ""), BadCredentialsException.class, "Bad credentials for: jle"); } @Test public void testCreateUpdateFindDelete() throws HttpAction, CredentialsException { final ObjectId objectId = new ObjectId(); final MongoProfile profile = new MongoProfile(); profile.setId(MONGO_ID); profile.setLinkedId(MONGO_LINKEDID); profile.addAttribute(USERNAME, MONGO_USER); profile.addAttribute(FIRSTNAME, objectId); final MongoProfileService mongoProfileService = new MongoProfileService(getClient()); mongoProfileService.setPasswordEncoder(MongoServer.PASSWORD_ENCODER); // create mongoProfileService.create(profile, MONGO_PASS); // check credentials final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(MONGO_USER, MONGO_PASS, CLIENT_NAME); mongoProfileService.validate(credentials, null); final CommonProfile profile1 = credentials.getUserProfile(); assertNotNull(profile1); // check data final List<Map<String, Object>> results = getData(mongoProfileService, MONGO_ID); assertEquals(1, results.size()); final Map<String, Object> result = results.get(0); assertEquals(6, result.size()); assertEquals(MONGO_ID, result.get(ID)); assertEquals(MONGO_LINKEDID, result.get(AbstractProfileService.LINKEDID)); assertNotNull(result.get(AbstractProfileService.SERIALIZED_PROFILE)); assertTrue(MongoServer.PASSWORD_ENCODER.matches(MONGO_PASS, (String) result.get(PASSWORD))); assertEquals(MONGO_USER, result.get(USERNAME)); // findById final MongoProfile profile2 = mongoProfileService.findByLinkedId(MONGO_LINKEDID); assertEquals(MONGO_ID, profile2.getId()); assertEquals(MONGO_LINKEDID, profile2.getLinkedId()); assertEquals(MONGO_USER, profile2.getUsername()); assertEquals(objectId, profile2.getAttribute(FIRSTNAME)); assertEquals(2, profile2.getAttributes().size()); // update profile.setLinkedId(MONGO_LINKEDID2); mongoProfileService.update(profile, MONGO_PASS2); final List<Map<String, Object>> results2 = getData(mongoProfileService, MONGO_ID); assertEquals(1, results2.size()); final Map<String, Object> result2 = results2.get(0); assertEquals(6, result2.size()); assertEquals(MONGO_ID, result2.get(ID)); assertEquals(MONGO_LINKEDID2, result2.get(AbstractProfileService.LINKEDID)); assertNotNull(result2.get(AbstractProfileService.SERIALIZED_PROFILE)); assertTrue(MongoServer.PASSWORD_ENCODER.matches(MONGO_PASS2, (String) result2.get(PASSWORD))); assertEquals(MONGO_USER, result2.get(USERNAME)); // remove mongoProfileService.remove(profile); final List<Map<String, Object>> results3 = getData(mongoProfileService, MONGO_ID); assertEquals(0, results3.size()); } private List<Map<String, Object>> getData(final MongoProfileService service, final String id) { return service.read(null, ID, id); } }