diff --git a/dspace-api/src/main/java/org/dspace/alerts/AllowSessionsEnum.java b/dspace-api/src/main/java/org/dspace/alerts/AllowSessionsEnum.java index 0c8b3f72d2..b43b350f7c 100644 --- a/dspace-api/src/main/java/org/dspace/alerts/AllowSessionsEnum.java +++ b/dspace-api/src/main/java/org/dspace/alerts/AllowSessionsEnum.java @@ -8,7 +8,14 @@ package org.dspace.alerts; /** - * Enum representing the options for allowing sessions + * Enum representing the options for allowing sessions: + * ALLOW_ALL_SESSIONS - Will allow all users to log in and continue their sessions + * ALLOW_CURRENT_SESSIONS_ONLY - Will prevent non admin users from logging in, however logged-in users + * will remain logged in + * ALLOW_ADMIN_SESSIONS_ONLY - Only admin users can log in, non admin sessions will be interrupted + * + * NOTE: This functionality can be stored in the database, but no support is present right now to interrupt and prevent + * sessions. */ public enum AllowSessionsEnum { ALLOW_ALL_SESSIONS(0), diff --git a/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlertServiceImpl.java b/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlertServiceImpl.java index cc59289e42..d0e98139d2 100644 --- a/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlertServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/alerts/SystemWideAlertServiceImpl.java @@ -20,7 +20,6 @@ import org.dspace.authorize.service.AuthorizeService; import org.dspace.core.Context; import org.dspace.core.LogHelper; import org.dspace.eperson.EPerson; -import org.dspace.eperson.service.EPersonService; import org.springframework.beans.factory.annotation.Autowired; /** @@ -37,12 +36,15 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService { @Autowired private AuthorizeService authorizeService; - @Autowired - private EPersonService ePersonService; - + @Override public SystemWideAlert create(final Context context, final String message, final AllowSessionsEnum allowSessionsType, - final Date countdownTo, final boolean active) throws SQLException { + final Date countdownTo, final boolean active) throws SQLException, + AuthorizeException { + if (!authorizeService.isAdmin(context)) { + throw new AuthorizeException( + "Only administrators can create a system-wide alert"); + } SystemWideAlert systemWideAlert = new SystemWideAlert(); systemWideAlert.setMessage(message); systemWideAlert.setAllowSessions(allowSessionsType); @@ -59,36 +61,52 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService { return createdAlert; } + @Override public SystemWideAlert find(final Context context, final int alertId) throws SQLException { return systemWideAlertDAO.findByID(context, SystemWideAlert.class, alertId); } + @Override public List findAll(final Context context) throws SQLException { return systemWideAlertDAO.findAll(context, SystemWideAlert.class); } + @Override public List findAll(final Context context, final int limit, final int offset) throws SQLException { return systemWideAlertDAO.findAll(context, limit, offset); } + @Override public List findAllActive(final Context context, final int limit, final int offset) throws SQLException { return systemWideAlertDAO.findAllActive(context, limit, offset); } + @Override public void delete(final Context context, final SystemWideAlert systemWideAlert) throws SQLException, IOException, AuthorizeException { + if (!authorizeService.isAdmin(context)) { + throw new AuthorizeException( + "Only administrators can create a system-wide alert"); + } systemWideAlertDAO.delete(context, systemWideAlert); log.info(LogHelper.getHeader(context, "system_wide_alert_create", "System Wide Alert with ID " + systemWideAlert.getID() + " has been deleted")); } - public void update(final Context context, final SystemWideAlert systemWideAlert) throws SQLException { + @Override + public void update(final Context context, final SystemWideAlert systemWideAlert) + throws SQLException, AuthorizeException { + if (!authorizeService.isAdmin(context)) { + throw new AuthorizeException( + "Only administrators can create a system-wide alert"); + } systemWideAlertDAO.save(context, systemWideAlert); } + @Override public boolean canNonAdminUserLogin(Context context) throws SQLException { List active = findAllActive(context, 1, 0); if (active == null || active.isEmpty()) { @@ -97,6 +115,7 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService { return active.get(0).getAllowSessions() == AllowSessionsEnum.ALLOW_ALL_SESSIONS.getValue(); } + @Override public boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException { if (authorizeService.isAdmin(context, ePerson)) { return true; diff --git a/dspace-api/src/main/java/org/dspace/alerts/service/SystemWideAlertService.java b/dspace-api/src/main/java/org/dspace/alerts/service/SystemWideAlertService.java index 85b6ad304c..cf23130884 100644 --- a/dspace-api/src/main/java/org/dspace/alerts/service/SystemWideAlertService.java +++ b/dspace-api/src/main/java/org/dspace/alerts/service/SystemWideAlertService.java @@ -19,7 +19,7 @@ import org.dspace.core.Context; import org.dspace.eperson.EPerson; /** - * An interface for the ProcessService with methods regarding the SystemWideAlert workload + * An interface for the SystemWideAlertService with methods regarding the SystemWideAlert workload */ public interface SystemWideAlertService { @@ -36,7 +36,7 @@ public interface SystemWideAlertService { */ SystemWideAlert create(Context context, String message, AllowSessionsEnum allowSessionsType, Date countdownTo, boolean active - ) throws SQLException; + ) throws SQLException, AuthorizeException; /** * This method will retrieve a SystemWideAlert object from the Database with the given ID @@ -96,7 +96,7 @@ public interface SystemWideAlertService { * @param systemWideAlert The SystemWideAlert object to be updated * @throws SQLException If something goes wrong */ - void update(Context context, SystemWideAlert systemWideAlert) throws SQLException; + void update(Context context, SystemWideAlert systemWideAlert) throws SQLException, AuthorizeException; /** diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.4_2022.12.15__system_wide_alerts.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.5_2022.12.15__system_wide_alerts.sql similarity index 100% rename from dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.4_2022.12.15__system_wide_alerts.sql rename to dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.5_2022.12.15__system_wide_alerts.sql diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V7.4_2022.12.15__system_wide_alerts.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V7.5_2022.12.15__system_wide_alerts.sql similarity index 100% rename from dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V7.4_2022.12.15__system_wide_alerts.sql rename to dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V7.5_2022.12.15__system_wide_alerts.sql diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.4_2022.12.15__system_wide_alerts.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.5_2022.12.15__system_wide_alerts.sql similarity index 100% rename from dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.4_2022.12.15__system_wide_alerts.sql rename to dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.5_2022.12.15__system_wide_alerts.sql diff --git a/dspace-api/src/test/java/org/dspace/alerts/SystemWideAlertServiceTest.java b/dspace-api/src/test/java/org/dspace/alerts/SystemWideAlertServiceTest.java new file mode 100644 index 0000000000..7355037ff1 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/alerts/SystemWideAlertServiceTest.java @@ -0,0 +1,202 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.alerts; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.Logger; +import org.dspace.alerts.dao.SystemWideAlertDAO; +import org.dspace.alerts.service.SystemWideAlertService; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.core.Context; +import org.dspace.eperson.EPerson; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SystemWideAlertServiceTest { + + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SystemWideAlertService.class); + + @InjectMocks + private SystemWideAlertServiceImpl systemWideAlertService; + + @Mock + private SystemWideAlertDAO systemWideAlertDAO; + + @Mock + private AuthorizeService authorizeService; + + @Mock + private Context context; + + @Mock + private SystemWideAlert systemWideAlert; + + @Mock + private EPerson eperson; + + + @Test + public void testCreate() throws Exception { + // Mock admin state + when(authorizeService.isAdmin(context)).thenReturn(true); + + // Declare objects utilized in unit test + SystemWideAlert systemWideAlert = new SystemWideAlert(); + systemWideAlert.setMessage("Test message"); + systemWideAlert.setAllowSessions(AllowSessionsEnum.ALLOW_ALL_SESSIONS); + systemWideAlert.setCountdownTo(null); + systemWideAlert.setActive(true); + + // Mock DAO to return our defined SystemWideAlert + when(systemWideAlertDAO.create(any(), any())).thenReturn(systemWideAlert); + + // The newly created SystemWideAlert's message should match our mocked SystemWideAlert's message + SystemWideAlert result = systemWideAlertService.create(context, "Test message", + AllowSessionsEnum.ALLOW_ALL_SESSIONS, null, true); + assertEquals("TestCreate 0", systemWideAlert.getMessage(), result.getMessage()); + // The newly created SystemWideAlert should match our mocked SystemWideAlert + assertEquals("TestCreate 1", systemWideAlert, result); + } + + + @Test + public void testFindAll() throws Exception { + // Declare objects utilized in unit test + List systemWideAlertList = new ArrayList<>(); + + // The SystemWideAlert(s) reported from our mocked state should match our systemWideAlertList + assertEquals("TestFindAll 0", systemWideAlertList, systemWideAlertService.findAll(context)); + } + + @Test + public void testFind() throws Exception { + // Mock DAO to return our mocked SystemWideAlert + when(systemWideAlertService.find(context, 0)).thenReturn(systemWideAlert); + + // The SystemWideAlert reported from our ID should match our mocked SystemWideAlert + assertEquals("TestFind 0", systemWideAlert, systemWideAlertService.find(context, 0)); + } + + @Test + public void testFindAllActive() throws Exception { + // Declare objects utilized in unit test + List systemWideAlertList = new ArrayList<>(); + + // The SystemWideAlert(s) reported from our mocked state should match our systemWideAlertList + assertEquals("TestFindAllActive 0", systemWideAlertList, systemWideAlertService.findAllActive(context, 10, 0)); + } + + + @Test + public void testUpdate() throws Exception { + // Mock admin state + when(authorizeService.isAdmin(context)).thenReturn(true); + + // Invoke impl of method update() + systemWideAlertService.update(context, systemWideAlert); + + // Verify systemWideAlertDAO.save was invoked twice to confirm proper invocation of both impls of update() + Mockito.verify(systemWideAlertDAO, times(1)).save(context, systemWideAlert); + } + + @Test + public void testDelete() throws Exception { + // Mock admin state + when(authorizeService.isAdmin(context)).thenReturn(true); + + // Invoke method delete() + systemWideAlertService.delete(context, systemWideAlert); + + // Verify systemWideAlertDAO.delete() ran once to confirm proper invocation of delete() + Mockito.verify(systemWideAlertDAO, times(1)).delete(context, systemWideAlert); + } + + @Test + public void canNonAdminUserLoginTrueTest() throws Exception { + // Mock the alert state + when(systemWideAlert.getAllowSessions()).thenReturn(AllowSessionsEnum.ALLOW_ALL_SESSIONS.getValue()); + + // Mock DAO to return our defined systemWideAlertList + List systemWideAlertList = new ArrayList<>(); + systemWideAlertList.add(systemWideAlert); + when(systemWideAlertDAO.findAllActive(context, 1, 0)).thenReturn(systemWideAlertList); + + // Assert the non admin users can log in + assertTrue("CanNonAdminUserLogin 0", systemWideAlertService.canNonAdminUserLogin(context)); + } + + @Test + public void canNonAdminUserLoginFalseTest() throws Exception { + // Mock the alert state + when(systemWideAlert.getAllowSessions()).thenReturn(AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY.getValue()); + + // Mock DAO to return our defined systemWideAlertList + List systemWideAlertList = new ArrayList<>(); + systemWideAlertList.add(systemWideAlert); + when(systemWideAlertDAO.findAllActive(context, 1, 0)).thenReturn(systemWideAlertList); + + // Assert the non admin users can log in + assertFalse("CanNonAdminUserLogin 1", systemWideAlertService.canNonAdminUserLogin(context)); + } + + @Test + public void canUserMaintainSessionAdminTest() throws Exception { + // Assert the admin user can log in + assertTrue("CanUserMaintainSession 0", systemWideAlertService.canNonAdminUserLogin(context)); + } + @Test + public void canUserMaintainSessionTrueTest() throws Exception { + // Mock admin state + when(authorizeService.isAdmin(context, eperson)).thenReturn(false); + + // Mock the alert state + when(systemWideAlert.getAllowSessions()).thenReturn(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue()); + + // Mock DAO to return our defined systemWideAlertList + List systemWideAlertList = new ArrayList<>(); + systemWideAlertList.add(systemWideAlert); + when(systemWideAlertDAO.findAllActive(context, 1, 0)).thenReturn(systemWideAlertList); + + // Assert the non admin users can main session + assertTrue("CanUserMaintainSession 1", systemWideAlertService.canUserMaintainSession(context, eperson)); + } + + @Test + public void canUserMaintainSessionFalseTest() throws Exception { + // Mock admin state + when(authorizeService.isAdmin(context, eperson)).thenReturn(false); + + // Mock the alert state + when(systemWideAlert.getAllowSessions()).thenReturn(AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY.getValue()); + + // Mock DAO to return our defined systemWideAlertList + List systemWideAlertList = new ArrayList<>(); + systemWideAlertList.add(systemWideAlert); + when(systemWideAlertDAO.findAllActive(context, 1, 0)).thenReturn(systemWideAlertList); + + // Assert the non admin users cannot main session + assertFalse("CanUserMaintainSession 2", systemWideAlertService.canUserMaintainSession(context, eperson)); + } + + + +} diff --git a/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java b/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java index 3306ced8f4..05bb659ac5 100644 --- a/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java @@ -13,6 +13,7 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.dspace.alerts.service.SystemWideAlertService; import org.dspace.app.requestitem.factory.RequestItemServiceFactory; import org.dspace.app.requestitem.service.RequestItemService; import org.dspace.authorize.AuthorizeException; @@ -102,6 +103,7 @@ public abstract class AbstractBuilder { static OrcidHistoryService orcidHistoryService; static OrcidQueueService orcidQueueService; static OrcidTokenService orcidTokenService; + static SystemWideAlertService systemWideAlertService; protected Context context; @@ -161,6 +163,8 @@ public abstract class AbstractBuilder { orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService(); orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService(); orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService(); + systemWideAlertService = DSpaceServicesFactory.getInstance().getServiceManager() + .getServicesByType(SystemWideAlertService.class).get(0); } @@ -194,6 +198,7 @@ public abstract class AbstractBuilder { requestItemService = null; versioningService = null; orcidTokenService = null; + systemWideAlertService = null; } diff --git a/dspace-api/src/test/java/org/dspace/builder/SystemWideAlertBuilder.java b/dspace-api/src/test/java/org/dspace/builder/SystemWideAlertBuilder.java new file mode 100644 index 0000000000..dbc902b97a --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/builder/SystemWideAlertBuilder.java @@ -0,0 +1,112 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.builder; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Date; + +import org.dspace.alerts.AllowSessionsEnum; +import org.dspace.alerts.SystemWideAlert; +import org.dspace.alerts.service.SystemWideAlertService; +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.Context; +import org.dspace.scripts.Process; + +public class SystemWideAlertBuilder extends AbstractBuilder { + + private SystemWideAlert systemWideAlert; + + protected SystemWideAlertBuilder(Context context) { + super(context); + } + + public static SystemWideAlertBuilder createSystemWideAlert(Context context, String message) + throws SQLException, AuthorizeException { + SystemWideAlertBuilder systemWideAlertBuilder = new SystemWideAlertBuilder(context); + return systemWideAlertBuilder.create(context, message, AllowSessionsEnum.ALLOW_ALL_SESSIONS, null, false); + } + + private SystemWideAlertBuilder create(Context context, String message, AllowSessionsEnum allowSessionsType, + Date countdownTo, boolean active) + throws SQLException, AuthorizeException { + this.context = context; + this.systemWideAlert = systemWideAlertService.create(context, message, allowSessionsType, countdownTo, active); + return this; + } + + public SystemWideAlertBuilder withAllowSessions(AllowSessionsEnum allowSessionsType) { + systemWideAlert.setAllowSessions(allowSessionsType); + return this; + } + + public SystemWideAlertBuilder withCountdownDate(Date countdownTo) { + systemWideAlert.setCountdownTo(countdownTo); + return this; + } + + public SystemWideAlertBuilder isActive(boolean isActive) { + systemWideAlert.setActive(isActive); + return this; + } + + @Override + public void cleanup() throws Exception { + try (Context c = new Context()) { + c.setDispatcher("noindex"); + c.turnOffAuthorisationSystem(); + // Ensure object and any related objects are reloaded before checking to see what needs cleanup + systemWideAlert = c.reloadEntity(systemWideAlert); + if (systemWideAlert != null) { + delete(c, systemWideAlert); + } + c.complete(); + indexingService.commit(); + } + } + + @Override + public SystemWideAlert build() { + try { + systemWideAlertService.update(context, systemWideAlert); + context.dispatchEvents(); + indexingService.commit(); + } catch (Exception e) { + return null; + } + return systemWideAlert; + } + + + @Override + protected SystemWideAlertService getService() { + return systemWideAlertService; + } + + public void delete(Context c, SystemWideAlert alert) throws Exception { + if (alert != null) { + getService().delete(c, alert); + } + } + + public static void deleteProcess(Integer integer) throws SQLException, IOException { + try (Context c = new Context()) { + c.turnOffAuthorisationSystem(); + Process process = processService.find(c, integer); + if (process != null) { + try { + processService.delete(c, process); + } catch (AuthorizeException e) { + // cannot occur, just wrap it to make the compiler happy + throw new RuntimeException(e); + } + } + c.complete(); + } + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SystemWideAlertRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SystemWideAlertRestRepository.java index bdca9eaf69..6b2e28ebee 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SystemWideAlertRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SystemWideAlertRestRepository.java @@ -23,10 +23,12 @@ import org.apache.logging.log4j.Logger; import org.dspace.alerts.AllowSessionsEnum; import org.dspace.alerts.SystemWideAlert; import org.dspace.alerts.service.SystemWideAlertService; +import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.SystemWideAlertRest; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.service.AuthorizeService; import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -46,6 +48,9 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository findAll(Context context, Pageable pageable) { try { List systemWideAlerts = systemWideAlertService.findAll(context, pageable.getPageSize(), @@ -118,12 +138,13 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository all = systemWideAlertService.findAll(context); if (!all.isEmpty()) { throw new DSpaceBadRequestException("A system wide alert already exists, no new value can be created. " + @@ -156,6 +177,29 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository findAllActive(Pageable pageable) { + Context context = obtainContext(); + try { + List systemWideAlerts = + systemWideAlertService.findAllActive(context, + pageable.getPageSize(), + Math.toIntExact( + pageable.getOffset())); + return converter.toRestPage(systemWideAlerts, pageable, utils.obtainProjection()); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + + } + @Override public Class getDomainClass() { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SystemWideAlertRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SystemWideAlertRestRepositoryIT.java index 648721f5e6..0a79452f21 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SystemWideAlertRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SystemWideAlertRestRepositoryIT.java @@ -19,65 +19,50 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.io.IOException; -import java.sql.SQLException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.dspace.alerts.AllowSessionsEnum; import org.dspace.alerts.SystemWideAlert; -import org.dspace.alerts.service.SystemWideAlertService; import org.dspace.app.rest.model.SystemWideAlertRest; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; -import org.dspace.authorize.AuthorizeException; -import org.junit.After; +import org.dspace.builder.SystemWideAlertBuilder; import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; /** * Test class to test the operations in the SystemWideAlertRestRepository */ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrationTest { - private static final Logger log = LogManager.getLogger(SystemWideAlertRestRepositoryIT.class); - - @Autowired - private SystemWideAlertService systemWideAlertService; - - @After - public void destroy() throws Exception { - context.turnOffAuthorisationSystem(); - systemWideAlertService.findAll(context).stream().forEach(systemWideAlert -> { - try { - systemWideAlertService.delete(context, systemWideAlert); - } catch (SQLException | IOException | AuthorizeException e) { - log.error(e); - } - }); - context.restoreAuthSystemState(); - - super.destroy(); - } - - @Test public void findAllTest() throws Exception { + // Create two alert entries in the db to fully test the findAll method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); Date countdownDate = new Date(); - SystemWideAlert systemWideAlert1 = systemWideAlertService.create(context, "Test alert 1", - AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY, - countdownDate, - true); - SystemWideAlert systemWideAlert2 = systemWideAlertService.create(context, "Test alert 2", - AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, - null, - false); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - getClient().perform(get("/api/system/systemwidealerts/")) + + String authToken = getAuthToken(admin.getEmail(), password); + + getClient(authToken).perform(get("/api/system/systemwidealerts/")) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.systemwidealerts", containsInAnyOrder( allOf( @@ -96,35 +81,243 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati hasJsonPath("$.active", is(systemWideAlert2.isActive())) ) ))); + } + @Test + public void findAllUnauthorizedTest() throws Exception { + // Create two alert entries in the db to fully test the findAll method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); + Date countdownDate = new Date(); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + + getClient().perform(get("/api/system/systemwidealerts/")) + .andExpect(status().isUnauthorized()); + + } + + @Test + public void findAllForbiddenTest() throws Exception { + // Create two alert entries in the db to fully test the findAll method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); + Date countdownDate = new Date(); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + + String authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform(get("/api/system/systemwidealerts/")) + .andExpect(status().isForbidden()); } @Test public void findOneTest() throws Exception { - + // Create two alert entries in the db to fully test the findOne method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); Date countdownDate = new Date(); - SystemWideAlert systemWideAlert1 = systemWideAlertService.create(context, "Test alert 1", - AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY, - countdownDate, - true); - SystemWideAlert systemWideAlert2 = systemWideAlertService.create(context, "Test alert 2", - AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, - null, - false); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + String authToken = getAuthToken(admin.getEmail(), password); + + // When the alert is active and the user is not an admin, the user will be able to see the alert + getClient(authToken).perform(get("/api/system/systemwidealerts/" + systemWideAlert1.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$", allOf( + hasJsonPath("$.alertId", is(systemWideAlert1.getID())), + hasJsonPath("$.message", is(systemWideAlert1.getMessage())), + hasJsonPath("$.allowSessions", + is(systemWideAlert1.getAllowSessions())), + hasJsonPath("$.countdownTo", + startsWith(sdf.format(systemWideAlert1.getCountdownTo()))), + hasJsonPath("$.active", is(systemWideAlert1.isActive())) + ) + )); + + } + + + @Test + public void findOneUnauthorizedTest() throws Exception { + // Create two alert entries in the db to fully test the findOne method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); + Date countdownDate = new Date(); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + // When the alert is active and the user is not an admin, the user will be able to see the alert getClient().perform(get("/api/system/systemwidealerts/" + systemWideAlert1.getID())) - .andExpect(status().isOk()) - .andExpect( - jsonPath("$", allOf( + .andExpect(status().isOk()) + .andExpect( + jsonPath("$", allOf( + hasJsonPath("$.alertId", is(systemWideAlert1.getID())), + hasJsonPath("$.message", is(systemWideAlert1.getMessage())), + hasJsonPath("$.allowSessions", + is(systemWideAlert1.getAllowSessions())), + hasJsonPath("$.countdownTo", + startsWith(sdf.format(systemWideAlert1.getCountdownTo()))), + hasJsonPath("$.active", is(systemWideAlert1.isActive())) + ) + )); + + // When the alert is inactive and the user is not an admin, the user will not be able to see the presence of the + // alert and a 404 will be returned by the findOne endpoint + getClient().perform(get("/api/system/systemwidealerts/" + systemWideAlert2.getID())) + .andExpect(status().isNotFound()); + + } + + @Test + public void findOneForbiddenTest() throws Exception { + // Create two alert entries in the db to fully test the findOne method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); + Date countdownDate = new Date(); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); + + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + String authToken = getAuthToken(eperson.getEmail(), password); + + + getClient(authToken).perform(get("/api/system/systemwidealerts/" + systemWideAlert1.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$", allOf( + hasJsonPath("$.alertId", is(systemWideAlert1.getID())), + hasJsonPath("$.message", is(systemWideAlert1.getMessage())), + hasJsonPath("$.allowSessions", + is(systemWideAlert1.getAllowSessions())), + hasJsonPath("$.countdownTo", + startsWith(sdf.format(systemWideAlert1.getCountdownTo()))), + hasJsonPath("$.active", is(systemWideAlert1.isActive())) + ) + )); + + // When the alert is inactive and the user is not an admin, the user will not be able to see the presence of the + // alert and a 404 will be returned by the findOne endpoint + getClient(authToken).perform(get("/api/system/systemwidealerts/" + systemWideAlert2.getID())) + .andExpect(status().isNotFound()); + + } + + @Test + public void findAllActiveTest() throws Exception { + // Create three alert entries in the db to fully test the findActive search method + // Note: It is not possible to create two alerts through the REST API + context.turnOffAuthorisationSystem(); + Date countdownDate = new Date(); + SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1") + .withAllowSessions( + AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY) + .withCountdownDate(countdownDate) + .isActive(true) + .build(); + + SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + + SystemWideAlert systemWideAlert3 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 3") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(true) + .build(); + context.restoreAuthSystemState(); + + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + getClient().perform(get("/api/system/systemwidealerts/search/active")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.systemwidealerts", containsInAnyOrder( + allOf( hasJsonPath("$.alertId", is(systemWideAlert1.getID())), hasJsonPath("$.message", is(systemWideAlert1.getMessage())), hasJsonPath("$.allowSessions", is(systemWideAlert1.getAllowSessions())), hasJsonPath("$.countdownTo", startsWith(sdf.format(systemWideAlert1.getCountdownTo()))), hasJsonPath("$.active", is(systemWideAlert1.isActive())) + ), + allOf( + hasJsonPath("$.alertId", is(systemWideAlert3.getID())), + hasJsonPath("$.message", is(systemWideAlert3.getMessage())), + hasJsonPath("$.allowSessions", is(systemWideAlert3.getAllowSessions())), + hasJsonPath("$.countdownTo", is(systemWideAlert3.getCountdownTo())), + hasJsonPath("$.active", is(systemWideAlert3.isActive())) ) - )); + ))); } @@ -162,7 +355,7 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati .andDo(result -> idRef .set((read(result.getResponse().getContentAsString(), "$.alertId")))); - getClient().perform(get("/api/system/systemwidealerts/" + idRef.get())) + getClient(authToken).perform(get("/api/system/systemwidealerts/" + idRef.get())) .andExpect(status().isOk()) .andExpect( jsonPath("$", allOf( @@ -218,11 +411,16 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati @Test public void createWhenAlreadyExistsTest() throws Exception { + context.turnOffAuthorisationSystem(); - SystemWideAlert systemWideAlert = systemWideAlertService.create(context, "Test alert", - AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, - null, - false); + SystemWideAlert systemWideAlert = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + + context.restoreAuthSystemState(); SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest(); systemWideAlertRest.setMessage("Alert test message"); @@ -243,11 +441,14 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati @Test public void putTest() throws Exception { - - SystemWideAlert systemWideAlert = systemWideAlertService.create(context, "Alert test message", - AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, - null, - false); + context.turnOffAuthorisationSystem(); + SystemWideAlert systemWideAlert = SystemWideAlertBuilder.createSystemWideAlert(context, "Alert test message") + .withAllowSessions( + AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY) + .withCountdownDate(null) + .isActive(false) + .build(); + context.restoreAuthSystemState(); SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest(); systemWideAlertRest.setAlertId(systemWideAlert.getID()); @@ -278,7 +479,7 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati ) )); - getClient().perform(get("/api/system/systemwidealerts/" + systemWideAlert.getID())) + getClient(authToken).perform(get("/api/system/systemwidealerts/" + systemWideAlert.getID())) .andExpect(status().isOk()) .andExpect( jsonPath("$", allOf(