/* * Copyright 2006-2014 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.server.itests.sec; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; import ome.conditions.ApiUsageException; import ome.conditions.SecurityViolation; import ome.conditions.ValidationException; import ome.model.core.Image; import ome.model.internal.Permissions; import ome.model.meta.Experimenter; import ome.model.meta.ExperimenterGroup; import ome.model.meta.GroupExperimenterMap; import ome.server.itests.AbstractManagedContextTest; import ome.system.Login; import ome.system.Roles; import ome.system.ServiceFactory; import ome.util.IdBlock; import org.springframework.mail.MailSender; import org.testng.annotations.Test; public class AdminTest extends AbstractManagedContextTest { @Test public void testGetEventContext() throws Exception { iAdmin.getEventContext(); } // ~ IAdmin.createUser // ========================================================================= @Test(expectedExceptions = ApiUsageException.class) public void testUserAccountCreationWithNull() throws Exception { iAdmin.createUser(null, null); } @Test(expectedExceptions = ApiUsageException.class) public void testUserAccountCreationWithEmpty() throws Exception { Experimenter e = new Experimenter(); iAdmin.createUser(e, null); } @Test(expectedExceptions = ApiUsageException.class) public void testUserAccountCreationWithUnknownGroup() throws Exception { Experimenter e = new Experimenter(); iAdmin.createUser(e, uuid()); // uuid won't exist } @Test public void testUserAccountCreation() throws Exception { ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); Experimenter e = testExperimenter(); e = iAdmin.getExperimenter(iAdmin.createUser(e, g.getName())); assertNotNull(e.getEmail()); assertNotNull(e.getOmeName()); assertNotNull(e.getFirstName()); assertNotNull(e.getLastName()); int size = e.sizeOfGroupExperimenterMap(); assertTrue(String.format("%d not 2", size), size == 2); } // ~ IAdmin.createSystemUser // ========================================================================= @Test(expectedExceptions = ApiUsageException.class) public void testSysUserAccountCreationWithNull() throws Exception { iAdmin.createUser(null, null); } @Test(expectedExceptions = ApiUsageException.class) public void testSysUserAccountCreationWithEmpty() throws Exception { Experimenter e = new Experimenter(); iAdmin.createSystemUser(e); } @Test public void testSysUserAccountCreation() throws Exception { Experimenter e = testExperimenter(); e = iAdmin.getExperimenter(iAdmin.createSystemUser(e)); assertNotNull(e.getEmail()); assertNotNull(e.getOmeName()); assertNotNull(e.getFirstName()); assertNotNull(e.getLastName()); assertEquals(2, iAdmin.containedGroups(e.getId()).length); assertEquals(2, e.sizeOfGroupExperimenterMap()); } // ~ IAdmin.createExperimenter // ========================================================================= @Test(expectedExceptions = ApiUsageException.class) public void testExperimenterAccountCreationWithAllNulls() throws Exception { iAdmin.createExperimenter(null, null, (ome.model.meta.ExperimenterGroup[])null); } @Test(expectedExceptions = ApiUsageException.class) public void testExperimenterAccountCreationWithEmpty() throws Exception { Experimenter e = new Experimenter(); iAdmin.createExperimenter(e, null, (ome.model.meta.ExperimenterGroup[])null); } @Test public void testExperimenterAccountCreation() throws Exception { Experimenter e = testExperimenter(); e = iAdmin.getExperimenter(iAdmin.createExperimenter(e, new ExperimenterGroup(0L, false))); assertNotNull(e.getEmail()); assertNotNull(e.getOmeName()); assertNotNull(e.getFirstName()); assertNotNull(e.getLastName()); assertFalse(e.getLdap()); assertTrue(e.sizeOfGroupExperimenterMap() == 1); } @Test public void testExperimenterAccountCreationAndUpdateWithPassword() throws Exception { Experimenter e = testExperimenter(); e = iAdmin.getExperimenter(iAdmin.createExperimenterWithPassword(e, "password", new ExperimenterGroup(0L, false))); assertNotNull(e.getEmail()); assertNotNull(e.getOmeName()); assertNotNull(e.getFirstName()); assertNotNull(e.getLastName()); assertFalse(e.getLdap()); assertTrue(e.sizeOfGroupExperimenterMap() == 1); Login ul = new Login(e.getOmeName(), "password"); ServiceFactory usf = new ServiceFactory(ul); usf.getAdminService().getEventContext(); iAdmin.updateExperimenterWithPassword(e, "password2"); Login ul2 = new Login(e.getOmeName(), "password2"); ServiceFactory usf2 = new ServiceFactory(ul2); usf2.getAdminService().getEventContext(); } @Test(groups = "ticket:1021") public void testDefaultGroupNotAddedTwice() throws Exception { List<ExperimenterGroup> groups = iAdmin.lookupGroups(); ExperimenterGroup def = null, nonDef = null; for (ExperimenterGroup group : groups) { if (group.getName().equals("user") || group.getName().equals("system")) { continue; } if (def == null) { def = group; } else if (nonDef == null && ! def.getId().equals(group.getId())) { nonDef = group; } else { break; } } assertNotNull(def); assertNotNull(nonDef); assertFalse(def.getId().equals(nonDef.getId())); Experimenter e = testExperimenter(); long id = iAdmin.createExperimenter(e, def, nonDef); assertEquals(2, iAdmin.containedGroups(id).length); e = iAdmin.lookupExperimenter(e.getOmeName()); assertEquals("should be 2", 2, e.sizeOfGroupExperimenterMap()); e = testExperimenter(); id = iAdmin.createExperimenter(e, def, nonDef, def); e = iAdmin.lookupExperimenter(e.getOmeName()); assertEquals("should still be 2", 2, e.sizeOfGroupExperimenterMap()); } private ExperimenterGroup testGroup() { ExperimenterGroup g = new ExperimenterGroup(); g.setName(uuid()); g.setLdap(false); return g; } private Experimenter testExperimenter() { Experimenter e = new Experimenter(); e.setEmail("blah"); e.setFirstName("foo"); e.setLastName("bar"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); return e; } // ~ Groups // ========================================================================= @Test(groups = "ticket:293") public void testUserCanOnlySetDetailsOnOwnObject() throws Exception { Experimenter e1 = loginNewUser(); Image i = new Image(); i.setName("test"); i = iUpdate.saveAndReturnObject(i); // this user should not be able to change things Experimenter e2 = loginNewUserInOtherUsersGroup(e1); try { iAdmin.changeOwner(i, e2.getOmeName()); fail("secvio!"); } catch (SecurityViolation sv) { } try { iAdmin.changeGroup(i, "system"); fail("secvio!"); } catch (SecurityViolation sv) { } try { iAdmin.changePermissions(i, Permissions.EMPTY); fail("secvio!"); } catch (SecurityViolation sv) { } // guarantee that the client-side check for ticket:293 still holds. // see: TicketsUpTo500Test loginUser(e1.getOmeName()); iAdmin.changePermissions(i, Permissions.EMPTY); // iAdmin.changePermissions(i, Permissions.DEFAULT); loginRoot(); iAdmin.changePermissions(i, Permissions.EMPTY); // iAdmin.changePermissions(i, Permissions.DEFAULT); fail("review post-ticket:1434"); } @Test public void testUserCanOnlySetDetailsToOwnGroup() throws Exception { ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); Experimenter e1 = testExperimenter(); e1.setId(iAdmin.createUser(e1, g.getName())); ExperimenterGroup g1 = new ExperimenterGroup(), g2 = new ExperimenterGroup(); g1.setName(uuid()); g2.setName(uuid()); g1.setLdap(false); g2.setLdap(false); g1.setId(iAdmin.createGroup(g1)); g2.setId(iAdmin.createGroup(g2)); login(e1.getOmeName(), g.getName(), "Test"); Image i = new Image(); i.setName("test"); i = iUpdate.saveAndReturnObject(i); try { iAdmin.changeGroup(i, g2.getName()); fail("secvio!"); } catch (SecurityViolation sv) { // ok } // add the user to these groups and try again. iAdmin.addGroups(e1, g1, g2); // should now work. iAdmin.changeGroup(i, g2.getName()); } @Test(groups = {"ticket:343", "ticket:1434"}) public void testSetGroupOwner() throws Exception { ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); Experimenter e1 = testExperimenter(); e1.setId(iAdmin.createUser(e1, g.getName())); ExperimenterGroup g1 = new ExperimenterGroup(); g1.setName(uuid()); g1.setLdap(false); g1.setId(iAdmin.createGroup(g1)); loginRoot(); iAdmin.setGroupOwner(g1, e1); ExperimenterGroup test = iQuery .get(ExperimenterGroup.class, g1.getId()); boolean found = false; Iterator<GroupExperimenterMap> maps = test.iterateGroupExperimenterMap(); while (maps.hasNext()) { GroupExperimenterMap map = maps.next(); if (map.child().getId().equals(e1.getId())) { if (map.getOwner()) { found = true; } } } assertTrue(found); } // ~ chgrp // ========================================================================= @Test public void testUserUsesChgrpThroughAdmin() throws Exception { Experimenter e = loginNewUser(); // a second group loginRoot(); ExperimenterGroup g = new ExperimenterGroup(); g.setName(UUID.randomUUID().toString()); g.setLdap(false); g = iAdmin.getGroup(iAdmin.createGroup(g)); iAdmin.addGroups(e, g); loginUser(e.getOmeName()); // create a new image Image i = new Image(); i.setName(UUID.randomUUID().toString()); i = factory.getUpdateService().saveAndReturnObject(i); // it should be in some other group Long group = i.getDetails().getGroup().getId(); assertFalse(group.equals(g.getId())); // now let's try to change that group factory.getAdminService().changeGroup(i, g.getName()); Image copy = factory.getQueryService().get(Image.class, i.getId()); Long test = copy.getDetails().getGroup().getId(); assertFalse(test.equals(group)); assertTrue(test.equals(g.getId())); } // ~ IAdmin.setDefaultGroup // ========================================================================= @Test public void testSetDefaultGroup() throws Exception { loginRoot(); // test group String gid = uuid(); ExperimenterGroup g = new ExperimenterGroup(); g.setName(gid); g.setLdap(false); g = iAdmin.getGroup(iAdmin.createGroup(g)); // create a new user for the test Experimenter e = new Experimenter(); e.setFirstName("user admin setters"); e.setLastName("test"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); e = iAdmin.getExperimenter(iAdmin.createUser(e, gid)); // check current default group ExperimenterGroup def = iAdmin.getDefaultGroup(e.getId()); assertEquals(def.getId(), g.getId()); // new test group String gid2 = uuid(); ExperimenterGroup g2 = new ExperimenterGroup(); g2.setName(gid2); g2.setLdap(false); g2 = iAdmin.getGroup(iAdmin.createGroup(g2)); // now change iAdmin.addGroups(e, g2); iAdmin.setDefaultGroup(e, g2); // test def = iAdmin.getDefaultGroup(e.getId()); assertEquals(def.getId(), g2.getId()); } @Test(groups = "ticket:1109") public void testSetDefaultGroup2() throws Exception { Experimenter e = loginNewUser(); e = assertGetDefaultGroupAndContainedExperimenters(e); // new test group String gid2 = uuid(); ExperimenterGroup g2 = new ExperimenterGroup(); g2.setName(gid2); g2.setLdap(false); g2 = iAdmin.getGroup(iAdmin.createGroup(g2)); // now change iAdmin.addGroups(e, g2); iAdmin.setDefaultGroup(e, g2); assertEquals(g2.getId(), iAdmin.getDefaultGroup(e.getId()).getId()); e = assertGetDefaultGroupAndContainedExperimenters(e); } private Experimenter assertGetDefaultGroupAndContainedExperimenters( Experimenter e) { ExperimenterGroup g1 = iAdmin.getDefaultGroup(e.getId()); Experimenter[] members = iAdmin.containedExperimenters(g1.getId()); boolean found = false; for (int i = 0; i < members.length; i++) { if (members[i].getId().longValue() == e.getId().longValue()) { e = members[i]; found = true; break; } } assertTrue(found); assertEquals(g1.getId(), e.getGroupExperimenterMap(0).parent().getId()); return e; } // ~ IAdmin.addGroups & .removeGroups // ========================================================================= @Test public void testPlusAndMinusGroups() throws Exception { loginRoot(); ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); // create a new user for the test Experimenter e = new Experimenter(); e.setFirstName("user admin setters"); e.setLastName("test"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); e = iAdmin.getExperimenter(iAdmin.createUser(e, g.getName())); int size = e.sizeOfGroupExperimenterMap(); assertTrue(String.format("%d not 2", size), size == 2); // two new test groups ExperimenterGroup g1 = new ExperimenterGroup(); g1.setName(UUID.randomUUID().toString()); g1.setLdap(false); g1 = iAdmin.getGroup(iAdmin.createGroup(g1)); ExperimenterGroup g2 = new ExperimenterGroup(); g2.setName(UUID.randomUUID().toString()); g2.setLdap(false); g2 = iAdmin.getGroup(iAdmin.createGroup(g2)); iAdmin.addGroups(e, g1, g2); // test e = iAdmin.lookupExperimenter(e.getOmeName()); assertTrue(e.linkedExperimenterGroupList().size() == 4); iAdmin.removeGroups(e, g1); e = iAdmin.lookupExperimenter(e.getOmeName()); assertTrue(e.linkedExperimenterGroupList().size() == 3); } // ~ IAdmin.contained* // ========================================================================= @Test public void testContainedUsersAndGroups() throws Exception { loginRoot(); ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); // create a new user for the test Experimenter e = new Experimenter(); e.setFirstName("user admin setters"); e.setLastName("test"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); e = iAdmin.getExperimenter(iAdmin.createUser(e, g.getName())); // two new test groups ExperimenterGroup g1 = new ExperimenterGroup(); g1.setName(UUID.randomUUID().toString()); g1.setLdap(false); g1 = iAdmin.getGroup(iAdmin.createGroup(g1)); ExperimenterGroup g2 = new ExperimenterGroup(); g2.setName(UUID.randomUUID().toString()); g2.setLdap(false); g2 = iAdmin.getGroup(iAdmin.createGroup(g2)); // add them all together iAdmin.addGroups(e, g1, g2); // test Experimenter[] es = iAdmin.containedExperimenters(g1.getId()); assertEquals(1, es.length); assertTrue(es[0].getId().equals(e.getId())); ExperimenterGroup[] gs = iAdmin.containedGroups(e.getId()); assertEquals(4, gs.length); List<Long> ids = new ArrayList<Long>(); for (ExperimenterGroup group : gs) { ids.add(group.getId()); } assertTrue(ids.contains(1L)); assertTrue(ids.contains(g1.getId())); assertTrue(ids.contains(g2.getId())); } // ~ IAdmin.lookup* & .get* // ========================================================================= @Test public void testLookupAndGet() throws Exception { loginRoot(); // create a new user for the test Experimenter e = new Experimenter(); e.setFirstName("user admin setters"); e.setLastName("test"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); e = iAdmin.getExperimenter(iAdmin.createSystemUser(e)); loginUser(e.getOmeName()); Experimenter test_e = iAdmin.lookupExperimenter(e.getOmeName()); ExperimenterGroup test_g = iAdmin.getGroup(0L); assertTrue(test_e.linkedExperimenterGroupList().size() == 2); assertTrue(test_g.eachLinkedExperimenter(new IdBlock()).contains( e.getId())); } @Test(groups = "ticket:910") public void testLookupGroupsReturnsExperimentersWithGroupsLoaded() { loginRoot(); List<ExperimenterGroup> list = iAdmin.lookupGroups(); ExperimenterGroup group = list.get(0); Experimenter exp = group.linkedExperimenterList().get(0); assertNotNull(exp.getPrimaryGroupExperimenterMap()); } // ~ Passwords // ========================================================================= /** * using this test to visually inspect the log output for changeUserPassword * it will fail and so there should be no side-effects. */ // SECURITY CHECKS AREN'T DONE FROM WITHIN. NEED TO HANDLE THIS!!! @Test(groups = { "ticket:209", "security", "broken" }) public void testUnallowedPasswordChange() throws Exception { loginRoot(); // and a new group ExperimenterGroup g = new ExperimenterGroup(); g.setName(UUID.randomUUID().toString()); g.setLdap(false); iAdmin.createGroup(g); // create a new user for the test Experimenter e = new Experimenter(); e.setFirstName("user admin setters"); e.setLastName("test"); e.setOmeName(UUID.randomUUID().toString()); e.setLdap(false); iAdmin.createUser(e, g.getName()); loginUser(e.getOmeName()); try { iAdmin.changeUserPassword("root", "THIS SHOULD NOT BE VISIBLE."); fail("secvio!"); } catch (SecurityViolation ex) { // ok. } } // ~ Security context // ========================================================================= @Test(groups = "ticket:328") public void testRoles() throws Exception { loginRoot(); Roles r = iAdmin.getSecurityRoles(); assertNotNull(r.getRootName()); assertNotNull(r.getSystemGroupName()); assertNotNull(r.getUserGroupName()); } // ~ Deletion // ========================================================================= public void testDeleteGroup() { ExperimenterGroup g = testGroup(); long gid = iAdmin.createGroup(g); Experimenter e1 = testExperimenter(); iAdmin.createUser(e1, g.getName()); iAdmin.deleteGroup(new ExperimenterGroup(gid, false)); } public void testDeleteUser() { ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); Experimenter e1 = testExperimenter(); long uid = iAdmin.createUser(e1, g.getName()); iAdmin.deleteExperimenter(new Experimenter(uid, false)); } @Test(expectedExceptions = ValidationException.class) public void testDeleteUserWithObject() { ExperimenterGroup g = testGroup(); iAdmin.createGroup(g); Experimenter e1 = testExperimenter(); long uid = iAdmin.createUser(e1, g.getName()); // Now make something loginUser(e1.getOmeName()); iUpdate.saveObject(new Image("name")); loginRoot(); iAdmin.deleteExperimenter(new Experimenter(uid, false)); } // Non private creation (#1204) // ========================================================================= @Test(groups = "ticket:1204") public void testUserCreate() { Experimenter e = loginNewUser(); // This creates all the types of interest: user, group, link loginRoot(); List<ExperimenterGroup> groups = iQuery.findAll(ExperimenterGroup.class, null); assertWorldReadable(groups); groups = null; List<GroupExperimenterMap> maps = iQuery.findAll(GroupExperimenterMap.class, null); assertWorldReadable(maps); maps = null; List<Experimenter> users = iQuery.findAll(Experimenter.class, null); assertWorldReadable(users); users = null; } // ~ Bugs // ========================================================================= public void testSetDefaultGroupCanNotUpateRows() throws Exception { Experimenter e1 = loginNewUser(); Experimenter e2 = loginNewUser(); loginRoot(); ExperimenterGroup eg = iAdmin.getDefaultGroup(e1.getId()); iAdmin.addGroups(e2, eg); iAdmin.setDefaultGroup(e2, eg); } public void testLookupExperimentersOnlyReturnsEachUserOnce() throws Exception { Experimenter e = loginNewUser(); loginRoot(); ExperimenterGroup g = new ExperimenterGroup(uuid(), false); g = new ExperimenterGroup( iAdmin.createGroup(g), false); iAdmin.addGroups(e, g); loginUser(e.getOmeName()); Set<Long> seen = new HashSet<Long>(); List<Experimenter> list = iAdmin.lookupExperimenters(); for (Experimenter user : list) { assertFalse(String.format("Already saw %s in %s", user, list), seen.contains(user.getId())); seen.add(user.getId()); } } public void testReportForgottenPassword() throws Exception { MailSender old = null; try { old = setNoopMailSender(); Experimenter e = loginNewUser(); loginRoot(); e = iQuery.get(Experimenter.class, e.getId()); e.setEmail("test@localhost"); iAdmin.updateExperimenter(e); loginUser(e.getOmeName()); iAdmin.reportForgottenPassword(e.getOmeName(), e.getEmail()); } finally { setMailSender(old); } } }