/*
* (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* Nuxeo - initial API and implementation
*/
package org.nuxeo.ecm.platform.usermanager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Ignore;
import org.junit.Test;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.NuxeoGroup;
import org.nuxeo.ecm.core.api.NuxeoPrincipal;
import org.nuxeo.ecm.core.api.security.ACE;
import org.nuxeo.ecm.core.api.security.ACL;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.api.security.impl.ACLImpl;
import org.nuxeo.ecm.core.api.security.impl.ACPImpl;
import org.nuxeo.ecm.directory.DirectoryException;
import org.nuxeo.ecm.platform.usermanager.exceptions.GroupAlreadyExistsException;
import org.nuxeo.ecm.platform.usermanager.exceptions.UserAlreadyExistsException;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.runtime.test.runner.LocalDeploy;
import org.nuxeo.runtime.test.runner.RuntimeHarness;
/**
* @author George Lefter
* @author Florent Guillaume
* @author Anahide Tchertchian
*/
@LocalDeploy("org.nuxeo.ecm.platform.usermanager.tests:test-usermanagerimpl/directory-config.xml")
public class TestUserManager extends UserManagerTestCase {
@Inject
protected RuntimeHarness harness;
@Test
public void testExistingSetup() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("Administrator");
List<String> groups = principal.getGroups();
assertTrue(groups.contains("administrators"));
}
private DocumentModel getUser(String userId) throws Exception {
DocumentModel newUser = userManager.getBareUserModel();
newUser.setProperty("user", "username", userId);
return newUser;
}
private DocumentModel getGroup(String groupId) throws Exception {
DocumentModel newGroup = userManager.getBareGroupModel();
newGroup.setProperty("group", "groupname", groupId);
return newGroup;
}
@Test
public void testGetAnonymous() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("Guest");
assertNotNull(principal);
assertEquals("Guest", principal.getName());
assertEquals("Anonymous", principal.getFirstName());
assertEquals("Coward", principal.getLastName());
assertNull(principal.getCompany());
}
@Test
public void testGetAdministrator() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("tehroot");
assertNotNull(principal);
assertTrue(principal.isAdministrator());
assertTrue(principal.isMemberOf("administrators"));
assertTrue(principal.isMemberOf("defgr"));
assertFalse(principal.isMemberOf("myAdministrators"));
assertEquals("tehroot", principal.getName());
assertEquals("The", principal.getFirstName());
assertEquals("Root", principal.getLastName());
assertNull(principal.getCompany());
}
@Test
public void testGetAdministratorOverride() throws Exception {
harness.deployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after deployment => refetch it
userManager = Framework.getService(UserManager.class);
try {
doTestGetAdministratorOverride();
} finally {
harness.undeployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after undeployment => refetch it
userManager = Framework.getService(UserManager.class);
}
}
public void doTestGetAdministratorOverride() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("tehroot");
assertNotNull(principal);
assertTrue(principal.isAdministrator());
// no administrators groups anymore
assertFalse(principal.isMemberOf("administrators"));
assertTrue(principal.isMemberOf("defgr"));
// new administrators group as virtual
assertTrue(principal.isMemberOf("myAdministrators"));
assertEquals("tehroot", principal.getName());
assertEquals("The", principal.getFirstName());
assertEquals("Root", principal.getLastName());
assertNull(principal.getCompany());
}
@Test
public void testGetVirtualUsers() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("ClassicAdministrator");
assertNotNull(principal);
assertEquals("ClassicAdministrator", principal.getName());
assertEquals("Classic", principal.getFirstName());
assertEquals("Administrator", principal.getLastName());
assertNull(principal.getCompany());
assertTrue(principal.isMemberOf("administrators"));
assertFalse(principal.isMemberOf("myAdministrators"));
assertTrue(principal.isAdministrator());
principal = userManager.getPrincipal("MyCustomAdministrator");
assertNotNull(principal);
assertEquals("MyCustomAdministrator", principal.getName());
assertEquals("My Custom", principal.getFirstName());
assertEquals("Administrator", principal.getLastName());
assertNull(principal.getCompany());
// test additional admin group
assertFalse(principal.isMemberOf("administrators"));
assertTrue(principal.isMemberOf("myAdministrators"));
assertFalse(principal.isAdministrator());
principal = userManager.getPrincipal("MyCustomMember");
// error in logs normal, we check an extra field do not compromise the
// main action
assertNotNull(principal);
assertEquals("MyCustomMember", principal.getName());
assertEquals("My Custom", principal.getFirstName());
assertEquals("Member", principal.getLastName());
assertNull(principal.getCompany());
// assertEquals(4, principal.getAllGroups().size());
assertFalse(principal.isAdministrator());
assertTrue(principal.isMemberOf("othergroup"));
assertTrue(principal.isMemberOf("defgr"));
// this one is taken from props
assertTrue(principal.isMemberOf("members"));
// group1 does not exist => not here
assertFalse(principal.isMemberOf("group1"));
}
@Test
public void testGetVirtualUsersOverride() throws Exception {
harness.deployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after deployment => refetch it
userManager = Framework.getService(UserManager.class);
try {
doTestGetVirtualUsersOverride();
} finally {
harness.undeployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after undeployment => refetch it
userManager = Framework.getService(UserManager.class);
}
}
public void doTestGetVirtualUsersOverride() throws Exception {
NuxeoPrincipal principal = userManager.getPrincipal("ClassicAdministrator");
assertNotNull(principal);
assertEquals("ClassicAdministrator", principal.getName());
assertEquals("Classic", principal.getFirstName());
assertEquals("Administrator", principal.getLastName());
assertNull(principal.getCompany());
assertTrue(principal.isMemberOf("administrators"));
assertFalse(principal.isMemberOf("myAdministrators"));
assertFalse(principal.isAdministrator());
principal = userManager.getPrincipal("MyCustomAdministrator");
assertNotNull(principal);
assertEquals("MyCustomAdministrator", principal.getName());
assertEquals("My Custom", principal.getFirstName());
assertEquals("Administrator", principal.getLastName());
assertNull(principal.getCompany());
// test additional admin group
assertFalse(principal.isMemberOf("administrators"));
assertTrue(principal.isMemberOf("myAdministrators"));
assertTrue(principal.isAdministrator());
principal = userManager.getPrincipal("MyCustomMember");
assertNotNull(principal);
assertEquals("MyCustomMember", principal.getName());
assertEquals("My Custom", principal.getFirstName());
assertEquals("Member", principal.getLastName());
assertNull(principal.getCompany());
// assertEquals(4, principal.getAllGroups().size());
assertFalse(principal.isAdministrator());
assertTrue(principal.isMemberOf("othergroup"));
assertTrue(principal.isMemberOf("defgr"));
// this one is taken from props
assertTrue(principal.isMemberOf("members"));
// group1 does not exist => not here
assertFalse(principal.isMemberOf("group1"));
}
@Test
public void testGetAdministratorGroups() {
List<String> adminGroups = userManager.getAdministratorsGroups();
assertEquals(Collections.singletonList("administrators"), adminGroups);
}
@Test
public void testGetAdministratorGroupsOverride() throws Exception {
harness.deployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after deployment => refetch it
userManager = Framework.getService(UserManager.class);
try {
doTestGetAdministratorGroupsOverride();
} finally {
harness.undeployContrib("org.nuxeo.ecm.platform.usermanager.tests",
"test-usermanagerimpl/userservice-override-config.xml");
// user manager is recomputed after undeployment => refetch it
userManager = Framework.getService(UserManager.class);
}
}
public void doTestGetAdministratorGroupsOverride() throws Exception {
List<String> adminGroups = userManager.getAdministratorsGroups();
assertEquals(Collections.singletonList("myAdministrators"), adminGroups);
}
@Test
public void testSearchAnonymous() throws Exception {
DocumentModelList users;
DocumentModel principal;
users = userManager.searchUsers("Gu");
assertEquals(1, users.size());
principal = users.get(0);
assertEquals("Guest", principal.getId());
assertEquals("Anonymous", principal.getProperty("user", "firstName"));
assertEquals("Coward", principal.getProperty("user", "lastName"));
// search by map
Map<String, Serializable> filter = new HashMap<>();
filter.put("lastName", "Cow");
users = userManager.searchUsers(filter, filter.keySet());
assertEquals(1, users.size());
principal = users.get(0);
assertEquals("Guest", principal.getId());
// with a non-matching criterion
filter.put("firstName", "Bob");
users = userManager.searchUsers(filter, filter.keySet());
assertEquals(0, users.size());
// another search
filter.clear();
filter.put("username", "Gue");
users = userManager.searchUsers(filter, filter.keySet());
assertEquals(1, users.size());
principal = users.get(0);
assertEquals("Guest", principal.getId());
// now add another non-Anonymous user that matches the same query
DocumentModel newUser = getUser("Gudule");
userManager.createUser(newUser);
users = userManager.searchUsers("Gu");
assertEquals(2, users.size());
String name1 = users.get(0).getId();
String name2 = users.get(1).getId();
if (!name1.equals("Guest")) {
final String tmp = name1;
name1 = name2;
name2 = tmp;
}
assertEquals("Guest", name1);
assertEquals("Gudule", name2);
}
public void deleteTestObjects() throws Exception {
List<String> users = userManager.getUserIds();
List<String> groups = userManager.getGroupIds();
for (String user : users) {
if (user.startsWith("test_")) {
userManager.deleteUser(user);
}
}
for (String group : groups) {
if (group.startsWith("test_")) {
userManager.deleteGroup(group);
}
}
}
// resource-intensive test, disabled by default
@Test
@Ignore
public void testMemoryLeak() throws Exception {
deleteTestObjects();
DocumentModel userModel = getUser("test_usr0");
userManager.createUser(userModel);
DocumentModel groupModel = getGroup("test_grp0");
userManager.createGroup(groupModel);
for (int i = 0; i < 100; i++) {
String userName = "test_u" + i;
userModel = getUser(userName);
userModel.setProperty("user", "username", userName);
userModel.setProperty("user", "groups", Collections.singletonList("test_grp0"));
userManager.createUser(userModel);
}
for (int i = 0; i < 100; i++) {
String groupName = "test_g" + i;
groupModel = getGroup(groupName);
groupModel.setProperty("group", "groupname", groupName);
userManager.createGroup(groupModel);
}
for (int i = 0; i < 100; i++) {
userManager.getGroupIds();
}
for (int i = 0; i < 100; i++) {
userManager.getUserIds();
}
}
@Test
public void testCreatePrincipal() throws Exception {
deleteTestObjects();
// force User Directory initialization first - so that the sql script
// executes
DocumentModel user = getUser("test_u1");
DocumentModel group = getGroup("test_g1");
userManager.createGroup(group);
NuxeoGroup g1 = userManager.getGroup("test_g1");
assertNotNull(g1);
List<String> groupNames = Collections.singletonList("test_g1");
List<String> groupNamesWithDefault = Arrays.asList("defgr", "test_g1");
List<String> roleNames = Collections.singletonList("regular");
user.setProperty("user", "firstName", "fname1");
user.setProperty("user", "lastName", "lname1");
user.setProperty("user", "company", "company1");
user.setProperty("user", "groups", groupNames);
userManager.createUser(user);
NuxeoPrincipal newPrincipal = userManager.getPrincipal("test_u1");
assertNotNull(newPrincipal);
assertEquals("test_u1", newPrincipal.getName());
assertEquals("fname1", newPrincipal.getFirstName());
assertEquals("lname1", newPrincipal.getLastName());
assertEquals("company1", newPrincipal.getCompany());
List<String> groups = newPrincipal.getGroups();
Collections.sort(groups);
assertEquals(groupNamesWithDefault, groups);
assertEquals(roleNames, newPrincipal.getRoles());
assertEquals("test_u1", newPrincipal.getName());
try {
userManager.createUser(user);
fail("Should have raised UserAlreadyExistsException");
} catch (UserAlreadyExistsException e) {
// ok
}
}
@Test
public void testCreateGroup() throws Exception {
deleteTestObjects();
DocumentModel u1 = getUser("test_u1");
DocumentModel u2 = getUser("test_u2");
userManager.createUser(u1);
userManager.createUser(u2);
DocumentModel g1 = getGroup("test_g1");
DocumentModel g2 = getGroup("test_g2");
DocumentModel g3 = getGroup("test_g3");
g3.setPropertyValue("group:grouplabel", "test_g3_label");
List<String> g1Users = Collections.singletonList("test_u1");
List<String> g2Users = Arrays.asList("test_u1", "test_u2");
List<String> g2Groups = Collections.singletonList("test_g1");
g1.setProperty("group", "members", g1Users);
userManager.createGroup(g1);
g2.setProperty("group", "members", g2Users);
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
// without users / groups
userManager.createGroup(g3);
NuxeoGroup newG1 = userManager.getGroup("test_g1");
NuxeoGroup newG2 = userManager.getGroup("test_g2");
NuxeoGroup newG3 = userManager.getGroup("test_g3");
assertNotNull(newG1);
assertNotNull(newG2);
assertNotNull(newG3);
assertEquals("test_g1", newG1.getName());
assertEquals("test_g2", newG2.getName());
assertEquals("test_g3", newG3.getName());
assertEquals("test_g1", newG1.getLabel());
assertEquals("test_g2", newG2.getLabel());
assertEquals("test_g3_label", newG3.getLabel());
assertEquals(g1Users, newG1.getMemberUsers());
assertEquals(g2Users, newG2.getMemberUsers());
assertEquals(g2Groups, newG2.getMemberGroups());
// try to create the group again and test if an exception is thrown
try {
userManager.createGroup(g1);
fail("Should have raised GroupAlreadyExistsException");
} catch (GroupAlreadyExistsException e) {
// ok
}
}
@Test
public void testGetTopLevelGroups() throws Exception {
deleteTestObjects();
DocumentModel g1 = getGroup("test_g1");
DocumentModel g2 = getGroup("test_g2");
List<String> g2Groups = Collections.singletonList("test_g1");
userManager.createGroup(g1);
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
List<String> expectedTopLevelGroups = Arrays.asList("administrators", "members", "powerusers", "test_g2");
List<String> topLevelGroups = userManager.getTopLevelGroups();
Collections.sort(topLevelGroups);
assertEquals(expectedTopLevelGroups, topLevelGroups);
// delete test_g2 and test if test_g1 is toplevel
userManager.deleteGroup(g2);
expectedTopLevelGroups = Arrays.asList("administrators", "members", "powerusers", "test_g1");
topLevelGroups = userManager.getTopLevelGroups();
Collections.sort(topLevelGroups);
assertEquals(expectedTopLevelGroups, topLevelGroups);
// re-create g2 as a parent of g1
// test if g1 is not top-level and g2 is
g2Groups = Collections.singletonList("test_g1");
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
expectedTopLevelGroups = Arrays.asList("administrators", "members", "powerusers", "test_g2");
topLevelGroups = userManager.getTopLevelGroups();
Collections.sort(topLevelGroups);
assertEquals(expectedTopLevelGroups, topLevelGroups);
}
/**
* Test the method getUsersInGroup, making sure it does return only the users of the group (and not the subgroups
* ones).
*/
@Test
public void testGetUsersInGroup() throws Exception {
deleteTestObjects();
DocumentModel u1 = getUser("test_u1");
DocumentModel u2 = getUser("test_u2");
DocumentModel u2bis = getUser("test_u2bis");
userManager.createUser(u1);
userManager.createUser(u2);
userManager.createUser(u2bis);
DocumentModel g1 = getGroup("test_g1");
DocumentModel g2 = getGroup("test_g2");
List<String> g1Users = Collections.singletonList("test_u1");
List<String> g2Users = Arrays.asList("test_u2", "test_u2bis");
List<String> g2Groups = Collections.singletonList("test_g1");
g1.setProperty("group", "members", g1Users);
userManager.createGroup(g1);
g2.setProperty("group", "members", g2Users);
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
List<String> expectedUsersInGroup1 = Collections.singletonList("test_u1");
List<String> expectedUsersInGroup2 = Arrays.asList("test_u2bis", "test_u2");
Collections.sort(expectedUsersInGroup1);
Collections.sort(expectedUsersInGroup2);
assertEquals(expectedUsersInGroup1, userManager.getUsersInGroup("test_g1"));
assertEquals(expectedUsersInGroup2, userManager.getUsersInGroup("test_g2"));
}
/**
* Test the method getUsersInGroupAndSubgroups, making sure it does return all the users from a group and its
* subgroups.
*/
@Test
public void testGetUsersInGroupAndSubgroups() throws Exception {
deleteTestObjects();
DocumentModel u1 = getUser("test_u1");
DocumentModel u2 = getUser("test_u2");
DocumentModel u2bis = getUser("test_u2bis");
userManager.createUser(u1);
userManager.createUser(u2);
userManager.createUser(u2bis);
DocumentModel g1 = getGroup("test_g1");
DocumentModel g2 = getGroup("test_g2");
List<String> g1Users = Collections.singletonList("test_u1");
List<String> g2Users = Arrays.asList("test_u2", "test_u2bis");
List<String> g2Groups = Collections.singletonList("test_g1");
g1.setProperty("group", "members", g1Users);
userManager.createGroup(g1);
g2.setProperty("group", "members", g2Users);
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
List<String> expectedUsersInGroup1 = Collections.singletonList("test_u1");
List<String> usersInGroupAndSubGroups1 = userManager.getUsersInGroupAndSubGroups("test_g1");
Collections.sort(expectedUsersInGroup1);
Collections.sort(usersInGroupAndSubGroups1);
assertEquals(expectedUsersInGroup1, usersInGroupAndSubGroups1);
// should have all the groups from group1 and group2
List<String> expectedUsersInGroup2 = Arrays.asList("test_u2bis", "test_u2", "test_u1");
List<String> usersInGroupAndSubGroups2 = userManager.getUsersInGroupAndSubGroups("test_g2");
Collections.sort(expectedUsersInGroup2);
Collections.sort(usersInGroupAndSubGroups2);
assertEquals(expectedUsersInGroup2, usersInGroupAndSubGroups2);
}
/**
* Test the method getUsersInGroupAndSubgroups making sure it's not going into an infinite loop when a subgroup is
* also parent of a group.
*/
@Test
public void testGetUsersInGroupAndSubgroupsWithoutInfiniteLoop() throws Exception {
deleteTestObjects();
DocumentModel u1 = getUser("test_u1");
DocumentModel u2 = getUser("test_u2");
DocumentModel u2bis = getUser("test_u2bis");
userManager.createUser(u1);
userManager.createUser(u2);
userManager.createUser(u2bis);
DocumentModel g1 = getGroup("test_g1");
DocumentModel g2 = getGroup("test_g2");
List<String> g1Users = Collections.singletonList("test_u1");
List<String> g2Users = Arrays.asList("test_u2", "test_u2bis");
List<String> g2Groups = Collections.singletonList("test_g1");
// group1 is also a subgroup of group2
List<String> g1Groups = Collections.singletonList("test_g2");
g1.setProperty("group", "members", g1Users);
g1.setProperty("group", "subGroups", g1Groups);
userManager.createGroup(g1);
g2.setProperty("group", "members", g2Users);
g2.setProperty("group", "subGroups", g2Groups);
userManager.createGroup(g2);
List<String> expectedUsersInGroup2 = Arrays.asList("test_u2bis", "test_u2", "test_u1");
// infinite loop can occur here:
List<String> usersInGroupAndSubGroups2 = userManager.getUsersInGroupAndSubGroups("test_g2");
Collections.sort(expectedUsersInGroup2);
Collections.sort(usersInGroupAndSubGroups2);
assertEquals(expectedUsersInGroup2, usersInGroupAndSubGroups2);
// and here
List<String> g1AncestorGroups = userManager.getAncestorGroups("test_g1");
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("test_g2", "test_g1"), g1AncestorGroups));
}
@Test
public void testDeletePrincipal() throws Exception {
deleteTestObjects();
DocumentModel user = getUser("test_u1");
userManager.createUser(user);
assertNotNull(userManager.getPrincipal("test_u1"));
userManager.deleteUser(user);
assertNull(userManager.getPrincipal("test_u1"));
// try to delete the principal twice
try {
userManager.deleteUser(user);
fail();
} catch (DirectoryException e) {
assertTrue(e.getMessage(), e.getMessage().contains("User does not exist: test_u1"));
}
}
@Test
public void testDeleteGroup() throws Exception {
deleteTestObjects();
DocumentModel group = getGroup("test_g1");
userManager.createGroup(group);
assertNotNull(userManager.getGroup("test_g1"));
userManager.deleteGroup(group);
assertNull(userManager.getGroup("test_g1"));
// try to delete the group twice
try {
userManager.deleteGroup(group);
fail();
} catch (DirectoryException e) {
assertTrue(e.getMessage(), e.getMessage().contains("Group does not exist: test_g1"));
}
}
@Test
public void testSearchUser() throws Exception {
assertEquals(0, userManager.searchUsers("test").size());
DocumentModel doc = getUser("test");
userManager.createUser(doc);
doc = getUser("test_2");
userManager.createUser(doc);
assertEquals(2, userManager.searchUsers("test").size());
doc = getUser("else");
doc.setProperty("user", "firstName", "test");
userManager.createUser(doc);
assertEquals(3, userManager.searchUsers("test").size());
doc = getGroup("group");
userManager.createGroup(doc);
doc = getGroup("group_1");
userManager.createGroup(doc);
assertEquals(2, userManager.searchGroups("group").size());
doc = getGroup("else");
doc.setProperty("group", "grouplabel", "group");
userManager.createGroup(doc);
assertEquals(3, userManager.searchGroups("group").size());
}
@Test
public void testUpdatePrincipal() throws Exception {
deleteTestObjects();
NuxeoPrincipal u1 = new NuxeoPrincipalImpl("test_u1");
u1.setFirstName("fname1");
u1.setLastName("lname1");
u1.setCompany("company1");
DocumentModel u1Model = userManager.createUser(u1.getModel());
DocumentModel g1 = getGroup("test_g1");
g1 = userManager.createGroup(g1);
DocumentModel g2 = getGroup("test_g2");
g2 = userManager.createGroup(g2);
DocumentModel g3 = getGroup("test_g3");
g3 = userManager.createGroup(g3);
u1Model.setProperty("user", "groups", Arrays.asList("test_g1", "test_g2"));
userManager.updateUser(u1Model);
// refresh u1
u1 = userManager.getPrincipal("test_u1");
List<String> expectedGroups = Arrays.asList("defgr", "test_g1", "test_g2");
List<String> groups = u1.getGroups();
Collections.sort(groups);
assertEquals(expectedGroups, groups);
u1.setFirstName("fname2");
u1.setLastName("lname2");
u1.setCompany("company2");
u1.getGroups().remove("test_g2"); // ???!!!
u1.getGroups().add("test_g3");
userManager.updateUser(u1.getModel());
NuxeoPrincipal newU1 = userManager.getPrincipal("test_u1");
assertNotNull(newU1);
assertEquals("test_u1", newU1.getName());
assertEquals("fname2", newU1.getFirstName());
assertEquals("lname2", newU1.getLastName());
assertEquals("company2", newU1.getCompany());
assertEquals(newU1.getName(), u1.getName());
assertEquals(newU1.getGroups(), u1.getGroups());
assertEquals(newU1.getRoles(), u1.getRoles());
}
@Test
public void testUpdateGroupLabel() throws Exception {
deleteTestObjects();
DocumentModel groupModel = getGroup("test_g");
groupModel.setProperty("group", "grouplabel", "test group");
groupModel = userManager.createGroup(groupModel);
NuxeoGroup group = userManager.getGroup("test_g");
assertEquals("test group", group.getLabel());
groupModel.setProperty("group", "grouplabel", "another group");
userManager.updateGroup(groupModel);
group = userManager.getGroup("test_g");
assertEquals("another group", group.getLabel());
}
@Test
public void testUpdateGroup() throws Exception {
deleteTestObjects();
// setup group g
DocumentModel u1 = getUser("test_u1");
userManager.createUser(u1);
DocumentModel u2 = getUser("test_u2");
userManager.createUser(u2);
DocumentModel u3 = getUser("test_u3");
userManager.createUser(u3);
DocumentModel g1 = getGroup("test_g1");
userManager.createGroup(g1);
DocumentModel g2 = getGroup("test_g2");
userManager.createGroup(g2);
DocumentModel g3 = getGroup("test_g3");
userManager.createGroup(g3);
List<String> gUsers = Arrays.asList("test_u1", "test_u2");
List<String> gGroups = Arrays.asList("test_g1", "test_g2");
DocumentModel g = getGroup("test_g");
g.setProperty("group", "members", gUsers);
g.setProperty("group", "subGroups", gGroups);
g = userManager.createGroup(g);
// update group g
gUsers = new ArrayList<>(Arrays.asList("test_u1", "test_u3"));
gGroups = new ArrayList<>(Arrays.asList("test_g1", "test_g3"));
g.setProperty("group", "members", gUsers);
g.setProperty("group", "subGroups", gGroups);
userManager.updateGroup(g);
// check new group
NuxeoGroup newG = userManager.getGroup("test_g");
List<String> newGUsers = Arrays.asList("test_u1", "test_u3");
List<String> newGGroups = Arrays.asList("test_g1", "test_g3");
List<String> actualUsers = newG.getMemberUsers();
Collections.sort(actualUsers);
assertEquals(newGUsers, actualUsers);
List<String> actualGroups = newG.getMemberGroups();
Collections.sort(actualGroups);
assertEquals(newGGroups, actualGroups);
}
@Test
public void testPasswordAuthenticate() {
assertTrue(userManager.checkUsernamePassword("Administrator", "Administrator"));
}
@Test
public void testPasswordChange() {
DocumentModel doc = userManager.getUserModel("Administrator");
doc.setProperty("user", "password", "newPassword123");
userManager.updateUser(doc);
// old one not valid anymore
assertFalse(userManager.checkUsernamePassword("Administrator", "Administrator"));
// new one can be used to authenticate
assertTrue(userManager.checkUsernamePassword("Administrator", "newPassword123"));
}
@Test
public void testPasswordNotReturned() {
// getPrincipal
NuxeoPrincipal principal = userManager.getPrincipal("Administrator");
DocumentModel doc = principal.getModel();
String password = (String) doc.getProperty("user", "password");
assertNull(password);
// getUserModel
doc = userManager.getUserModel("Administrator");
password = (String) doc.getProperty("user", "password");
assertNull(password);
// searchUsers
List<DocumentModel> docs = userManager.searchUsers("Administrator");
assertEquals(1, docs.size());
doc = docs.get(0);
password = (String) doc.getProperty("user", "password");
assertNull(password);
}
/**
* common init method for initialising tests for the method getUsernamesForPermission.
*/
private void initTestGetUsernamesForPermission() throws Exception {
userManager.getPrincipal("Administrator"); // creates tables
deleteTestObjects();
userManager.createUser(getUser("alex"));
userManager.createUser(getUser("bree"));
userManager.createUser(getUser("jdoe"));
userManager.createUser(getUser("stef"));
List<String> g1Users = Arrays.asList("alex", "stef");
DocumentModel g1 = getGroup("group1");
g1.setProperty("group", "members", g1Users);
userManager.createGroup(g1);
List<String> g2Users = Arrays.asList("alex", "bree");
DocumentModel g2 = getGroup("group2");
g2.setProperty("group", "members", g2Users);
userManager.createGroup(g2);
// group3 has jdoe and a subgroup: g2
List<String> g3Users = Collections.singletonList("jdoe");
List<String> g3SubGroups = Collections.singletonList("group2");
DocumentModel g3 = getGroup("group3");
g3.setProperty("group", "members", g3Users);
g3.setProperty("group", "subGroups", g3SubGroups);
userManager.createGroup(g3);
}
/**
* Testing the method getUsernamesForPermission for a simple case.
*/
@Test
public void testGetUsernamesForPermission() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, true));
acl.add(new ACE("group1", SecurityConstants.READ, false));
acl.add(new ACE("alex", SecurityConstants.READ, true));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
List<String> expectedUsers = Arrays.asList("Administrator", "alex", "jdoe", "bree");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Testing the method getUsernamesForPermission for a simple case.
*/
@Test
public void testGetUsernamesForPermission2() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(ACE.BLOCK);
acl.add(new ACE("group1", SecurityConstants.READ, false));
acl.add(new ACE("alex", SecurityConstants.READ, true));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
List<String> expectedUsers = Collections.singletonList("alex");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Same test as before but without the first ace (default value: everyone, everything false).
*/
@Test
public void testGetUsernamesForPermissionWithoutEveryoneEverythingACE() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(new ACE("group1", SecurityConstants.READ, false));
acl.add(new ACE("alex", SecurityConstants.READ, true));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
List<String> expectedUsers = Collections.singletonList("alex");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Testing getUsernamesForPermission with a user in 2 groups.
*/
@Test
public void testGetUsernamesForPermissionIn2Groups() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, true));
acl.add(new ACE("group2", SecurityConstants.READ, false));
acl.add(new ACE("group1", SecurityConstants.READ, true));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
// Should contain alex and stef (in group1) and jdoe (in none of these
// groups) but not bree (in group2)
List<String> expectedUsers = Arrays.asList("Administrator", "alex", "stef", "jdoe");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Testing getUsernamesForPermission with compound permission. For example, READ_WRITE contains READ.
*/
@Test
public void testGetUsernamesForPermissionWithCompoundPermission() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, true));
acl.add(new ACE("group2", SecurityConstants.READ_WRITE, false));
acl.add(new ACE("group1", SecurityConstants.READ, true));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
// Should contain alex and stef (in group1) and jdoe (in none of these
// groups) but not bree (in group2)
List<String> expectedUsers = Arrays.asList("Administrator", "alex", "stef", "jdoe");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Testing getUsernamesForPermission with a ACP having more than one ACL
*/
@Test
public void testGetUsernamesForPermissionWithMultipleACL() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl(ACL.INHERITED_ACL);
acl.add(new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, true));
acl.add(new ACE("group2", SecurityConstants.READ_WRITE, false));
acp.addACL(acl);
ACLImpl acl2 = new ACLImpl(ACL.LOCAL_ACL);
acl2.add(new ACE("group1", SecurityConstants.READ, true));
acp.addACL(acl2);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
// Should contain stef (in group1) and jdoe (in none of these
// groups) but not bree (in group2) neither alex (in group1 and group2)
List<String> expectedUsers = Arrays.asList("Administrator", "stef", "jdoe");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
/**
* Testing getUsernamesForPermission with subgroups.
*/
@Test
public void testGetUsernamesForPermissionWithSubGroups() throws Exception {
initTestGetUsernamesForPermission();
ACPImpl acp = new ACPImpl();
ACLImpl acl = new ACLImpl();
acl.add(new ACE("group3", SecurityConstants.READ_WRITE, true));
acl.add(new ACE("group1", SecurityConstants.READ, false));
acp.addACL(acl);
List<String> users = Arrays.asList(userManager.getUsersForPermission(SecurityConstants.READ, acp));
// group3 and group2 but alex should have read access
List<String> expectedUsers = Arrays.asList("bree", "jdoe");
Collections.sort(users);
Collections.sort(expectedUsers);
assertEquals("Expected users having read access are ", expectedUsers, users);
}
@Test
public void testUsersAndGroupsWithSpaces() throws Exception {
String userNameWithSpaces = " test_u1 ";
String groupNameWithSpaces = " test_g1 ";
deleteTestObjects();
DocumentModel u1 = getUser(userNameWithSpaces);
u1 = userManager.createUser(u1);
assertTrue(userManager.searchUsers(userNameWithSpaces).size() == 1);
assertNotNull(userManager.getUserModel(userNameWithSpaces));
assertTrue(userManager.searchUsers(userNameWithSpaces.trim()).size() == 1);
assertNotNull(userManager.getUserModel(userNameWithSpaces.trim()));
DocumentModel g1 = getGroup(groupNameWithSpaces);
List<String> g1Users = Collections.singletonList(u1.getId());
g1.setProperty("group", "members", g1Users);
g1 = userManager.createGroup(g1);
assertTrue(userManager.searchGroups(groupNameWithSpaces).size() == 1);
assertNotNull(userManager.getGroup(groupNameWithSpaces));
assertTrue(userManager.searchGroups(groupNameWithSpaces.trim()).size() == 1);
assertNotNull(userManager.getGroup(groupNameWithSpaces.trim()));
NuxeoPrincipal up1 = userManager.getPrincipal(userNameWithSpaces);
assertNotNull(up1);
up1 = userManager.getPrincipal(userNameWithSpaces.trim());
assertNotNull(up1);
assertTrue(up1.getGroups().contains(groupNameWithSpaces.trim()));
}
@Test
public void testTransientUsers() {
NuxeoPrincipal principal = userManager.getPrincipal("Administrator");
assertFalse(principal.isTransient());
String transientUsername = NuxeoPrincipal.computeTransientUsername("leela@nuxeo.com");
assertTrue(NuxeoPrincipal.isTransientUsername(transientUsername));
principal = userManager.getPrincipal(transientUsername);
assertNotNull(principal);
assertTrue(principal.isTransient());
assertFalse(principal.isAdministrator());
assertFalse(principal.isAnonymous());
assertTrue(principal.getAllGroups().isEmpty());
assertEquals("leela@nuxeo.com", principal.getFirstName());
assertEquals("leela@nuxeo.com", principal.getEmail());
assertEquals(transientUsername, principal.getName());
}
@Test
public void testCacheAlter() {
// Given we use a cache
assertNotNull(((UserManagerImpl) userManager).principalCache);
// Given a principal
NuxeoPrincipal principal = userManager.getPrincipal("Administrator");
// When I alter the principal without saving it
String value = principal.getFirstName();
principal.setFirstName("pfouh");
// Then the cached principal is not altered
assertEquals(value, userManager.getPrincipal("Administrator").getFirstName());
// When I save it
userManager.updateUser(principal.getModel());
// Then the cached principal is altered
assertEquals("pfouh", userManager.getPrincipal("Administrator").getFirstName());
}
@Test
public void testPrincipalSerialization() throws IOException, ClassNotFoundException {
class DebuggingObjectOutputStream extends ObjectOutputStream {
final List<Object> stack = new ArrayList<>();
DebuggingObjectOutputStream(OutputStream out) throws IOException {
super(out);
enableReplaceObject(true);
}
/**
* Abuse {@code replaceObject()} as a hook to maintain our stack.
*/
@Override
protected Object replaceObject(Object o) {
stack.add(o);
return o;
}
}
class DebuggingObjectInputStream extends ObjectInputStream {
DebuggingObjectInputStream(InputStream in) throws IOException {
super(in);
enableResolveObject(true);
}
final List<Object> stack = new ArrayList<>();
@Override
protected Object resolveObject(Object obj) throws IOException {
Object resolveObject = super.resolveObject(obj);
stack.add(resolveObject);
return resolveObject;
}
}
NuxeoPrincipal original = userManager.getPrincipal("Administrator");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (DebuggingObjectOutputStream oos = new DebuggingObjectOutputStream(bos)) {
oos.writeObject(original);
assertEquals(NuxeoPrincipalImpl.TransferableClone.DataTransferObject.class, oos.stack.get(0).getClass());
assertEquals("Administrator", oos.stack.get(1));
}
try (DebuggingObjectInputStream ois = new DebuggingObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()))) {
assertEquals(original, ois.readObject());
assertEquals("Administrator", ois.stack.get(0));
assertEquals(NuxeoPrincipalImpl.TransferableClone.class, ois.stack.get(1).getClass());
}
}
/**
* Checks the ancestor groups of the ABCD group with the following hierarchy:
*
* <pre>
* A B C D
* \/ \/
* AB CD
* \ /
* \ /
* ABCD
* </pre>
*/
@Test
public void testAncestorGroups() throws Exception {
DocumentModel groupABCD = getGroup("ABCD");
userManager.createGroup(groupABCD);
DocumentModel groupAB = getGroup("AB");
groupAB.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("ABCD"));
userManager.createGroup(groupAB);
DocumentModel groupCD = getGroup("CD");
groupCD.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("ABCD"));
userManager.createGroup(groupCD);
DocumentModel groupA = getGroup("A");
groupA.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("AB"));
userManager.createGroup(groupA);
DocumentModel groupB = getGroup("B");
groupB.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("AB"));
userManager.createGroup(groupB);
DocumentModel groupC = getGroup("C");
groupC.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("CD"));
userManager.createGroup(groupC);
DocumentModel groupD = getGroup("D");
groupD.setPropertyValue("group:subGroups", (Serializable) Collections.singletonList("CD"));
userManager.createGroup(groupD);
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("AB", "A", "B", "CD", "C", "D"),
userManager.getAncestorGroups("ABCD")));
}
}