97425: Implement feedback

This commit is contained in:
Yana De Pauw
2023-01-31 12:27:39 +01:00
parent 51424cbb7c
commit 659382fa8b
11 changed files with 665 additions and 75 deletions

View File

@@ -8,7 +8,14 @@
package org.dspace.alerts; 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 { public enum AllowSessionsEnum {
ALLOW_ALL_SESSIONS(0), ALLOW_ALL_SESSIONS(0),

View File

@@ -20,7 +20,6 @@ import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogHelper; import org.dspace.core.LogHelper;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** /**
@@ -37,12 +36,15 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService {
@Autowired @Autowired
private AuthorizeService authorizeService; private AuthorizeService authorizeService;
@Autowired @Override
private EPersonService ePersonService;
public SystemWideAlert create(final Context context, final String message, public SystemWideAlert create(final Context context, final String message,
final AllowSessionsEnum allowSessionsType, 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 systemWideAlert = new SystemWideAlert();
systemWideAlert.setMessage(message); systemWideAlert.setMessage(message);
systemWideAlert.setAllowSessions(allowSessionsType); systemWideAlert.setAllowSessions(allowSessionsType);
@@ -59,36 +61,52 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService {
return createdAlert; return createdAlert;
} }
@Override
public SystemWideAlert find(final Context context, final int alertId) throws SQLException { public SystemWideAlert find(final Context context, final int alertId) throws SQLException {
return systemWideAlertDAO.findByID(context, SystemWideAlert.class, alertId); return systemWideAlertDAO.findByID(context, SystemWideAlert.class, alertId);
} }
@Override
public List<SystemWideAlert> findAll(final Context context) throws SQLException { public List<SystemWideAlert> findAll(final Context context) throws SQLException {
return systemWideAlertDAO.findAll(context, SystemWideAlert.class); return systemWideAlertDAO.findAll(context, SystemWideAlert.class);
} }
@Override
public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException { public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException {
return systemWideAlertDAO.findAll(context, limit, offset); return systemWideAlertDAO.findAll(context, limit, offset);
} }
@Override
public List<SystemWideAlert> findAllActive(final Context context, final int limit, final int offset) public List<SystemWideAlert> findAllActive(final Context context, final int limit, final int offset)
throws SQLException { throws SQLException {
return systemWideAlertDAO.findAllActive(context, limit, offset); return systemWideAlertDAO.findAllActive(context, limit, offset);
} }
@Override
public void delete(final Context context, final SystemWideAlert systemWideAlert) public void delete(final Context context, final SystemWideAlert systemWideAlert)
throws SQLException, IOException, AuthorizeException { throws SQLException, IOException, AuthorizeException {
if (!authorizeService.isAdmin(context)) {
throw new AuthorizeException(
"Only administrators can create a system-wide alert");
}
systemWideAlertDAO.delete(context, systemWideAlert); systemWideAlertDAO.delete(context, systemWideAlert);
log.info(LogHelper.getHeader(context, "system_wide_alert_create", log.info(LogHelper.getHeader(context, "system_wide_alert_create",
"System Wide Alert with ID " + systemWideAlert.getID() + " has been deleted")); "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); systemWideAlertDAO.save(context, systemWideAlert);
} }
@Override
public boolean canNonAdminUserLogin(Context context) throws SQLException { public boolean canNonAdminUserLogin(Context context) throws SQLException {
List<SystemWideAlert> active = findAllActive(context, 1, 0); List<SystemWideAlert> active = findAllActive(context, 1, 0);
if (active == null || active.isEmpty()) { if (active == null || active.isEmpty()) {
@@ -97,6 +115,7 @@ public class SystemWideAlertServiceImpl implements SystemWideAlertService {
return active.get(0).getAllowSessions() == AllowSessionsEnum.ALLOW_ALL_SESSIONS.getValue(); return active.get(0).getAllowSessions() == AllowSessionsEnum.ALLOW_ALL_SESSIONS.getValue();
} }
@Override
public boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException { public boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException {
if (authorizeService.isAdmin(context, ePerson)) { if (authorizeService.isAdmin(context, ePerson)) {
return true; return true;

View File

@@ -19,7 +19,7 @@ import org.dspace.core.Context;
import org.dspace.eperson.EPerson; 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 { public interface SystemWideAlertService {
@@ -36,7 +36,7 @@ public interface SystemWideAlertService {
*/ */
SystemWideAlert create(Context context, String message, AllowSessionsEnum allowSessionsType, SystemWideAlert create(Context context, String message, AllowSessionsEnum allowSessionsType,
Date countdownTo, boolean active Date countdownTo, boolean active
) throws SQLException; ) throws SQLException, AuthorizeException;
/** /**
* This method will retrieve a SystemWideAlert object from the Database with the given ID * 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 * @param systemWideAlert The SystemWideAlert object to be updated
* @throws SQLException If something goes wrong * @throws SQLException If something goes wrong
*/ */
void update(Context context, SystemWideAlert systemWideAlert) throws SQLException; void update(Context context, SystemWideAlert systemWideAlert) throws SQLException, AuthorizeException;
/** /**

View File

@@ -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<SystemWideAlert> 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<SystemWideAlert> 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<SystemWideAlert> 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<SystemWideAlert> 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<SystemWideAlert> 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<SystemWideAlert> 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));
}
}

View File

@@ -13,6 +13,7 @@ import java.util.List;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.alerts.service.SystemWideAlertService;
import org.dspace.app.requestitem.factory.RequestItemServiceFactory; import org.dspace.app.requestitem.factory.RequestItemServiceFactory;
import org.dspace.app.requestitem.service.RequestItemService; import org.dspace.app.requestitem.service.RequestItemService;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
@@ -102,6 +103,7 @@ public abstract class AbstractBuilder<T, S> {
static OrcidHistoryService orcidHistoryService; static OrcidHistoryService orcidHistoryService;
static OrcidQueueService orcidQueueService; static OrcidQueueService orcidQueueService;
static OrcidTokenService orcidTokenService; static OrcidTokenService orcidTokenService;
static SystemWideAlertService systemWideAlertService;
protected Context context; protected Context context;
@@ -161,6 +163,8 @@ public abstract class AbstractBuilder<T, S> {
orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService(); orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService();
orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService(); orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService();
orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService(); orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService();
systemWideAlertService = DSpaceServicesFactory.getInstance().getServiceManager()
.getServicesByType(SystemWideAlertService.class).get(0);
} }
@@ -194,6 +198,7 @@ public abstract class AbstractBuilder<T, S> {
requestItemService = null; requestItemService = null;
versioningService = null; versioningService = null;
orcidTokenService = null; orcidTokenService = null;
systemWideAlertService = null;
} }

View File

@@ -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<SystemWideAlert, SystemWideAlertService> {
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();
}
}
}

View File

@@ -23,10 +23,12 @@ import org.apache.logging.log4j.Logger;
import org.dspace.alerts.AllowSessionsEnum; import org.dspace.alerts.AllowSessionsEnum;
import org.dspace.alerts.SystemWideAlert; import org.dspace.alerts.SystemWideAlert;
import org.dspace.alerts.service.SystemWideAlertService; 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.DSpaceBadRequestException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.SystemWideAlertRest; import org.dspace.app.rest.model.SystemWideAlertRest;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -46,6 +48,9 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
@Autowired @Autowired
private SystemWideAlertService systemWideAlertService; private SystemWideAlertService systemWideAlertService;
@Autowired
private AuthorizeService authorizeService;
@Override @Override
@PreAuthorize("hasAuthority('ADMIN')") @PreAuthorize("hasAuthority('ADMIN')")
protected SystemWideAlertRest createAndReturn(Context context) throws SQLException, AuthorizeException { protected SystemWideAlertRest createAndReturn(Context context) throws SQLException, AuthorizeException {
@@ -54,6 +59,18 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
} }
/**
* This method will retrieve the system-wide alert for the provided ID
* However, only admins will be able to retrieve the inactive alerts. Non-admin users will only be able to retrieve
* active alerts. This is necessary also to be able to return the results through the search endpoint, since the
* PreAuthorization will be checked when converting the results to a list. Therefore, closing this endpoint fully
* off will
* prevent results from being displayed in the search endpoint
*
* @param context the dspace context
* @param id the rest object id
* @return retrieve the system-wide alert for the provided ID
*/
@Override @Override
@PreAuthorize("permitAll()") @PreAuthorize("permitAll()")
public SystemWideAlertRest findOne(Context context, Integer id) { public SystemWideAlertRest findOne(Context context, Integer id) {
@@ -63,6 +80,9 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
throw new ResourceNotFoundException( throw new ResourceNotFoundException(
"systemWideAlert with id " + systemWideAlert.getID() + " was not found"); "systemWideAlert with id " + systemWideAlert.getID() + " was not found");
} }
if (!authorizeService.isAdmin(context) && !systemWideAlert.isActive()) {
throw new AuthorizeException("Non admin users are not allowed to retrieve inactive alerts");
}
return converter.toRest(systemWideAlert, utils.obtainProjection()); return converter.toRest(systemWideAlert, utils.obtainProjection());
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
@@ -71,7 +91,7 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
} }
@Override @Override
@PreAuthorize("permitAll()") @PreAuthorize("hasAuthority('ADMIN')")
public Page<SystemWideAlertRest> findAll(Context context, Pageable pageable) { public Page<SystemWideAlertRest> findAll(Context context, Pageable pageable) {
try { try {
List<SystemWideAlert> systemWideAlerts = systemWideAlertService.findAll(context, pageable.getPageSize(), List<SystemWideAlert> systemWideAlerts = systemWideAlertService.findAll(context, pageable.getPageSize(),
@@ -118,12 +138,13 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
/** /**
* Helper method to create a system-wide alert and deny creation when one already exists * Helper method to create a system-wide alert and deny creation when one already exists
* @param context The database context *
* @param context The database context
* @return the created system-wide alert * @return the created system-wide alert
* @throws SQLException * @throws SQLException
*/ */
private SystemWideAlert createSystemWideAlert(Context context) private SystemWideAlert createSystemWideAlert(Context context)
throws SQLException { throws SQLException, AuthorizeException {
List<SystemWideAlert> all = systemWideAlertService.findAll(context); List<SystemWideAlert> all = systemWideAlertService.findAll(context);
if (!all.isEmpty()) { if (!all.isEmpty()) {
throw new DSpaceBadRequestException("A system wide alert already exists, no new value can be created. " + throw new DSpaceBadRequestException("A system wide alert already exists, no new value can be created. " +
@@ -156,6 +177,29 @@ public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWi
return systemWideAlert; return systemWideAlert;
} }
/**
* Search method to retrieve all active system-wide alerts
*
* @param pageable The page object
* @return all active system-wide alerts for the provided page
*/
@PreAuthorize("permitAll()")
@SearchRestMethod(name = "active")
public Page<SystemWideAlertRest> findAllActive(Pageable pageable) {
Context context = obtainContext();
try {
List<SystemWideAlert> 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 @Override
public Class<SystemWideAlertRest> getDomainClass() { public Class<SystemWideAlertRest> getDomainClass() {

View File

@@ -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.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper; 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.AllowSessionsEnum;
import org.dspace.alerts.SystemWideAlert; import org.dspace.alerts.SystemWideAlert;
import org.dspace.alerts.service.SystemWideAlertService;
import org.dspace.app.rest.model.SystemWideAlertRest; import org.dspace.app.rest.model.SystemWideAlertRest;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authorize.AuthorizeException; import org.dspace.builder.SystemWideAlertBuilder;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
/** /**
* Test class to test the operations in the SystemWideAlertRestRepository * Test class to test the operations in the SystemWideAlertRestRepository
*/ */
public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrationTest { 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 @Test
public void findAllTest() throws Exception { 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(); Date countdownDate = new Date();
SystemWideAlert systemWideAlert1 = systemWideAlertService.create(context, "Test alert 1", SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1")
AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY, .withAllowSessions(
countdownDate, AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY)
true); .withCountdownDate(countdownDate)
SystemWideAlert systemWideAlert2 = systemWideAlertService.create(context, "Test alert 2", .isActive(true)
AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, .build();
null,
false); 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"); 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(status().isOk())
.andExpect(jsonPath("$._embedded.systemwidealerts", containsInAnyOrder( .andExpect(jsonPath("$._embedded.systemwidealerts", containsInAnyOrder(
allOf( allOf(
@@ -96,35 +81,243 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati
hasJsonPath("$.active", is(systemWideAlert2.isActive())) 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 @Test
public void findOneTest() throws Exception { 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(); Date countdownDate = new Date();
SystemWideAlert systemWideAlert1 = systemWideAlertService.create(context, "Test alert 1", SystemWideAlert systemWideAlert1 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 1")
AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY, .withAllowSessions(
countdownDate, AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY)
true); .withCountdownDate(countdownDate)
SystemWideAlert systemWideAlert2 = systemWideAlertService.create(context, "Test alert 2", .isActive(true)
AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, .build();
null, SystemWideAlert systemWideAlert2 = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert 2")
false); .withAllowSessions(
AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY)
.withCountdownDate(null)
.isActive(false)
.build();
context.restoreAuthSystemState();
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 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())) getClient().perform(get("/api/system/systemwidealerts/" + systemWideAlert1.getID()))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect( .andExpect(
jsonPath("$", allOf( 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("$.alertId", is(systemWideAlert1.getID())),
hasJsonPath("$.message", is(systemWideAlert1.getMessage())), hasJsonPath("$.message", is(systemWideAlert1.getMessage())),
hasJsonPath("$.allowSessions", is(systemWideAlert1.getAllowSessions())), hasJsonPath("$.allowSessions", is(systemWideAlert1.getAllowSessions())),
hasJsonPath("$.countdownTo", hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlert1.getCountdownTo()))), startsWith(sdf.format(systemWideAlert1.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlert1.isActive())) 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 .andDo(result -> idRef
.set((read(result.getResponse().getContentAsString(), "$.alertId")))); .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(status().isOk())
.andExpect( .andExpect(
jsonPath("$", allOf( jsonPath("$", allOf(
@@ -218,11 +411,16 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati
@Test @Test
public void createWhenAlreadyExistsTest() throws Exception { public void createWhenAlreadyExistsTest() throws Exception {
context.turnOffAuthorisationSystem();
SystemWideAlert systemWideAlert = systemWideAlertService.create(context, "Test alert", SystemWideAlert systemWideAlert = SystemWideAlertBuilder.createSystemWideAlert(context, "Test alert")
AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, .withAllowSessions(
null, AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY)
false); .withCountdownDate(null)
.isActive(false)
.build();
context.restoreAuthSystemState();
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest(); SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setMessage("Alert test message"); systemWideAlertRest.setMessage("Alert test message");
@@ -243,11 +441,14 @@ public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrati
@Test @Test
public void putTest() throws Exception { public void putTest() throws Exception {
context.turnOffAuthorisationSystem();
SystemWideAlert systemWideAlert = systemWideAlertService.create(context, "Alert test message", SystemWideAlert systemWideAlert = SystemWideAlertBuilder.createSystemWideAlert(context, "Alert test message")
AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY, .withAllowSessions(
null, AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY)
false); .withCountdownDate(null)
.isActive(false)
.build();
context.restoreAuthSystemState();
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest(); SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setAlertId(systemWideAlert.getID()); 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(status().isOk())
.andExpect( .andExpect(
jsonPath("$", allOf( jsonPath("$", allOf(