// Copyright 2012 Google Inc.
//
// Licensed under the Apache 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.apache.org/licenses/LICENSE-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 com.google.enterprise.connector.notes;
import com.google.common.collect.Lists;
import com.google.enterprise.connector.notes.client.NotesACL;
import com.google.enterprise.connector.notes.client.NotesACLEntry;
import com.google.enterprise.connector.notes.client.NotesDocument;
import com.google.enterprise.connector.notes.client.NotesItem;
import com.google.enterprise.connector.notes.client.NotesSession;
import com.google.enterprise.connector.notes.client.NotesView;
import com.google.enterprise.connector.notes.client.mock.NotesACLEntryMock;
import com.google.enterprise.connector.notes.client.mock.NotesACLMock;
import com.google.enterprise.connector.notes.client.mock.NotesDatabaseMock;
import com.google.enterprise.connector.notes.client.mock.NotesDocumentMock;
import com.google.enterprise.connector.notes.client.mock.NotesItemMock;
import com.google.enterprise.connector.notes.client.mock.NotesSessionMock;
import com.google.enterprise.connector.notes.client.mock.SessionFactoryMock;
import com.google.enterprise.connector.spi.RepositoryException;
import com.google.enterprise.connector.util.database.JdbcDatabase;
import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class NotesUserGroupManagerTest extends TestCase {
private static NotesConnector connector;
private static SessionFactoryMock factory;
private static NotesConnectorSession connectorSession;
private static NotesSession session;
private static NotesDatabaseMock namesDatabase;
private static final int groupCount = 8;
private static final int userCount = 11;
public static Test suite() {
return new TestSetup(
new TestSuite(NotesUserGroupManagerTest.class)) {
@Override protected void setUp() throws Exception {
connector = NotesConnectorTest.getConnector();
factory = (SessionFactoryMock) connector.getSessionFactory();
NotesConnectorSessionTest.configureFactoryForSession(factory);
connectorSession = (NotesConnectorSession) connector.login();
session = connectorSession.createNotesSession();
namesDatabase = (NotesDatabaseMock) session.getDatabase(
connectorSession.getServer(), connectorSession.getDirectory());
// Create helper views.
namesDatabase.setViewFields("notesnamelookup", NCCONST.PITM_FULLNAME);
namesDatabase.setViewFields("grouplookup", NCCONST.GITM_LISTNAME);
NotesUserGroupManager userGroupManager =
new NotesUserGroupManager(connectorSession);
addNotesUser(namesDatabase, "cn=Anakin Skywalker/ou=Tests/o=Tests",
"anakin");
addNotesUser(namesDatabase, "cn=Ahsoka Tano/ou=Tests/o=Tests",
"ahsoka");
addNotesUser(namesDatabase, "cn=Obi-Wan Kenobi/ou=Tests/o=Tests",
"kenobi");
addNotesUser(namesDatabase, "cn=Mace Windu/ou=Tests/o=Tests",
"mace");
addNotesUser(namesDatabase, "cn=Yoda/ou=Tests/o=Tests",
"yoda");
addNotesUser(namesDatabase, "cn=Chancellor Palpatine/ou=Tests/o=Tests",
"palpatine");
addNotesUser(namesDatabase, "cn=Count Dooku/ou=Tests/o=Tests",
"dooku");
addNotesUser(namesDatabase, "cn=Padme Amidala/ou=Tests/o=Tests",
"padme");
addNotesUser(namesDatabase, "cn=Rex/ou=Tests/o=Tests", "rex");
addNotesUser(namesDatabase, "cn=Cody/ou=Tests/o=Tests", "cody");
addNotesUser(namesDatabase, "cn=Echo/ou=Tests/o=Tests", "echo");
addNotesGroup(namesDatabase, "Jedi", "Masters", "Padawan Learners");
addNotesGroup(namesDatabase, "Masters",
"CN=Anakin Skywalker/OU=Tests/O=Tests",
"CN=Obi-Wan Kenobi/OU=Tests/O=Tests",
"CN=Mace Windu/OU=Tests/O=Tests",
"CN=Yoda/OU=Tests/O=Tests",
"*/ou=Tests/o=Tests");
addNotesGroup(namesDatabase, "Padawan Learners",
"cn=ahsoka tano/ou=tests/o=tests");
addNotesGroup(namesDatabase, "Separatists",
"cn=count dooku/ou=tests/o=tests");
addNotesGroup(namesDatabase, "Senators",
"cn=padme amidala/ou=tests/o=tests");
addNotesGroup(namesDatabase, "Clones",
"cn=rex/ou=tests/o=tests",
"cn=cody/ou=tests/o=tests",
"cn=echo/ou=tests/o=tests");
addNotesGroup(namesDatabase, "Good Guys", "Jedi", "Senators", "Clones");
addNotesGroup(namesDatabase, "Bad Guys", "Separatists",
"cn=chancellor palpatine/ou=tests/o=tests");
addNotesGroup(namesDatabase, "cn=west coast/ou=west/o=test",
"cn=chancellor palpatine/ou=tests/o=tests");
// Create some databases with ACLs to be crawled.
// First, create the connector database records, then
// create the database. For the purposes of
// NotesUserGroupManager, we only need a database, no
// documents.
NotesDatabaseMock configDatabase = (NotesDatabaseMock) session
.getDatabase(connectorSession.getServer(),
connectorSession.getDatabase());
NotesDocumentMock databaseDocument = new NotesDocumentMock();
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_DBNAME,
"type", NotesItem.TEXT, "values", "JediTrainingManuals.nsf"));
databaseDocument.addItem(new NotesItemMock("name",
NCCONST.DITM_REPLICAID, "type", NotesItem.TEXT,
"values", "jtmreplicaid0123"));
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_SERVER,
"type", NotesItem.TEXT, "values", "JediServer"));
configDatabase.addDocument(databaseDocument, NCCONST.VIEWDATABASES);
databaseDocument = new NotesDocumentMock();
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_DBNAME,
"type", NotesItem.TEXT, "values", "SenateExpenseReports.nsf"));
databaseDocument.addItem(new NotesItemMock("name",
NCCONST.DITM_REPLICAID, "type", NotesItem.TEXT,
"values", "serreplicaid0123"));
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_SERVER,
"type", NotesItem.TEXT, "values", "SenateServer"));
configDatabase.addDocument(databaseDocument, NCCONST.VIEWDATABASES);
databaseDocument = new NotesDocumentMock();
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_DBNAME,
"type", NotesItem.TEXT, "values", "EvilSeparatistPlots.nsf"));
databaseDocument.addItem(new NotesItemMock("name",
NCCONST.DITM_REPLICAID, "type", NotesItem.TEXT,
"values", "espreplicaid0123"));
databaseDocument.addItem(new NotesItemMock("name", NCCONST.DITM_SERVER,
"type", NotesItem.TEXT, "values", "SenateServer"));
configDatabase.addDocument(databaseDocument, NCCONST.VIEWDATABASES);
NotesDatabaseMock notesDatabase = new NotesDatabaseMock(
"JediServer", "JediTrainingManuals.nsf", "jtmreplicaid0123");
((NotesSessionMock) session).addDatabase(notesDatabase);
NotesACLMock acl = new NotesACLMock();
acl.addAclEntry(new NotesACLEntryMock(
"cn=Ahsoka Tano/ou=Tests/o=Tests", NotesACLEntry.TYPE_PERSON,
NotesACL.LEVEL_READER, "[student]"));
acl.addAclEntry(new NotesACLEntryMock(
"cn=Anakin Skywalker/ou=Tests/o=Tests", NotesACLEntry.TYPE_PERSON,
NotesACL.LEVEL_AUTHOR, "[tacticsexpert]"));
acl.addAclEntry(new NotesACLEntryMock(
"cn=Yoda/ou=Tests/o=Tests", NotesACLEntry.TYPE_PERSON,
NotesACL.LEVEL_AUTHOR, "[philosopher]"));
acl.addAclEntry(new NotesACLEntryMock("masters",
NotesACLEntry.TYPE_PERSON_GROUP, NotesACL.LEVEL_AUTHOR,
"[holderofopinions]", "[duplicategroupname]"));
acl.addAclEntry(new NotesACLEntryMock("bad guys",
NotesACLEntry.TYPE_PERSON_GROUP, NotesACL.LEVEL_NOACCESS));
notesDatabase.setACL(acl);
notesDatabase = new NotesDatabaseMock(
"SenateServer", "SenateExpenseReports.nsf", "serreplicaid0123");
((NotesSessionMock) session).addDatabase(notesDatabase);
acl = new NotesACLMock();
acl.addAclEntry(new NotesACLEntryMock(
"cn=Chancellor Palpatine/ou=Tests/o=Tests",
NotesACLEntry.TYPE_PERSON, NotesACL.LEVEL_READER,
"[removablerole]"));
acl.addAclEntry(new NotesACLEntryMock("senators",
NotesACLEntry.TYPE_PERSON_GROUP, NotesACL.LEVEL_AUTHOR,
"[creator]", "[duplicategroupname]"));
notesDatabase.setACL(acl);
notesDatabase = new NotesDatabaseMock(
"SenateServer", "EvilSeparatistPlots.nsf", "espreplicaid0123");
((NotesSessionMock) session).addDatabase(notesDatabase);
acl = new NotesACLMock();
acl.addAclEntry(new NotesACLEntryMock(
"cn=Chancellor Palpatine/ou=Tests/o=Tests",
NotesACLEntry.TYPE_PERSON, NotesACL.LEVEL_MANAGER,
"[evilmastermind]"));
acl.addAclEntry(new NotesACLEntryMock(
"Count Dooku", // Test a short name in the ACL
NotesACLEntry.TYPE_PERSON, NotesACL.LEVEL_AUTHOR,
"[henchman]"));
acl.addAclEntry(new NotesACLEntryMock(
"bad guys", NotesACLEntry.TYPE_PERSON_GROUP,
NotesACL.LEVEL_READER));
acl.addAclEntry(new NotesACLEntryMock("jedi",
NotesACLEntry.TYPE_PERSON_GROUP,
NotesACL.LEVEL_READER, "[reader]"));
notesDatabase.setACL(acl);
try {
userGroupManager.setUpResources(true);
userGroupManager.clearTables(userGroupManager.getConnection());
} finally {
userGroupManager.releaseResources();
}
}
@Override protected void tearDown() throws Exception {
connector.shutdown();
}
};
}
// Used by this class.
private static NotesDocumentMock addNotesUser(
NotesDatabaseMock namesDatabase, String notesname, String gsaname)
throws Exception {
return addNotesUser(connectorSession, namesDatabase, notesname, gsaname);
}
// Used by other test classes.
static NotesDocumentMock addNotesUser(NotesConnectorSession connectorSession,
NotesDatabaseMock namesDatabase, String notesname, String gsaname)
throws Exception {
NotesDocumentMock notesPerson = new NotesDocumentMock();
notesPerson.addItem(new NotesItemMock("name", "unid",
"type", NotesItem.TEXT, "values", gsaname));
notesPerson.addItem(new NotesItemMock("name", NCCONST.NCITM_UNID,
"type", NotesItem.TEXT, "values", gsaname));
notesPerson.addItem(new NotesItemMock("name", NCCONST.PITM_FULLNAME,
"type", NotesItem.TEXT, "values", notesname));
notesPerson.addItem(new NotesItemMock("name", "HTTPPassword",
"type", NotesItem.TEXT, "values", "password"));
notesPerson.addItem(new NotesItemMock("name", NCCONST.ITMFORM,
"type", NotesItem.TEXT, "values", NCCONST.DIRFORM_PERSON));
notesPerson.addItem(new NotesItemMock("name",
"evaluate_" + connectorSession.getUserNameFormula(),
"type", NotesItem.TEXT, "values", gsaname));
notesPerson.addItem(new NotesItemMock("name",
"evaluate_" + connectorSession.getUserSelectionFormula(),
"type", NotesItem.TEXT, "values", 1.0));
namesDatabase.addDocument(notesPerson, NCCONST.DIRVIEW_USERS,
NCCONST.DIRVIEW_PEOPLEGROUPFLAT, NCCONST.DIRVIEW_SERVERACCESS,
NCCONST.DIRVIEW_VIMUSERS, "notesnamelookup");
return notesPerson;
}
static NotesDocumentMock addNotesGroup(
NotesDatabaseMock namesDatabase, String groupName,
String... members) throws Exception {
NotesDocumentMock notesGroup = new NotesDocumentMock();
notesGroup.addItem(new NotesItemMock("name", "unid",
"type", NotesItem.TEXT, "values", groupName));
notesGroup.addItem(new NotesItemMock("name", NCCONST.NCITM_UNID,
"type", NotesItem.TEXT, "values", groupName));
notesGroup.addItem(new NotesItemMock("name", NCCONST.GITM_LISTNAME,
"type", NotesItem.TEXT, "values", groupName));
notesGroup.addItem(new NotesItemMock("name", NCCONST.ITMFORM,
"type", NotesItem.TEXT, "values", NCCONST.DIRFORM_GROUP));
notesGroup.addItem(new NotesItemMock("name", NCCONST.GITM_GROUPTYPE,
"type", NotesItem.TEXT, "values",
NCCONST.DIR_ACCESSCONTROLGROUPTYPES));
if (members != null && members.length > 0) {
notesGroup.addItem(new NotesItemMock("name", NCCONST.GITM_MEMBERS,
"type", NotesItem.TEXT, "values", members));
}
namesDatabase.addDocument(notesGroup,
NCCONST.DIRVIEW_PEOPLEGROUPFLAT, NCCONST.DIRVIEW_SERVERACCESS,
NCCONST.DIRVIEW_VIMGROUPS, "grouplookup");
return notesGroup;
}
private NotesUserGroupManager userGroupManager;
private Connection conn;
private HashMap<String, Long> groups = new HashMap<String, Long>();
private HashMap<Long, HashSet<Long>> groupChildren =
new HashMap<Long, HashSet<Long>>();
private HashMap<String, Long> notesUserNames = new HashMap<String, Long>();
private HashMap<String, Long> gsaUserNames = new HashMap<String, Long>();
private HashMap<Long, HashSet<Long>> userGroups =
new HashMap<Long, HashSet<Long>>();
private HashMap<String, Long> roles = new HashMap<String, Long>();
private HashMap<Long, HashSet<Long>> userRoles =
new HashMap<Long, HashSet<Long>>();
private HashMap<Long, HashSet<Long>> groupRoles =
new HashMap<Long, HashSet<Long>>();
private List<String> userUnids;
private List<String> groupUnids;
public NotesUserGroupManagerTest() {
super();
}
@Override
protected void setUp() throws Exception {
userGroupManager = new NotesUserGroupManager(connectorSession);
userGroupManager.setUpResources(true);
conn = userGroupManager.getConnection();
userGroupManager.initializeUserCache();
userUnids =
userGroupManager.getViewUnids(namesDatabase, NCCONST.DIRVIEW_VIMUSERS);
groupUnids =
userGroupManager.getViewUnids(namesDatabase, NCCONST.DIRVIEW_VIMGROUPS);
}
@Override
protected void tearDown() {
userGroupManager.clearTables(conn);
userGroupManager.releaseResources();
}
public void testDropTables() throws Exception {
JdbcDatabase jdbcDatabase =
connectorSession.getConnector().getJdbcDatabase();
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.roleTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userGroupsTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userRolesTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupRolesTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupChildrenTableName, null));
userGroupManager.dropTables();
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.userTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.groupTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.roleTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.userGroupsTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.userRolesTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.groupRolesTableName, null));
assertFalse(jdbcDatabase.verifyTableExists(
userGroupManager.groupChildrenTableName, null));
// Re-initialize cache after this test for the tearDown.clearTables
userGroupManager.initializeUserCache();
}
public void testInitializeUserCache() throws Exception {
JdbcDatabase jdbcDatabase =
connectorSession.getConnector().getJdbcDatabase();
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.roleTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userGroupsTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.userRolesTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupRolesTableName, null));
assertTrue(jdbcDatabase.verifyTableExists(
userGroupManager.groupChildrenTableName, null));
}
public void testNestedGroups() throws Exception {
setUpUsers();
assertGroupExists("jedi");
assertGroupHasChild("jedi", "masters");
assertUserHasGroup("echo", "masters");
}
public void testInheritedRoles() throws Exception {
String testRole = "espreplicaid0123/[reader]";
setUpRoles();
assertRoleExists(testRole);
assertGroupHasRole("jedi", testRole);
assertUserHasRole("echo", testRole);
}
public void testUpdateGroups() throws Exception {
setUpGroups();
assertEquals(groups.toString(), groupCount + 2, groups.size());
HashSet<Long> children = groupChildren.get(groups.get("good guys"));
assertEquals(6, children.size());
assertGroupHasChild("good guys", "jedi");
assertGroupHasChild("good guys", "masters");
assertGroupHasChild("good guys", "padawan learners");
assertGroupHasChild("good guys", "senators");
assertGroupHasChild("good guys", "clones");
children = groupChildren.get(groups.get("jedi"));
assertEquals(3, children.size());
assertGroupHasChild("jedi", "masters");
assertGroupHasChild("jedi", "padawan learners");
}
public void testSkipUpdateGroups() throws Exception {
String nonExistentId = "group123";
assertTrue(groupUnids.size() > 1);
groupUnids.add(2, nonExistentId);
assertEquals("Groups' map is not empty", 0, groups.size());
setUpGroups();
assertTrue("Groups are not populated from groupUnids", groups.size() > 0);
for (String unid : groupUnids) {
NotesDocument doc;
try {
doc = namesDatabase.getDocumentByUNID(unid);
assertEquals(doc.getItemValueString(NCCONST.NCITM_UNID), unid);
String groupName = doc.getItemValueString(NCCONST.GITM_LISTNAME);
assertGroupExists(groupName.toLowerCase());
} catch (RepositoryException e) {
assertTrue(e.getMessage().contains(nonExistentId));
}
}
}
public void testUpdateUsers() throws Exception {
setUpUsers();
assertEquals(userCount, notesUserNames.size());
assertUserHasGroup("ahsoka", "padawan learners");
assertUserHasGroup("ahsoka", "jedi");
assertUserHasGroup("ahsoka", "good guys");
assertUserHasGroup("ahsoka", "ou=tests/o=tests");
assertUserHasGroup("ahsoka", "o=tests");
assertUserHasGroup("palpatine", "bad guys");
assertUserHasGroup("palpatine", "ou=tests/o=tests");
assertUserHasGroup("palpatine", "o=tests");
}
public void testSkipUpdateUsers() throws Exception {
String nonExistentId = "user123";
assertTrue(userUnids.size() > 1);
userUnids.add(2, nonExistentId);
assertEquals("Users'map is not empty", 0, notesUserNames.size());
setUpUsers();
assertTrue("Users are not populated from userUnids",
notesUserNames.size() > 0);
for (String unid : userUnids) {
NotesDocument doc;
try {
doc = namesDatabase.getDocumentByUNID(unid);
assertEquals(doc.getItemValueString(NCCONST.NCITM_UNID), unid);
String notesName = doc.getItemValueString(NCCONST.PITM_FULLNAME);
assertTrue(notesName + " user doesn't exist",
notesUserNames.containsKey(notesName.toLowerCase()));
} catch (RepositoryException e) {
assertTrue(e.getMessage().contains(nonExistentId));
}
}
}
public void testUpdateRoles() throws Exception {
setUpRoles();
assertUserHasRole("palpatine", "espreplicaid0123/[evilmastermind]");
assertUserHasRole("dooku", "espreplicaid0123/[henchman]");
assertGroupHasRole("senators", "serreplicaid0123/[creator]");
// Same role name in different databases.
Long id1 = assertRoleExists("serreplicaid0123/[duplicategroupname]");
Long id2 = assertRoleExists("jtmreplicaid0123/[duplicategroupname]");
assertTrue(id1 != id2);
}
public void testRolesAclEntryDeleted() throws Exception {
setUpRoles();
assertUserHasRole("palpatine", "serreplicaid0123/[removablerole]");
// Modify one of the previously-created ACLs (we don't
// actually have editing support, so just recreate it here).
NotesDatabaseMock notesDatabase = (NotesDatabaseMock) session.getDatabase(
"SenateServer", "SenateExpenseReports.nsf");
NotesACLMock originalAcl = (NotesACLMock) notesDatabase.getACL();
try {
NotesACLMock acl = new NotesACLMock();
// Remove Palpatine from this database's ACL
acl.addAclEntry(new NotesACLEntryMock("senators",
NotesACLEntry.TYPE_PERSON_GROUP, NotesACL.LEVEL_AUTHOR,
"[creator]", "[duplicategroupname]"));
notesDatabase.setACL(acl);
setUpRoles();
assertRoleDoesNotExist("serreplicaid0123/[removablerole]");
assertUserDoesNotHaveRole("palpatine",
"serreplicaid0123/[removablerole]");
} finally {
notesDatabase.setACL(originalAcl);
}
}
public void testDeleteRolesForDatabase() throws Exception {
setUpRoles();
assertRoleExists("serreplicaid0123/[removablerole]");
HashSet<String> currentDatabases = new HashSet<String>();
currentDatabases.add("jtmreplicaid0123");
currentDatabases.add("espreplicaid0123");
userGroupManager.checkDatabaseDeletions(currentDatabases);
getRoleData();
assertRoleDoesNotExist("serreplicaid0123/[removablerole]");
}
public void testUserDeletions() throws Exception {
setUpRoles();
// Find the Notes doc for the user to be deleted. Use a
// user with a role.
NotesView nameView = namesDatabase.getView("notesnamelookup");
NotesDocumentMock doc = (NotesDocumentMock) nameView.getDocumentByKey(
"cn=Yoda/ou=Tests/o=Tests");
assertNotNull("No yoda", doc);
try {
Long id = assertUserExists("yoda");
assertUserHasGroup("yoda", "jedi");
assertUserHasRole("yoda", "jtmreplicaid0123/[philosopher]");
// Delete the user from the Notes database. Call
// checkUserDeletions and verify that the user was removed
// from the user cache.
doc.remove(true);
userGroupManager.checkUserDeletions();
getGroupData();
getUserData();
getRoleData();
assertUserDoesNotExist("yoda");
assertNull("user still has groups", userGroups.get(id));
assertNull("user still has roles", userRoles.get(id));
} finally {
addNotesUser(namesDatabase, "cn=Yoda/ou=Tests/o=Tests",
"yoda");
}
}
public void testGroupDeletions() throws Exception {
userGroupManager.updateGroups(groupUnids);
userGroupManager.updateUsers(userUnids);
// Find the Notes doc for the group to be deleted.
// Use a group with children.
NotesView nameView = namesDatabase.getView("grouplookup");
NotesDocumentMock doc = (NotesDocumentMock) nameView.getDocumentByKey(
"jedi");
assertNotNull("No jedi", doc);
// Test group with canonical name
NotesDocumentMock doc2 = (NotesDocumentMock) nameView.getDocumentByKey(
"cn=west coast/ou=west/o=test");
assertNotNull("cn=west coast/ou=west/o=test", doc2);
try {
// Get the current user/group data and verify that the group is there.
getGroupData();
getUserData();
Long id = groups.get("jedi");
assertNotNull("missing test group before test", id);
// Delete the group from the Notes database. Call
// checkGroupDeletions and verify that the group was removed
// from the group cache.
doc.remove(true);
doc2.remove(true);
userGroupManager.checkGroupDeletions();
getGroupData();
getUserData();
assertGroupDoesNotExist("jedi");
assertGroupDoesNotExist("cn=west coast/ou=west/o=test");
assertNull("group still has child groups", groupChildren.get(id));
for (Long userId : userGroups.keySet()) {
HashSet<Long> g = userGroups.get(userId);
assertFalse(g.contains(id));
}
} finally {
addNotesGroup(namesDatabase, "jedi", "masters", "padawan learners");
}
}
public void testUserNoLongerSelected() throws Exception {
userGroupManager.updateGroups(groupUnids);
userGroupManager.updateUsers(userUnids);
// Find the Notes doc for the user to be deleted.
NotesView nameView = namesDatabase.getView("notesnamelookup");
NotesDocumentMock doc = (NotesDocumentMock) nameView.getDocumentByKey(
"cn=Anakin Skywalker/ou=Tests/o=Tests");
assertNotNull("No anakin", doc);
try {
// Get the current user/group data and verify that the user is there.
getGroupData();
getUserData();
Long id = assertUserExists("anakin");
assertNotNull("user has no groups", userGroups.get(id));
// Change the result of the user selection formula. Call
// checkUserDeletions and verify that the user was removed
// from the user cache.
doc.replaceItemValue(
"evaluate_" + connectorSession.getUserSelectionFormula(),
new NotesItemMock("name",
"evaluate_" + connectorSession.getUserSelectionFormula(),
"type", NotesItem.TEXT, "values", 0.0));
userGroupManager.checkUserDeletions();
getGroupData();
getUserData();
assertUserDoesNotExist("anakin");
assertNull("user still has groups", userGroups.get(id));
} finally {
doc.replaceItemValue(
"evaluate_" + connectorSession.getUserSelectionFormula(),
new NotesItemMock("name",
"evaluate_" + connectorSession.getUserSelectionFormula(),
"type", NotesItem.TEXT, "values", 1.0));
}
}
public void testChangeUserGsaName() throws Exception {
setUpRoles();
// Find the Notes doc for the user to be changed.
NotesView nameView = namesDatabase.getView("notesnamelookup");
NotesDocumentMock doc = (NotesDocumentMock) nameView.getDocumentByKey(
"cn=Obi-Wan Kenobi/ou=Tests/o=Tests");
assertNotNull("No kenobi", doc);
try {
assertUserExists("kenobi");
assertUserDoesNotExist("ben");
// Change the user name.
doc.replaceItemValue(
"evaluate_" + connectorSession.getUserNameFormula(),
new NotesItemMock("name",
"evaluate_" + connectorSession.getUserNameFormula(),
"type", NotesItem.TEXT, "values", "ben"));
setUpRoles();
assertUserExists("ben");
assertUserDoesNotExist("kenobi");
} finally {
doc.replaceItemValue(
"evaluate_" + connectorSession.getUserNameFormula(),
new NotesItemMock("name",
"evaluate_" + connectorSession.getUserNameFormula(),
"type", NotesItem.TEXT, "values", "kenobi"));
}
}
public void testRunningRepeatedly() throws Exception {
userGroupManager.clearTables(conn);
for (int i = 0; i < 10; i++) {
userGroupManager.updateUsersGroups(true);
getGroupData();
getUserData();
assertEquals(groups.toString(), groupCount + 5, groups.size());
assertEquals(userCount, notesUserNames.size());
}
}
public void testGetUser() throws Exception {
setUpRoles();
NotesUserGroupManager.User user =
userGroupManager.getUserByGsaName("yoda");
assertYodaUserProperties(user);
user = userGroupManager.getUserByNotesName("cn=yoda/ou=tests/o=tests");
assertYodaUserProperties(user);
}
private void assertYodaUserProperties(
NotesUserGroupManager.User user) throws Exception {
assertEquals("yoda", user.getGsaName());
assertEquals("cn=yoda/ou=tests/o=tests", user.getNotesName());
Collection<String> groups = user.getGroups();
assertEquals("size of: " + groups, 9, groups.size());
assertTrue("good guys", groups.contains("good guys"));
assertTrue("jedi", groups.contains("jedi"));
assertTrue("masters", groups.contains("masters"));
assertTrue("o=tests", groups.contains("o=tests"));
assertTrue("*/o=tests", groups.contains("*/o=tests"));
assertTrue("ou=tests/o=tests", groups.contains("ou=tests/o=tests"));
assertTrue("*/ou=tests/o=tests", groups.contains("*/ou=tests/o=tests"));
Collection<String> roles = user.getRoles();
assertEquals("size of: " + roles, 4, roles.size());
assertTrue("jtmreplicaid0123/[philosopher]",
roles.contains("jtmreplicaid0123/[philosopher]"));
assertTrue("jtmreplicaid0123/[holderofopinions]",
roles.contains("jtmreplicaid0123/[holderofopinions]"));
assertTrue("jtmreplicaid0123/[duplicategroupname]",
roles.contains("jtmreplicaid0123/[duplicategroupname]"));
roles = user.getRolesByDatabase("jtmreplicaid0123");
assertEquals("size of: " + roles, 3, roles.size());
assertTrue("[philosopher]", roles.contains("[philosopher]"));
assertTrue("[holderofopinions]", roles.contains("[holderofopinions]"));
assertTrue("[duplicategroupname]", roles.contains("[duplicategroupname]"));
}
public void testGetUserByGsaNameNoRoles() throws Exception {
setUpRoles();
NotesUserGroupManager.User user =
userGroupManager.getUserByGsaName("cody");
assertEquals("cody", user.getGsaName());
assertEquals("cn=cody/ou=tests/o=tests", user.getNotesName());
Collection<String> groups = user.getGroups();
assertEquals("size of: " + groups, 10, groups.size());
assertTrue("*", groups.contains("*"));
assertTrue("good guys", groups.contains("good guys"));
assertTrue("jedi", groups.contains("clones"));
assertTrue("o=tests", groups.contains("o=tests"));
assertTrue("*/o=tests", groups.contains("*/o=tests"));
assertTrue("ou=tests/o=tests", groups.contains("ou=tests/o=tests"));
assertTrue("*/ou=tests/o=tests", groups.contains("*/ou=tests/o=tests"));
Collection<String> roles = user.getRoles();
assertEquals("size of: " + roles, 3, roles.size());
assertTrue(roles.contains("espreplicaid0123/[reader]"));
assertTrue(roles.contains("jtmreplicaid0123/[holderofopinions]"));
assertTrue(roles.contains("jtmreplicaid0123/[duplicategroupname]"));
}
public void testMapNotesNamesToGsaNames() throws Exception {
setUpUsers();
Collection<String> gsaNames = userGroupManager.mapNotesNamesToGsaNames(
session,
Lists.newArrayList("cn=Padme Amidala/ou=Tests/o=Tests",
"cn=Count Dooku/ou=Tests/o=Tests",
"cn=Ahsoka Tano/ou=Tests/o=Tests"), false);
assertEquals(3, gsaNames.size());
assertTrue(gsaNames.contains("padme"));
assertTrue(gsaNames.contains("dooku"));
assertTrue(gsaNames.contains("ahsoka"));
}
public void testMapNotesNamesToGsaNamesCommonNames() throws Exception {
setUpUsers();
Collection<String> gsaNames = userGroupManager.mapNotesNamesToGsaNames(
session,
Lists.newArrayList("Padme Amidala",
"Count Dooku",
"Ahsoka Tano"), false);
assertEquals(3, gsaNames.size());
assertTrue(gsaNames.contains("padme"));
assertTrue(gsaNames.contains("dooku"));
assertTrue(gsaNames.contains("ahsoka"));
}
public void testMapNotesNamesToGsaNamesEmptyList() throws Exception {
setUpUsers();
Collection<String> gsaNames = userGroupManager.mapNotesNamesToGsaNames(
session, null, false);
assertEquals(0, gsaNames.size());
gsaNames = userGroupManager.mapNotesNamesToGsaNames(session,
Collections.emptyList(), false);
assertEquals(0, gsaNames.size()); }
public void testMapNotesNamesToGsaNamesInvalidUser() throws Exception {
setUpUsers();
Collection<String> gsaNames = userGroupManager.mapNotesNamesToGsaNames(
session,
Lists.newArrayList("cn=Padme Amidala/ou=Tests/o=Tests",
"cn=Count Dooku/ou=Tests/o=Tests",
"bad user",
"bad user",
"cn=Ahsoka Tano/ou=Tests/o=Tests"), false);
assertEquals(3, gsaNames.size());
assertTrue(gsaNames.contains("padme"));
assertTrue(gsaNames.contains("dooku"));
assertTrue(gsaNames.contains("ahsoka"));
}
public void testMapNotesNamesToGsaNamesRemoveUsers() throws Exception {
setUpUsers();
ArrayList<String> notesNames = Lists.newArrayList(
"cn=Padme Amidala/ou=Tests/o=Tests",
"cn=Count Dooku/ou=Tests/o=Tests",
"bad user",
"bad user",
"cn=Ahsoka Tano/ou=Tests/o=Tests");
Collection<String> gsaNames = userGroupManager.mapNotesNamesToGsaNames(
session, notesNames, true);
assertEquals(3, gsaNames.size());
assertTrue(gsaNames.contains("padme"));
assertTrue(gsaNames.contains("dooku"));
assertTrue(gsaNames.contains("ahsoka"));
assertEquals(2, notesNames.size());
}
private void setUpGroups() throws Exception {
userGroupManager.updateGroups(groupUnids);
getGroupData();
}
private void setUpUsers() throws Exception {
userGroupManager.updateGroups(groupUnids);
userGroupManager.updateUsers(userUnids);
getGroupData(); // Must be done after updateUsers
getUserData();
}
private void setUpRoles() throws Exception {
setUpUsers();
userGroupManager.updateRoles();
getRoleData();
}
private Long assertUserExists(String user) {
Long userId = gsaUserNames.get(user);
assertNotNull("Missing user: " + user, userId);
return userId;
}
private void assertUserDoesNotExist(String user) {
Long userId = gsaUserNames.get(user);
assertNull("Has user: " + user, userId);
}
private Long assertGroupExists(String group) {
Long groupId = groups.get(group);
assertNotNull("Missing group: " + group, groupId);
return groupId;
}
private void assertGroupDoesNotExist(String group) {
Long groupId = groups.get(group);
assertNull("Has group: " + group, groupId);
}
private Long assertRoleExists(String role) {
Long roleId = roles.get(role);
assertNotNull("Missing role: " + role, roleId);
return roleId;
}
private void assertRoleDoesNotExist(String role) {
Long roleId = roles.get(role);
assertNull("Has role: " + role, roleId);
}
private void assertGroupHasChild(String parentGroup, String childGroup) {
HashSet<Long> children = groupChildren.get(groups.get(parentGroup));
assertTrue(parentGroup + "->" + childGroup,
children.contains(groups.get(childGroup)));
}
private void assertUserHasGroup(String gsaname, String groupName) {
Long userId = assertUserExists(gsaname);
Long groupId = assertGroupExists(groupName);
assertTrue(gsaname + "->" + groupName,
userGroups.get(userId).contains(groupId));
}
private void assertUserHasRole(String gsaname, String role)
throws Exception {
Long roleId = assertRoleExists(role);
Long userId = assertUserExists(gsaname);
assertNotNull(roleId);
assertNotNull(userId);
assertNotNull(userRoles);
HashSet<Long> uRoles = userRoles.get(userId);
if (uRoles != null && uRoles.contains(roleId)) {
return;
}
HashSet<Long> uGroups = userGroups.get(userId);
assertNotNull(uGroups);
for (Long groupId : uGroups) {
HashSet<Long> roles = groupRoles.get(groupId);
if (roles != null && roles.contains(roleId)) {
return;
}
}
assertTrue(gsaname + " missing role: " + role, false);
}
private void assertUserDoesNotHaveRole(String gsaname, String role) {
Long roleId = roles.get(role);
if (roleId == null) {
return;
}
Long userId = assertUserExists(gsaname);
assertFalse(gsaname + " has role: " + role,
userRoles.get(userId).contains(roleId));
}
private void assertGroupHasRole(String group, String role)
throws Exception {
Long roleId = assertRoleExists(role);
Long groupId = assertGroupExists(group);
assertTrue(group + " missing role: " + role,
groupRoles.get(groupId).contains(roleId));
}
private void getGroupData() throws Exception {
groups.clear();
groupChildren.clear();
ResultSet rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.groupTableName);
while (rs.next()) {
groups.put(rs.getString("groupname"), rs.getLong("groupid"));
}
rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.groupChildrenTableName);
while (rs.next()) {
Long parentId = rs.getLong("parentgroupid");
Long childId = rs.getLong("childgroupid");
HashSet<Long> children = groupChildren.get(parentId);
if (children == null) {
children = new HashSet<Long>();
groupChildren.put(parentId, children);
}
assertTrue("Duplicate group child: " + parentId + ", " + childId,
children.add(childId));
assertTrue("No group record for " + parentId,
groups.containsValue(parentId));
assertTrue("No group record for " + childId,
groups.containsValue(childId));
}
}
private void getUserData() throws Exception {
notesUserNames.clear();
gsaUserNames.clear();
userGroups.clear();
ResultSet rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.userTableName);
while (rs.next()) {
notesUserNames.put(rs.getString("notesname"), rs.getLong("userid"));
gsaUserNames.put(rs.getString("gsaname"), rs.getLong("userid"));
}
rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.userGroupsTableName +
" left join " + userGroupManager.groupChildrenTableName + " on " +
" groupid = childgroupid");
while (rs.next()) {
Long userId = rs.getLong("userid");
Long groupId = rs.getLong("groupid");
Long parentId = rs.getLong("parentgroupid");
HashSet<Long> tmp = userGroups.get(userId);
if (tmp == null) {
tmp = new HashSet<Long>();
userGroups.put(userId, tmp);
}
tmp.add(groupId);
tmp.add(parentId);
assertTrue("No user record for " + userId,
gsaUserNames.containsValue(userId));
assertTrue("No group record for " + groupId,
groups.containsValue(groupId));
}
}
private void getRoleData() throws Exception {
roles.clear();
userRoles.clear();
groupRoles.clear();
ResultSet rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.roleTableName);
while (rs.next()) {
roles.put(rs.getString("replicaid") + "/" + rs.getString("rolename"),
rs.getLong("roleid"));
}
rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.userRolesTableName);
while (rs.next()) {
Long userId = rs.getLong("userid");
Long roleId = rs.getLong("roleid");
HashSet<Long> tmp = userRoles.get(userId);
if (tmp == null) {
tmp = new HashSet<Long>();
userRoles.put(userId, tmp);
}
assertTrue("Duplicate user roles: " + userId + ", " + roleId,
tmp.add(roleId));
assertTrue("No user record for " + userId,
gsaUserNames.containsValue(userId));
assertTrue("No role record for " + roleId,
roles.containsValue(roleId));
}
rs = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY).executeQuery(
"select * from " + userGroupManager.groupRolesTableName);
while (rs.next()) {
Long groupId = rs.getLong("groupid");
Long roleId = rs.getLong("roleid");
HashSet<Long> tmp = groupRoles.get(groupId);
if (tmp == null) {
tmp = new HashSet<Long>();
groupRoles.put(groupId, tmp);
}
assertTrue("Duplicate group roles: " + groupId + ", " + roleId,
tmp.add(roleId));
assertTrue("No group record for " + groupId,
groups.containsValue(groupId));
assertTrue("No role record for " + roleId,
roles.containsValue(roleId));
}
}
private void printCache() throws Exception {
System.out.println("**************************");
System.out.println("Groups: " + groups.toString());
System.out.println("Group children: " + groupChildren);
System.out.println("Users: " + notesUserNames);
System.out.println("Users: " + gsaUserNames);
System.out.println("User groups: " + userGroups);
System.out.println("Roles: " + roles);
System.out.println("User roles: " + userRoles);
System.out.println("Group roles: " + groupRoles);
System.out.println("**************************");
}
}