/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import org.junit.Assert; import org.apache.commons.io.FileUtils; import org.geoserver.platform.resource.Files; import org.geoserver.security.GeoServerRoleService; import org.geoserver.security.GeoServerRoleStore; import org.geoserver.security.event.RoleLoadedEvent; import org.geoserver.security.event.RoleLoadedListener; import org.geoserver.security.impl.AbstractRoleServiceTest; import org.geoserver.security.impl.GeoServerRole; import org.geoserver.security.impl.GeoServerUser; import org.geoserver.security.impl.Util; import org.geoserver.test.SystemTest; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; @Category(SystemTest.class) public class XMLRoleServiceTest extends AbstractRoleServiceTest { static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.security.xml"); @Override public GeoServerRoleService createRoleService(String serviceName) throws Exception { return createRoleService(serviceName,XMLConstants.FILE_RR); } @Before public void cleraRoleService() throws Exception { store.clear(); store.store(); } protected GeoServerRoleService createRoleService(String serviceName, String xmlFileName) throws Exception { XMLRoleServiceConfig gaConfig = (XMLRoleServiceConfig) getSecurityManager().loadRoleServiceConfig(serviceName); if (gaConfig == null) { gaConfig = new XMLRoleServiceConfig(); gaConfig.setName(serviceName); } gaConfig.setClassName(XMLRoleService.class.getName()); gaConfig.setCheckInterval(1000); gaConfig.setFileName(xmlFileName); gaConfig.setValidating(true); getSecurityManager().saveRoleService(gaConfig/*,isNewRoleService(serviceName)*/); return getSecurityManager().loadRoleService(serviceName); } @Test public void testCopyFrom() throws Exception { GeoServerRoleService service1 = createRoleService("copyFrom"); GeoServerRoleService service2 = createRoleService("copyTo"); GeoServerRoleStore store1 = createStore(service1); GeoServerRoleStore store2 = createStore(service2); store1.clear(); checkEmpty(store1); insertValues(store1); Util.copyFrom(store1, store2); store1.clear(); checkEmpty(store1); checkValuesInserted(store2); } @Test public void testDefault() throws Exception { GeoServerRoleService service = getSecurityManager().loadRoleService(XMLRoleService.DEFAULT_NAME); assertEquals(2, service.getRoles().size()); GeoServerRole adminRole = service.getRoleByName(XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE); GeoServerRole groupAdminRole = service.getRoleByName(XMLRoleService.DEFAULT_LOCAL_GROUP_ADMIN_ROLE); assertEquals(0,service.getGroupNamesForRole(adminRole).size()); assertEquals(0,service.getGroupNamesForRole(groupAdminRole).size()); assertEquals(1,service.getUserNamesForRole(adminRole).size()); assertEquals(0,service.getUserNamesForRole(groupAdminRole).size()); assertEquals(1, service.getRolesForUser(GeoServerUser.ADMIN_USERNAME).size()); assertTrue(service.getRolesForUser(GeoServerUser.ADMIN_USERNAME).contains(adminRole)); } @Test public void testLocking() throws Exception { File xmlFile = File.createTempFile("roles", ".xml"); try { FileUtils.copyURLToFile(getClass().getResource("rolesTemplate.xml"), xmlFile); GeoServerRoleService service1 = createRoleService("locking1", xmlFile.getCanonicalPath()); GeoServerRoleService service2 = createRoleService("locking2", xmlFile.getCanonicalPath()); GeoServerRoleStore store1 = createStore(service1); GeoServerRoleStore store2 = createStore(service2); GeoServerRole role_test1 = store1.createRoleObject("ROLE_TEST"); GeoServerRole role_test2 = store2.createRoleObject("ROLE_TEST"); // obtain a lock store1.addRole(role_test1); boolean fail; String failMessage = "Concurrent lock not allowed"; fail = true; try { store2.clear(); } catch (IOException ex) { fail=false; } if (fail) Assert.fail(failMessage); // release lock store1.load(); // get lock store2.addRole(role_test1); fail = true; try { store1.clear(); } catch (IOException ex) { fail=false; } if (fail) Assert.fail(failMessage); // release lock store2.store(); store1.clear(); store1.store(); // // end of part one, now check all modifying methods // obtain a lock store1.addRole(role_test1); fail = true; try { store2.associateRoleToGroup(role_test2, "agroup"); } catch (IOException ex) { try { store2.disAssociateRoleFromGroup(role_test2, "agroup"); } catch (IOException e) { fail = false; } } if (fail) Assert.fail(failMessage); fail = true; try { store2.associateRoleToUser(role_test2, "auser"); } catch (IOException ex) { try { store2.disAssociateRoleFromUser(role_test2, "auser"); } catch (IOException e) { fail = false; } } if (fail) Assert.fail(failMessage); fail = true; try { store2.updateRole(role_test2); } catch (IOException ex) { try { store2.removeRole(role_test2); } catch (IOException ex1) { try { store2.addRole(role_test2); } catch (IOException ex2) { fail = false; } } } if (fail) Assert.fail(failMessage); fail = true; try { store2.clear(); } catch (IOException ex) { try { store2.store(); } catch (IOException e) { fail=false; } } if (fail) Assert.fail(failMessage); fail = true; try { store2.setParentRole(role_test1, null); } catch (IOException ex) { fail=false; } if (fail) Assert.fail(failMessage); } finally { xmlFile.delete(); } } @Test public void testDynamicReload() throws Exception { Files.schedule(200,TimeUnit.MILLISECONDS); File xmlFile = File.createTempFile("roles", ".xml"); try { FileUtils.copyURLToFile(getClass().getResource("rolesTemplate.xml"),xmlFile); GeoServerRoleService service1 = createRoleService("reload1",xmlFile.getCanonicalPath()); GeoServerRoleService service2 = createRoleService("reload2",xmlFile.getCanonicalPath()); GeoServerRoleStore store1= createStore(service1); GeoServerRole role_test1 = store1.createRoleObject("ROLE_TEST1"); checkEmpty(service1); checkEmpty(service2); // prepare for syncing class CheckRoleLoaded implements RoleLoadedListener { public int notified = 0; @Override public void rolesChanged(RoleLoadedEvent event) { synchronized (this) { this.notifyAll(); notified++; } } }; CheckRoleLoaded listener = new CheckRoleLoaded(); service2.registerRoleLoadedListener(listener); // modifiy store1 store1.addRole(role_test1); store1.store(); assertTrue(service1.getRoles().size()==1); // increment lastmodified adding a second manually, the test is too fast xmlFile.setLastModified(xmlFile.lastModified()+1000); // wait for the listener to unlock when // service 2 triggers a load event synchronized (listener) { if(listener.notified == 0 ){ listener.wait(); // wait 4 seconds } } assertTrue("notification expected",listener.notified > 0 ); // here comes the magic !!! assertTrue(service2.getRoles().size()==1); } finally { Files.schedule(10,TimeUnit.SECONDS); xmlFile.delete(); } } }