package uk.ac.ebi.fg.myequivalents.managers; import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static java.lang.System.out; 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 java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import org.joda.time.DateTime; import org.junit.After; import org.junit.Before; import org.junit.Test; import uk.ac.ebi.fg.myequivalents.access_control.model.User; import uk.ac.ebi.fg.myequivalents.access_control.model.User.Role; import uk.ac.ebi.fg.myequivalents.dao.ServiceDAO; import uk.ac.ebi.fg.myequivalents.dao.access_control.UserDao; import uk.ac.ebi.fg.myequivalents.exceptions.SecurityException; import uk.ac.ebi.fg.myequivalents.managers.impl.db.DbAccessControlManager; import uk.ac.ebi.fg.myequivalents.managers.impl.db.DbManagerFactory; import uk.ac.ebi.fg.myequivalents.managers.interfaces.AccessControlManager; import uk.ac.ebi.fg.myequivalents.managers.interfaces.EntityMappingManager; import uk.ac.ebi.fg.myequivalents.managers.interfaces.ManagerFactory; import uk.ac.ebi.fg.myequivalents.managers.interfaces.ServiceManager; import uk.ac.ebi.fg.myequivalents.model.Entity; import uk.ac.ebi.fg.myequivalents.model.Repository; import uk.ac.ebi.fg.myequivalents.model.Service; import uk.ac.ebi.fg.myequivalents.resources.Resources; import uk.ac.ebi.fg.myequivalents.utils.jaxb.DateJaxbXmlAdapter; /** * JUnit tests for the access control features available from the {@link AccessControlManager} interface and its * {@link DbAccessControlManager database implementation}, as well as from DAOs like {@link UserDao}. * * <dl><dt>date</dt><dd>Apr 22, 2013</dd></dl> * @author Marco Brandizi * */ public class AccessControlManagerTest { private ManagerFactory mgrFactory = Resources.getInstance ().getMyEqManagerFactory (); private EntityManagerFactory emf = ((DbManagerFactory) mgrFactory).getEntityManagerFactory (); private EntityManager em = emf.createEntityManager (); private String adminPass = "test.password"; private String adminSecret = User.generateSecret (); private User adminUser = new User ( "test.admin", "Test", "Admin", adminPass, "test notes", Role.ADMIN, adminSecret ); private String userPass = "test.password"; private String userSecret = User.generateSecret (); private User user = new User ( "test.user", "Test", "User", userPass, "test notes", Role.VIEWER, userSecret ); private String editorPass = "test.password"; private String editorSecret = User.generateSecret (); private User editorUser = new User ( "test.editor", "Test Editor", "User", editorPass, "test editor notes", Role.EDITOR, editorSecret ); private UserDao userDao = new UserDao ( em ); /** * Stores an admin and a regular user to be used in the tests below. */ @Before public void init () { EntityTransaction ts = em.getTransaction (); ts.begin (); userDao.storeUnauthorized ( adminUser ); ts.commit (); ts = em.getTransaction (); ts.begin (); userDao.login ( adminUser.getEmail (), adminPass, true ); userDao.store ( user ); userDao.store ( editorUser ); ts.commit (); } /** * Cleans up test users. */ @After public void shutdown () { // Delete the regular user userDao = new UserDao ( em = emf.createEntityManager () ); EntityTransaction ts = em.getTransaction (); ts.begin (); userDao.login ( adminUser.getEmail (), adminPass, true ); userDao.delete ( user.getEmail () ); userDao.delete ( editorUser.getEmail () ); ts.commit (); userDao = new UserDao ( em = emf.createEntityManager () ); userDao.login ( adminUser.getEmail (), adminSecret ); assertNull ( "User not deleted!", userDao.findByEmail ( user.getEmail () ) ); // Delete the admin itself and now we should have clened after ourselves ts = em.getTransaction (); ts.begin (); userDao.deleteUnauthorized ( adminUser.getEmail () ); ts.commit (); userDao = new UserDao ( em = emf.createEntityManager () ); assertNull ( "Admin User not deleted!", userDao.findByEmailUnauthorized ( adminUser.getEmail () ) ); } /** * Test features available from the {@link UserDao}. */ @Test public void testUserDao () { // Must login with pass to change yourself EntityTransaction ts = em.getTransaction (); ts.begin (); userDao.login ( adminUser.getEmail (), adminSecret ); catchException ( userDao ).store ( user ); Exception caught = caughtException (); if ( !( caught instanceof SecurityException ) ) throw new IllegalStateException ( "User modification with API password should fail!" ); ts.rollback (); // Was the reg user saved? userDao = new UserDao ( em = emf.createEntityManager () ); userDao.login ( user.getEmail (), userSecret ); User userDB = userDao.findByEmail ( user.getEmail () ); assertNotNull ( "User not stored!", userDB ); out.println ( "Stored user: " + userDB ); // You can change non-critical data about yourself userDB.setNotes ( "Modified User Notes" ); ts = em.getTransaction (); ts.begin (); userDao.login ( user.getEmail (), userPass, true ); userDao.store ( userDB ); ts.commit (); userDB.setRole ( Role.ADMIN ); // But not stuff like role. ts.begin (); catchException ( userDao ).store ( userDB ); caught = caughtException (); if ( !( caught instanceof SecurityException ) ) throw new IllegalStateException ( "Unauthorised user role modification should fail!" ); // Unless you're an admin userDao.login ( adminUser.getEmail (), adminPass, true ); userDao.setRole ( userDB.getEmail (), Role.EDITOR ); ts.commit (); em.close (); // Reload changes see if they went fine. // userDao = new UserDao ( em = emf.createEntityManager () ); userDao.login ( user.getEmail (), userSecret ); userDB = userDao.findByEmail ( user.getEmail () ); assertNotNull ( "User not stored!", userDB ); out.println ( "Modified user: " + userDB ); assertNotNull( "user.notes not changed!", userDB.getName () ); assertFalse ( "User role not changed!", user.getRole ().equals ( userDB.getRole () ) ); // Same for deletion ts = em.getTransaction (); ts.begin (); catchException ( userDao ).delete ( adminUser.getEmail () ); assertTrue ( "Unauthorised user removal should fail!", caughtException () instanceof SecurityException ); // Deletion of yourself not possible userDao.login ( adminUser.getEmail (), adminPass, true ); catchException ( userDao ).delete ( adminUser.getEmail () ); if ( ! ( ( caught = caughtException () ) instanceof SecurityException ) ) throw new IllegalStateException ( "Error while checking failure of self-removal!", caught ); } /** * Tests user-related commands available from the {@link AccessControlManager}. */ @Test public void testAccessControlManagerForUser () { // Must login with pass to change these things AccessControlManager accMgr = mgrFactory.newAccessControlManager ( adminUser.getEmail (), adminSecret ); catchException ( accMgr ).storeUser ( user ); Exception caught = caughtException (); if ( ! ( caught instanceof SecurityException ) ) throw new IllegalStateException ( "User modification with API password should fail!" ); // Was the reg user saved? accMgr = mgrFactory.newAccessControlManager ( user.getEmail (), userSecret ); User userDB = accMgr.getUser ( user.getEmail () ); assertNotNull ( "User not stored!", userDB ); out.println ( "Stored user: " + userDB ); // You can change non-critical data about yourself userDB.setNotes ( "Modified User Notes" ); accMgr = mgrFactory.newAccessControlManagerFullAuth ( user.getEmail (), userPass ); accMgr.storeUser ( userDB ); // But not this! userDB.setRole ( Role.ADMIN ); // But not stuff like role. catchException ( accMgr ).storeUser ( userDB ); if ( ! ( (caught = caughtException ()) instanceof SecurityException ) ) throw new IllegalStateException ( "Unauthorised user role modification should fail!" ); // Unless you're an admin accMgr = mgrFactory.newAccessControlManagerFullAuth ( adminUser.getEmail (), adminPass ); accMgr.setUserRole ( userDB.getEmail (), Role.EDITOR ); // Reload changes see if they went fine. // accMgr = mgrFactory.newAccessControlManager ( user.getEmail (), userSecret ); userDB = accMgr.getUser ( user.getEmail () ); assertNotNull ( "User not stored!", userDB ); out.println ( "Modified user: " + userDB ); assertNotNull( "user.notes not changed!", userDB.getName () ); assertFalse ( "User role not changed!", user.getRole ().equals ( userDB.getRole () ) ); // Same for deletion catchException ( accMgr ).deleteUser ( adminUser.getEmail () ); if ( ! ( (caught = caughtException ()) instanceof SecurityException ) ) throw new IllegalStateException ( "Unauthorised user removal should fail!" ); // Deletion of yourself not possible accMgr = mgrFactory.newAccessControlManagerFullAuth ( adminUser.getEmail (), adminPass ); catchException ( accMgr ).deleteUser ( adminUser.getEmail () ); if ( ! ( ( caught = caughtException () ) instanceof SecurityException ) ) throw new IllegalStateException ( "Error while checking failure of self-removal!", caught ); } /** * Tests permission-related commands available from {@link AccessControlManager}. */ @Test public void testPermssionCommands () { Service service = new Service ( "test.perms.service1", "someType", "A Test Service", "The Description of a Test Service" ); ServiceManager servMgr = mgrFactory.newServiceManager ( editorUser.getEmail (), editorSecret ); servMgr.storeServices ( service ); EntityMappingManager emMgr = mgrFactory.newEntityMappingManager ( editorUser.getEmail (), editorSecret ); emMgr.storeMappings ( service.getName () + ":e1", service.getName () + ":e2" ); AccessControlManager accMgr = mgrFactory.newAccessControlManagerFullAuth ( adminUser.getEmail (), adminPass ); accMgr.setUserRole ( user.getEmail (), User.Role.EDITOR ); Date testDate = new DateTime ( 2013, 4, 25, 0, 0 ).toDate (); accMgr.setAuthenticationCredentials ( editorUser.getEmail (), editorSecret ); accMgr.setServicesVisibility ( "false", DateJaxbXmlAdapter.STR2DATE.marshal ( testDate ), true, service.getName () ); ServiceDAO servDao = new ServiceDAO ( ((DbManagerFactory) mgrFactory ).getEntityManagerFactory ().createEntityManager () ); Service serviceDB = servDao.findByName ( service.getName () ); assertNull ( "ServiceDAO returns a private service!", serviceDB ); serviceDB = servDao.findByName ( service.getName (), false ); out.println ( "Reloaded service:" ); out.println ( serviceDB ); assertFalse ( "Public Flag not stored!", serviceDB.getPublicFlag () ); assertEquals ( "Release date not stored!", testDate, serviceDB.getReleaseDate () ); assertFalse ( "The service should be private!", serviceDB.isPublic () ); Entity ent = emMgr.getMappings ( false, service.getName () + ":e1" ).getBundles ().iterator ().next ().getEntities ().iterator ().next (); assertFalse ( "setServicesVisibility() wasn't cascaded!", ent.getPublicFlag () ); assertEquals ( "setServicesVisibility() wasn't cascaded!", testDate, ent.getReleaseDate () ); servMgr.deleteServices ( service.getName () ); } /** * Tests cascading properties of service permission features, e.g., when you set a permission on a service and * that is cascaded to all its entities. */ @Test public void testServicePermissionCascading () { Repository repo = new Repository ( "test.perms.repo1", "A test repo 1", "Descr about A test Repo 1" ); repo.setPublicFlag ( true ); Service service = new Service ( "test.perms.service1", "someType", "A Test Service", "The Description of a Test Service" ); service.setPublicFlag ( null ); service.setReleaseDate ( null ); service.setRepository ( repo ); ServiceManager servMgr = mgrFactory.newServiceManager ( editorUser.getEmail (), editorSecret ); servMgr.storeServices ( service ); ServiceDAO servDao = new ServiceDAO ( ((DbManagerFactory) mgrFactory ).getEntityManagerFactory ().createEntityManager () ); Service serviceDB = servDao.findByName ( service.getName () ); assertNotNull ( "ServiceDAO doesn't return a cascade-public service!", serviceDB ); assertTrue ( "serviceDB.isPublic() is not true!", serviceDB.isPublic () ); } }