Merge branch 'main' into CST-7754

# Conflicts:
#	dspace-api/src/test/java/org/dspace/builder/AbstractBuilder.java
This commit is contained in:
corrado lombardi
2023-02-10 09:54:40 +01:00
34 changed files with 2122 additions and 142 deletions

View File

@@ -0,0 +1,54 @@
/**
* 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;
/**
* 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("all"),
ALLOW_CURRENT_SESSIONS_ONLY("current"),
ALLOW_ADMIN_SESSIONS_ONLY("admin");
private String allowSessionsType;
AllowSessionsEnum(String allowSessionsType) {
this.allowSessionsType = allowSessionsType;
}
public String getValue() {
return allowSessionsType;
}
public static AllowSessionsEnum fromString(String alertAllowSessionType) {
if (alertAllowSessionType == null) {
return AllowSessionsEnum.ALLOW_ALL_SESSIONS;
}
switch (alertAllowSessionType) {
case "all":
return AllowSessionsEnum.ALLOW_ALL_SESSIONS;
case "current":
return AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY;
case "admin" :
return AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY;
default:
throw new IllegalArgumentException("No corresponding enum value for provided string: "
+ alertAllowSessionType);
}
}
}

View File

@@ -0,0 +1,179 @@
/**
* 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 java.util.Date;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dspace.core.ReloadableEntity;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
* Database object representing system-wide alerts
*/
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy")
@Table(name = "systemwidealert")
public class SystemWideAlert implements ReloadableEntity<Integer> {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "alert_id_seq")
@SequenceGenerator(name = "alert_id_seq", sequenceName = "alert_id_seq", allocationSize = 1)
@Column(name = "alert_id", unique = true, nullable = false)
private Integer alertId;
@Column(name = "message", nullable = false)
private String message;
@Column(name = "allow_sessions")
private String allowSessions;
@Column(name = "countdown_to")
@Temporal(TemporalType.TIMESTAMP)
private Date countdownTo;
@Column(name = "active")
private boolean active;
protected SystemWideAlert() {
}
/**
* This method returns the ID that the system-wide alert holds within the database
*
* @return The ID that the system-wide alert holds within the database
*/
@Override
public Integer getID() {
return alertId;
}
/**
* Set the ID for the system-wide alert
*
* @param alertID The ID to set
*/
public void setID(final Integer alertID) {
this.alertId = alertID;
}
/**
* Retrieve the message of the system-wide alert
*
* @return the message of the system-wide alert
*/
public String getMessage() {
return message;
}
/**
* Set the message of the system-wide alert
*
* @param message The message to set
*/
public void setMessage(final String message) {
this.message = message;
}
/**
* Retrieve what kind of sessions are allowed while the system-wide alert is active
*
* @return what kind of sessions are allowed while the system-wide alert is active
*/
public AllowSessionsEnum getAllowSessions() {
return AllowSessionsEnum.fromString(allowSessions);
}
/**
* Set what kind of sessions are allowed while the system-wide alert is active
*
* @param allowSessions Integer representing what kind of sessions are allowed
*/
public void setAllowSessions(AllowSessionsEnum allowSessions) {
this.allowSessions = allowSessions.getValue();
}
/**
* Retrieve the date to which will be count down when the system-wide alert is active
*
* @return the date to which will be count down when the system-wide alert is active
*/
public Date getCountdownTo() {
return countdownTo;
}
/**
* Set the date to which will be count down when the system-wide alert is active
*
* @param countdownTo The date to which will be count down
*/
public void setCountdownTo(final Date countdownTo) {
this.countdownTo = countdownTo;
}
/**
* Retrieve whether the system-wide alert is active
*
* @return whether the system-wide alert is active
*/
public boolean isActive() {
return active;
}
/**
* Set whether the system-wide alert is active
*
* @param active Whether the system-wide alert is active
*/
public void setActive(final boolean active) {
this.active = active;
}
/**
* Return <code>true</code> if <code>other</code> is the same SystemWideAlert
* as this object, <code>false</code> otherwise
*
* @param other object to compare to
* @return <code>true</code> if object passed in represents the same
* system-wide alert as this object
*/
@Override
public boolean equals(Object other) {
return (other instanceof SystemWideAlert &&
new EqualsBuilder().append(this.getID(), ((SystemWideAlert) other).getID())
.append(this.getMessage(), ((SystemWideAlert) other).getMessage())
.append(this.getAllowSessions(), ((SystemWideAlert) other).getAllowSessions())
.append(this.getCountdownTo(), ((SystemWideAlert) other).getCountdownTo())
.append(this.isActive(), ((SystemWideAlert) other).isActive())
.isEquals());
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(this.getID())
.append(this.getMessage())
.append(this.getAllowSessions())
.append(this.getCountdownTo())
.append(this.isActive())
.toHashCode();
}
}

View File

@@ -0,0 +1,129 @@
/**
* 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 java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
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.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.core.LogHelper;
import org.dspace.eperson.EPerson;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The implementation for the {@link SystemWideAlertService} class
*/
public class SystemWideAlertServiceImpl implements SystemWideAlertService {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SystemWideAlertService.class);
@Autowired
private SystemWideAlertDAO systemWideAlertDAO;
@Autowired
private AuthorizeService authorizeService;
@Override
public SystemWideAlert create(final Context context, final String message,
final AllowSessionsEnum allowSessionsType,
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);
systemWideAlert.setCountdownTo(countdownTo);
systemWideAlert.setActive(active);
SystemWideAlert createdAlert = systemWideAlertDAO.create(context, systemWideAlert);
log.info(LogHelper.getHeader(context, "system_wide_alert_create",
"System Wide Alert has been created with message: '" + message + "' and ID "
+ createdAlert.getID() + " and allowSessionsType " + allowSessionsType +
" and active set to " + active));
return createdAlert;
}
@Override
public SystemWideAlert find(final Context context, final int alertId) throws SQLException {
return systemWideAlertDAO.findByID(context, SystemWideAlert.class, alertId);
}
@Override
public List<SystemWideAlert> findAll(final Context context) throws SQLException {
return systemWideAlertDAO.findAll(context, SystemWideAlert.class);
}
@Override
public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException {
return systemWideAlertDAO.findAll(context, limit, offset);
}
@Override
public List<SystemWideAlert> 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"));
}
@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<SystemWideAlert> active = findAllActive(context, 1, 0);
if (active == null || active.isEmpty()) {
return true;
}
return active.get(0).getAllowSessions() == AllowSessionsEnum.ALLOW_ALL_SESSIONS;
}
@Override
public boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException {
if (authorizeService.isAdmin(context, ePerson)) {
return true;
}
List<SystemWideAlert> active = findAllActive(context, 1, 0);
if (active == null || active.isEmpty()) {
return true;
}
return active.get(0).getAllowSessions() != AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY;
}
}

View File

@@ -0,0 +1,45 @@
/**
* 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.dao;
import java.sql.SQLException;
import java.util.List;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
/**
* This is the Data Access Object for the {@link SystemWideAlert} object
*/
public interface SystemWideAlertDAO extends GenericDAO<SystemWideAlert> {
/**
* Returns a list of all SystemWideAlert objects in the database
*
* @param context The relevant DSpace context
* @param limit The limit for the amount of SystemWideAlerts returned
* @param offset The offset for the Processes to be returned
* @return The list of all SystemWideAlert objects in the Database
* @throws SQLException If something goes wrong
*/
List<SystemWideAlert> findAll(Context context, int limit, int offset) throws SQLException;
/**
* Returns a list of all active SystemWideAlert objects in the database
*
* @param context The relevant DSpace context
* @param limit The limit for the amount of SystemWideAlerts returned
* @param offset The offset for the Processes to be returned
* @return The list of all SystemWideAlert objects in the Database
* @throws SQLException If something goes wrong
*/
List<SystemWideAlert> findAllActive(Context context, int limit, int offset) throws SQLException;
}

View File

@@ -0,0 +1,48 @@
/**
* 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.dao.impl;
import java.sql.SQLException;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.alerts.SystemWideAlert_;
import org.dspace.alerts.dao.SystemWideAlertDAO;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
/**
* Implementation class for the {@link SystemWideAlertDAO}
*/
public class SystemWideAlertDAOImpl extends AbstractHibernateDAO<SystemWideAlert> implements SystemWideAlertDAO {
public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, SystemWideAlert.class);
Root<SystemWideAlert> alertRoot = criteriaQuery.from(SystemWideAlert.class);
criteriaQuery.select(alertRoot);
return list(context, criteriaQuery, false, SystemWideAlert.class, limit, offset);
}
public List<SystemWideAlert> findAllActive(final Context context, final int limit, final int offset)
throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, SystemWideAlert.class);
Root<SystemWideAlert> alertRoot = criteriaQuery.from(SystemWideAlert.class);
criteriaQuery.select(alertRoot);
criteriaQuery.where(criteriaBuilder.equal(alertRoot.get(SystemWideAlert_.active), true));
return list(context, criteriaQuery, false, SystemWideAlert.class, limit, offset);
}
}

View File

@@ -0,0 +1,118 @@
/**
* 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.service;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import org.dspace.alerts.AllowSessionsEnum;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
/**
* An interface for the SystemWideAlertService with methods regarding the SystemWideAlert workload
*/
public interface SystemWideAlertService {
/**
* This method will create a SystemWideAlert object in the database
*
* @param context The relevant DSpace context
* @param message The message of the system-wide alert
* @param allowSessionsType Which sessions need to be allowed for the system-wide alert
* @param countdownTo The date to which to count down to when the system-wide alert is active
* @param active Whether the system-wide alert os active
* @return The created SystemWideAlert object
* @throws SQLException If something goes wrong
*/
SystemWideAlert create(Context context, String message, AllowSessionsEnum allowSessionsType,
Date countdownTo, boolean active
) throws SQLException, AuthorizeException;
/**
* This method will retrieve a SystemWideAlert object from the Database with the given ID
*
* @param context The relevant DSpace context
* @param alertId The alert id on which we'll search for in the database
* @return The system-wide alert that holds the given alert id
* @throws SQLException If something goes wrong
*/
SystemWideAlert find(Context context, int alertId) throws SQLException;
/**
* Returns a list of all SystemWideAlert objects in the database
*
* @param context The relevant DSpace context
* @return The list of all SystemWideAlert objects in the Database
* @throws SQLException If something goes wrong
*/
List<SystemWideAlert> findAll(Context context) throws SQLException;
/**
* Returns a list of all SystemWideAlert objects in the database
*
* @param context The relevant DSpace context
* @param limit The limit for the amount of system-wide alerts returned
* @param offset The offset for the system-wide alerts to be returned
* @return The list of all SystemWideAlert objects in the Database
* @throws SQLException If something goes wrong
*/
List<SystemWideAlert> findAll(Context context, int limit, int offset) throws SQLException;
/**
* Returns a list of all active SystemWideAlert objects in the database
*
* @param context The relevant DSpace context
* @return The list of all active SystemWideAlert objects in the database
* @throws SQLException If something goes wrong
*/
List<SystemWideAlert> findAllActive(Context context, int limit, int offset) throws SQLException;
/**
* This method will delete the given SystemWideAlert object from the database
*
* @param context The relevant DSpace context
* @param systemWideAlert The SystemWideAlert object to be deleted
* @throws SQLException If something goes wrong
*/
void delete(Context context, SystemWideAlert systemWideAlert)
throws SQLException, IOException, AuthorizeException;
/**
* This method will be used to update the given SystemWideAlert object in the database
*
* @param context The relevant DSpace context
* @param systemWideAlert The SystemWideAlert object to be updated
* @throws SQLException If something goes wrong
*/
void update(Context context, SystemWideAlert systemWideAlert) throws SQLException, AuthorizeException;
/**
* Verifies if the user connected to the current context can retain its session
*
* @param context The relevant DSpace context
* @return if the user connected to the current context can retain its session
*/
boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException;
/**
* Verifies if a non admin user can log in
*
* @param context The relevant DSpace context
* @return if a non admin user can log in
*/
boolean canNonAdminUserLogin(Context context) throws SQLException;
}

View File

@@ -59,7 +59,16 @@ public class CrossLinks {
* @return true/false
*/
public boolean hasLink(String metadata) {
return links.containsKey(metadata);
return findLinkType(metadata) != null;
}
/**
* Is there a link for the given browse name (eg 'author')
* @param browseIndexName
* @return true/false
*/
public boolean hasBrowseName(String browseIndexName) {
return links.containsValue(browseIndexName);
}
/**
@@ -69,6 +78,41 @@ public class CrossLinks {
* @return type
*/
public String getLinkType(String metadata) {
return links.get(metadata);
return findLinkType(metadata);
}
/**
* Get full map of field->indexname link configurations
* @return
*/
public Map<String, String> getLinks() {
return links;
}
/**
* Find and return the browse name for a given metadata field.
* If the link key contains a wildcard eg dc.subject.*, it should
* match dc.subject.other, etc.
* @param metadata
* @return
*/
public String findLinkType(String metadata) {
// Resolve wildcards properly, eg. dc.subject.other matches a configuration for dc.subject.*
for (String key : links.keySet()) {
if (null != key && key.endsWith(".*")) {
// A substring of length-1, also substracting the wildcard should work as a "startsWith"
// check for the field eg. dc.subject.* -> dc.subject is the start of dc.subject.other
if (null != metadata && metadata.startsWith(key.substring(0, key.length() - 1 - ".*".length()))) {
return links.get(key);
}
} else {
// Exact match, if the key field has no .* wildcard
if (links.containsKey(metadata)) {
return links.get(key);
}
}
}
// No match
return null;
}
}

View File

@@ -8,7 +8,6 @@
package org.dspace.browse;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -179,7 +178,6 @@ public class SolrBrowseDAO implements BrowseDAO {
DiscoverQuery query = new DiscoverQuery();
addLocationScopeFilter(query);
addDefaultFilterQueries(query);
addStatusFilter(query);
if (distinct) {
DiscoverFacetField dff;
if (StringUtils.isNotBlank(startsWith)) {
@@ -230,18 +228,6 @@ public class SolrBrowseDAO implements BrowseDAO {
return sResponse;
}
private void addStatusFilter(DiscoverQuery query) {
try {
if (!authorizeService.isAdmin(context)
&& (authorizeService.isCommunityAdmin(context)
|| authorizeService.isCollectionAdmin(context))) {
query.addFilterQueries(searcher.createLocationQueryForAdministrableItems(context));
}
} catch (SQLException ex) {
log.error("Error looking up authorization rights of current user", ex);
}
}
private void addLocationScopeFilter(DiscoverQuery query) {
if (container != null) {
if (containerIDField.startsWith("collection")) {
@@ -346,7 +332,6 @@ public class SolrBrowseDAO implements BrowseDAO {
DiscoverQuery query = new DiscoverQuery();
addLocationScopeFilter(query);
addDefaultFilterQueries(query);
addStatusFilter(query);
query.setMaxResults(0);
query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE);

View File

@@ -14,6 +14,7 @@ import javax.mail.MessagingException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authenticate.service.AuthenticationService;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.core.Email;
@@ -51,6 +52,9 @@ public class AccountServiceImpl implements AccountService {
@Autowired
private ConfigurationService configurationService;
@Autowired
private AuthenticationService authenticationService;
protected AccountServiceImpl() {
}
@@ -79,6 +83,9 @@ public class AccountServiceImpl implements AccountService {
if (!configurationService.getBooleanProperty("user.registration", true)) {
throw new IllegalStateException("The user.registration parameter was set to false");
}
if (!authenticationService.canSelfRegister(context, null, email)) {
throw new IllegalStateException("self registration is not allowed with this email address");
}
sendInfo(context, email, true, true);
}

View File

@@ -0,0 +1,22 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create table for System wide alerts
-----------------------------------------------------------------------------------
CREATE SEQUENCE alert_id_seq;
CREATE TABLE systemwidealert
(
alert_id INTEGER NOT NULL PRIMARY KEY,
message VARCHAR(512),
allow_sessions VARCHAR(64),
countdown_to TIMESTAMP,
active BOOLEAN
);

View File

@@ -0,0 +1,22 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create table for System wide alerts
-----------------------------------------------------------------------------------
CREATE SEQUENCE alert_id_seq;
CREATE TABLE systemwidealert
(
alert_id INTEGER NOT NULL PRIMARY KEY,
message VARCHAR(512),
allow_sessions VARCHAR(64),
countdown_to TIMESTAMP,
active BOOLEAN
);

View File

@@ -0,0 +1,22 @@
--
-- 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/
--
-----------------------------------------------------------------------------------
-- Create table for System wide alerts
-----------------------------------------------------------------------------------
CREATE SEQUENCE alert_id_seq;
CREATE TABLE systemwidealert
(
alert_id INTEGER NOT NULL PRIMARY KEY,
message VARCHAR(512),
allow_sessions VARCHAR(64),
countdown_to TIMESTAMP,
active BOOLEAN
);

View File

@@ -78,7 +78,7 @@ handle.remote-resolver.enabled = true
# Whether to enable the DSpace listhandles resolver that lists all available
# handles for this DSpace installation.
# Defaults to "false" which means is possible to obtain the list of handles
# of this DSpace installation, whenever the `handle.remote-resolver.enabled = true`.
# of this DSpace installation, whenever the `handle.remote-resolver.enabled = true`.
handle.hide.listhandles = false
#####################
@@ -171,3 +171,6 @@ choices.plugin.dspace.object.owner = EPersonAuthority
choices.presentation.dspace.object.owner = suggest
authority.controlled.dspace.object.owner = true
# Configuration required for thorough testing of browse links
webui.browse.link.1 = author:dc.contributor.*
webui.browse.link.2 = subject:dc.subject.*

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);
// 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);
// 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);
// 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);
// 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.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;
@@ -104,6 +105,7 @@ public abstract class AbstractBuilder<T, S> {
static OrcidHistoryService orcidHistoryService;
static OrcidQueueService orcidQueueService;
static OrcidTokenService orcidTokenService;
static SystemWideAlertService systemWideAlertService;
static SupervisionOrderService supervisionOrderService;
@@ -165,6 +167,8 @@ public abstract class AbstractBuilder<T, S> {
orcidHistoryService = OrcidServiceFactory.getInstance().getOrcidHistoryService();
orcidQueueService = OrcidServiceFactory.getInstance().getOrcidQueueService();
orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService();
systemWideAlertService = DSpaceServicesFactory.getInstance().getServiceManager()
.getServicesByType(SystemWideAlertService.class).get(0);
supervisionOrderService = SupervisionOrderServiceFactory.getInstance().getSupervisionOrderService();
}
@@ -199,6 +203,7 @@ public abstract class AbstractBuilder<T, S> {
requestItemService = null;
versioningService = null;
orcidTokenService = null;
systemWideAlertService = null;
supervisionOrderService = null;
}

View File

@@ -0,0 +1,94 @@
/**
* 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.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;
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);
}
}
}

View File

@@ -34,7 +34,6 @@ import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.security.RestAuthenticationService;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.service.ClientInfoService;
import org.slf4j.Logger;
@@ -210,33 +209,7 @@ public class AuthenticationRestController implements InitializingBean {
}
/**
* This method will generate a short lived token to be used for bitstream downloads among other things.
*
* For security reasons, this endpoint only responds to a explicitly defined list of ips.
*
* curl -v -X GET https://{dspace-server.url}/api/authn/shortlivedtokens -H "Authorization: Bearer eyJhbG...COdbo"
*
* Example:
* <pre>
* {@code
* curl -v -X GET https://{dspace-server.url}/api/authn/shortlivedtokens -H "Authorization: Bearer eyJhbG...COdbo"
* }
* </pre>
* @param request The StandardMultipartHttpServletRequest
* @return The created short lived token
*/
@PreAuthorize("hasAuthority('AUTHENTICATED')")
@RequestMapping(value = "/shortlivedtokens", method = RequestMethod.GET)
public AuthenticationTokenResource shortLivedTokenViaGet(HttpServletRequest request) throws AuthorizeException {
if (!clientInfoService.isRequestFromTrustedProxy(request.getRemoteAddr())) {
throw new AuthorizeException("Requests to this endpoint should be made from a trusted IP address.");
}
return shortLivedTokenResponse(request);
}
/**
* See {@link #shortLivedToken} and {@link #shortLivedTokenViaGet}
* See {@link #shortLivedToken}
*/
private AuthenticationTokenResource shortLivedTokenResponse(HttpServletRequest request) {
Projection projection = utils.obtainProjection();

View File

@@ -0,0 +1,39 @@
/**
* 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.app.rest.converter;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.app.rest.model.SystemWideAlertRest;
import org.dspace.app.rest.projection.Projection;
import org.springframework.stereotype.Component;
/**
* This converter will convert an object of {@Link SystemWideAlert} to an object of {@link SystemWideAlertRest}
*/
@Component
public class SystemWideAlertConverter implements DSpaceConverter<SystemWideAlert, SystemWideAlertRest> {
@Override
public SystemWideAlertRest convert(SystemWideAlert systemWideAlert, Projection projection) {
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setProjection(projection);
systemWideAlertRest.setId(systemWideAlert.getID());
systemWideAlertRest.setAlertId(systemWideAlert.getID());
systemWideAlertRest.setMessage(systemWideAlert.getMessage());
systemWideAlertRest.setAllowSessions(systemWideAlert.getAllowSessions().getValue());
systemWideAlertRest.setCountdownTo(systemWideAlert.getCountdownTo());
systemWideAlertRest.setActive(systemWideAlert.isActive());
return systemWideAlertRest;
}
@Override
public Class<SystemWideAlert> getModelClass() {
return SystemWideAlert.class;
}
}

View File

@@ -0,0 +1,88 @@
/**
* 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.app.rest.model;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.app.rest.RestResourceController;
/**
* This class serves as a REST representation for the {@link SystemWideAlert} class
*/
public class SystemWideAlertRest extends BaseObjectRest<Integer> {
public static final String NAME = "systemwidealert";
public static final String CATEGORY = RestAddressableModel.SYSTEM;
public String getCategory() {
return CATEGORY;
}
public Class getController() {
return RestResourceController.class;
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getType() {
return NAME;
}
private Integer alertId;
private String message;
private String allowSessions;
private Date countdownTo;
private boolean active;
public Integer getAlertId() {
return alertId;
}
public void setAlertId(final Integer alertID) {
this.alertId = alertID;
}
public String getMessage() {
return message;
}
public void setMessage(final String message) {
this.message = message;
}
public String getAllowSessions() {
return allowSessions;
}
public void setAllowSessions(final String allowSessions) {
this.allowSessions = allowSessions;
}
public Date getCountdownTo() {
return countdownTo;
}
public void setCountdownTo(final Date countdownTo) {
this.countdownTo = countdownTo;
}
public boolean isActive() {
return active;
}
public void setActive(final boolean active) {
this.active = active;
}
@JsonIgnore
@Override
public Integer getId() {
return id;
}
}

View File

@@ -0,0 +1,23 @@
/**
* 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.app.rest.model.hateoas;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.app.rest.model.SystemWideAlertRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils;
/**
* The Resource representation of a {@link SystemWideAlert} object
*/
@RelNameDSpaceResource(SystemWideAlertRest.NAME)
public class SystemWideAlertResource extends DSpaceResource<SystemWideAlertRest> {
public SystemWideAlertResource(SystemWideAlertRest content, Utils utils) {
super(content, utils);
}
}

View File

@@ -7,12 +7,16 @@
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.model.BrowseIndexRest;
import org.dspace.browse.BrowseException;
import org.dspace.browse.BrowseIndex;
import org.dspace.browse.CrossLinks;
import org.dspace.core.Context;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@@ -53,6 +57,37 @@ public class BrowseIndexRestRepository extends DSpaceRestRepository<BrowseIndexR
}
}
/**
* Find a browse index by a list of fields (first match will be returned)
* @param fields
* @return
* @throws SQLException
*/
@SearchRestMethod(name = "byFields")
public BrowseIndexRest findByFields(@Parameter(value = "fields", required = true) String[] fields)
throws SQLException {
BrowseIndexRest bi = null;
BrowseIndex bix = null;
try {
// Find the browse index definition that matches any field - once found, return
for (String field : fields) {
CrossLinks cl = new CrossLinks();
if (cl.hasLink(field)) {
// Get the index name for this
String browseIndexName = cl.getLinkType(field);
bix = BrowseIndex.getBrowseIndex(browseIndexName);
break;
}
}
} catch (BrowseException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (bix != null) {
bi = converter.toRest(bix, utils.obtainProjection());
}
return bi;
}
@Override
public Class<BrowseIndexRest> getDomainClass() {
return BrowseIndexRest.class;

View File

@@ -26,6 +26,7 @@ import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.RegistrationRest;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authenticate.service.AuthenticationService;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
@@ -52,12 +53,19 @@ public class RegistrationRestRepository extends DSpaceRestRepository<Registratio
private static Logger log = LogManager.getLogger(RegistrationRestRepository.class);
public static final String TYPE_QUERY_PARAM = "accountRequestType";
public static final String TYPE_REGISTER = "register";
public static final String TYPE_FORGOT = "forgot";
@Autowired
private EPersonService ePersonService;
@Autowired
private AccountService accountService;
@Autowired
private AuthenticationService authenticationService;
@Autowired
private RequestService requestService;
@@ -106,33 +114,45 @@ public class RegistrationRestRepository extends DSpaceRestRepository<Registratio
if (StringUtils.isBlank(registrationRest.getEmail())) {
throw new UnprocessableEntityException("The email cannot be omitted from the Registration endpoint");
}
String accountType = request.getParameter(TYPE_QUERY_PARAM);
if (StringUtils.isBlank(accountType) ||
(!accountType.equalsIgnoreCase(TYPE_FORGOT) && !accountType.equalsIgnoreCase(TYPE_REGISTER))) {
throw new IllegalArgumentException(String.format("Needs query param '%s' with value %s or %s indicating " +
"what kind of registration request it is", TYPE_QUERY_PARAM, TYPE_FORGOT, TYPE_REGISTER));
}
EPerson eperson = null;
try {
eperson = ePersonService.findByEmail(context, registrationRest.getEmail());
} catch (SQLException e) {
log.error("Something went wrong retrieving EPerson for email: " + registrationRest.getEmail(), e);
}
if (eperson != null) {
if (eperson != null && accountType.equalsIgnoreCase(TYPE_FORGOT)) {
try {
if (!AuthorizeUtil.authorizeUpdatePassword(context, eperson.getEmail())) {
throw new DSpaceBadRequestException("Password cannot be updated for the given EPerson with email: "
+ eperson.getEmail());
+ eperson.getEmail());
}
accountService.sendForgotPasswordInfo(context, registrationRest.getEmail());
} catch (SQLException | IOException | MessagingException | AuthorizeException e) {
log.error("Something went wrong with sending forgot password info email: "
+ registrationRest.getEmail(), e);
+ registrationRest.getEmail(), e);
}
} else {
} else if (accountType.equalsIgnoreCase(TYPE_REGISTER)) {
try {
String email = registrationRest.getEmail();
if (!AuthorizeUtil.authorizeNewAccountRegistration(context, request)) {
throw new AccessDeniedException(
"Registration is disabled, you are not authorized to create a new Authorization");
}
accountService.sendRegistrationInfo(context, registrationRest.getEmail());
if (!authenticationService.canSelfRegister(context, request, email)) {
throw new UnprocessableEntityException(
String.format("Registration is not allowed with email address" +
" %s", email));
}
accountService.sendRegistrationInfo(context, email);
} catch (SQLException | IOException | MessagingException | AuthorizeException e) {
log.error("Something went wrong with sending registration info email: "
+ registrationRest.getEmail(), e);
+ registrationRest.getEmail(), e);
}
}
return null;

View File

@@ -0,0 +1,208 @@
/**
* 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.app.rest.repository;
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
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.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;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* The repository for the SystemWideAlert workload
*/
@Component(SystemWideAlertRest.CATEGORY + "." + SystemWideAlertRest.NAME)
public class SystemWideAlertRestRepository extends DSpaceRestRepository<SystemWideAlertRest, Integer> {
private static final Logger log = LogManager.getLogger();
@Autowired
private SystemWideAlertService systemWideAlertService;
@Autowired
private AuthorizeService authorizeService;
@Override
@PreAuthorize("hasAuthority('ADMIN')")
protected SystemWideAlertRest createAndReturn(Context context) throws SQLException, AuthorizeException {
SystemWideAlert systemWideAlert = createSystemWideAlert(context);
return converter.toRest(systemWideAlert, utils.obtainProjection());
}
/**
* 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
@PreAuthorize("permitAll()")
public SystemWideAlertRest findOne(Context context, Integer id) {
try {
SystemWideAlert systemWideAlert = systemWideAlertService.find(context, id);
if (systemWideAlert == null) {
throw new ResourceNotFoundException(
"systemWideAlert with id " + systemWideAlert.getID() + " was not found");
}
if (!systemWideAlert.isActive() && !authorizeService.isAdmin(context)) {
throw new AuthorizeException("Non admin users are not allowed to retrieve inactive alerts");
}
return converter.toRest(systemWideAlert, utils.obtainProjection());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
@Override
@PreAuthorize("hasAuthority('ADMIN')")
public Page<SystemWideAlertRest> findAll(Context context, Pageable pageable) {
try {
List<SystemWideAlert> systemWideAlerts = systemWideAlertService.findAll(context, pageable.getPageSize(),
Math.toIntExact(
pageable.getOffset()));
return converter.toRestPage(systemWideAlerts, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
@PreAuthorize("hasAuthority('ADMIN')")
protected SystemWideAlertRest put(Context context, HttpServletRequest request, String apiCategory, String model,
Integer id, JsonNode jsonNode) throws SQLException, AuthorizeException {
SystemWideAlertRest systemWideAlertRest;
try {
systemWideAlertRest = new ObjectMapper().readValue(jsonNode.toString(), SystemWideAlertRest.class);
} catch (JsonProcessingException e) {
throw new UnprocessableEntityException("Cannot parse JSON in request body", e);
}
if (systemWideAlertRest == null || isBlank(systemWideAlertRest.getMessage())) {
throw new UnprocessableEntityException("system alert message cannot be blank");
}
SystemWideAlert systemWideAlert = systemWideAlertService.find(context, id);
if (systemWideAlert == null) {
throw new ResourceNotFoundException("system wide alert with id: " + id + " not found");
}
systemWideAlert.setMessage(systemWideAlertRest.getMessage());
systemWideAlert.setAllowSessions(AllowSessionsEnum.fromString(systemWideAlertRest.getAllowSessions()));
systemWideAlert.setCountdownTo(systemWideAlertRest.getCountdownTo());
systemWideAlert.setActive(systemWideAlertRest.isActive());
systemWideAlertService.update(context, systemWideAlert);
context.commit();
return converter.toRest(systemWideAlert, utils.obtainProjection());
}
/**
* Helper method to create a system-wide alert and deny creation when one already exists
*
* @param context The database context
* @return the created system-wide alert
* @throws SQLException
*/
private SystemWideAlert createSystemWideAlert(Context context)
throws SQLException, AuthorizeException {
List<SystemWideAlert> all = systemWideAlertService.findAll(context);
if (!all.isEmpty()) {
throw new DSpaceBadRequestException("A system wide alert already exists, no new value can be created. " +
"Try updating the existing one.");
}
HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest();
ObjectMapper mapper = new ObjectMapper();
SystemWideAlertRest systemWideAlertRest;
try {
ServletInputStream input = req.getInputStream();
systemWideAlertRest = mapper.readValue(input, SystemWideAlertRest.class);
} catch (IOException e1) {
throw new UnprocessableEntityException("Error parsing request body.", e1);
}
SystemWideAlert systemWideAlert;
try {
systemWideAlert = systemWideAlertService.create(context, systemWideAlertRest.getMessage(),
AllowSessionsEnum.fromString(
systemWideAlertRest.getAllowSessions()),
systemWideAlertRest.getCountdownTo(),
systemWideAlertRest.isActive());
systemWideAlertService.update(context, systemWideAlert);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
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
public Class<SystemWideAlertRest> getDomainClass() {
return SystemWideAlertRest.class;
}
}

View File

@@ -1394,64 +1394,6 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
.andExpect(status().isNoContent());
}
@Test
public void testShortLivedTokenUsingGet() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
// Verify the main session salt doesn't change
String salt = eperson.getSessionSalt();
getClient(token).perform(
get("/api/authn/shortlivedtokens")
.with(ip(TRUSTED_IP))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.token", notNullValue()))
.andExpect(jsonPath("$.type", is("shortlivedtoken")))
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authn/shortlivedtokens")))
// Verify generating short-lived token doesn't change our CSRF token
// (so, neither the CSRF cookie nor header are sent back)
.andExpect(cookie().doesNotExist("DSPACE-XSRF-COOKIE"))
.andExpect(header().doesNotExist("DSPACE-XSRF-TOKEN"));
assertEquals(salt, eperson.getSessionSalt());
// Logout, invalidating token
getClient(token).perform(post("/api/authn/logout"))
.andExpect(status().isNoContent());
}
@Test
public void testShortLivedTokenUsingGetFromUntrustedIpShould403() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
get("/api/authn/shortlivedtokens")
.with(ip(UNTRUSTED_IP))
)
.andExpect(status().isForbidden());
// Logout, invalidating token
getClient(token).perform(post("/api/authn/logout"))
.andExpect(status().isNoContent());
}
@Test
public void testShortLivedTokenUsingGetFromUntrustedIpWithForwardHeaderShould403() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
get("/api/authn/shortlivedtokens")
.with(ip(UNTRUSTED_IP))
.header("X-Forwarded-For", TRUSTED_IP) // this should not affect the test result
)
.andExpect(status().isForbidden());
// Logout, invalidating token
getClient(token).perform(post("/api/authn/logout"))
.andExpect(status().isNoContent());
}
@Test
public void testShortLivedTokenWithCSRFSentViaParam() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
@@ -1476,15 +1418,6 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
.andExpect(status().isUnauthorized());
}
@Test
public void testShortLivedTokenNotAuthenticatedUsingGet() throws Exception {
getClient().perform(
get("/api/authn/shortlivedtokens")
.with(ip(TRUSTED_IP))
)
.andExpect(status().isUnauthorized());
}
@Test
public void testShortLivedTokenToDownloadBitstream() throws Exception {
Bitstream bitstream = createPrivateBitstream();
@@ -1598,22 +1531,6 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
.andExpect(status().isNoContent());
}
@Test
public void testGenerateShortLivedTokenWithShortLivedTokenUsingGet() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
String shortLivedToken = getShortLivedToken(token);
getClient().perform(
get("/api/authn/shortlivedtokens?authentication-token=" + shortLivedToken)
.with(ip(TRUSTED_IP))
)
.andExpect(status().isForbidden());
// Logout, invalidating token
getClient(token).perform(post("/api/authn/logout"))
.andExpect(status().isNoContent());
}
@Test
public void testStatusOrcidAuthenticatedWithCookie() throws Exception {

View File

@@ -980,7 +980,7 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
/**
* This test was introduced to reproduce the bug DS-4269 Pagination links must be consistent also when there is not
* explicit pagination parameters in the request (i.e. defaults apply)
*
*
* @throws Exception
*/
public void browsePaginationWithoutExplicitParams() throws Exception {
@@ -2125,4 +2125,57 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.andExpect(jsonPath("$._embedded.items[0]._embedded.owningCollection._embedded.adminGroup",
nullValue()));
}
/**
* Expect a single author browse definition
* @throws Exception
*/
@Test
public void findOneLinked() throws Exception {
// When we call the search endpoint
getClient().perform(get("/api/discover/browses/search/byFields")
.param("fields", "dc.contributor.author"))
// The status has to be 200 OK
.andExpect(status().isOk())
// We expect the content type to be "application/hal+json;charset=UTF-8"
.andExpect(content().contentType(contentType))
// The browse definition ID should be "author"
.andExpect(jsonPath("$.id", is("author")))
// It should be configured as a metadata browse
.andExpect(jsonPath("$.metadataBrowse", is(true)))
;
}
@Test
public void findOneLinkedPassingTwoFields() throws Exception {
// When we call the search endpoint
getClient().perform(get("/api/discover/browses/search/byFields")
.param("fields", "dc.contributor.author")
.param("fields", "dc.date.issued"))
// The status has to be 200 OK
.andExpect(status().isOk())
// We expect the content type to be "application/hal+json;charset=UTF-8"
.andExpect(content().contentType(contentType))
// The browse definition ID should be "author"
.andExpect(jsonPath("$.id", is("author")))
// It should be configured as a metadata browse
.andExpect(jsonPath("$.metadataBrowse", is(true)));
}
@Test
public void findUnconfiguredFields() throws Exception {
// When we call the search endpoint with a field that isn't configured for any browse links
getClient().perform(get("/api/discover/browses/search/byFields")
.param("fields", "dc.identifier.uri"))
// The status has to be 204 NO CONTENT
.andExpect(status().isNoContent());
}
@Test
public void findBrowseLinksWithMissingParameter() throws Exception {
// When we call the search endpoint with a field that isn't configured for any browse links
getClient().perform(get("/api/discover/browses/search/byFields"))
// The status has to be 400 BAD REQUEST
.andExpect(status().isBadRequest());
}
}

View File

@@ -11,6 +11,8 @@ import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist;
import static org.dspace.app.rest.repository.RegistrationRestRepository.TYPE_QUERY_PARAM;
import static org.dspace.app.rest.repository.RegistrationRestRepository.TYPE_REGISTER;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
@@ -2178,6 +2180,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2226,6 +2229,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2290,6 +2294,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2352,6 +2357,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2418,6 +2424,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2427,6 +2434,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRestTwo = new RegistrationRest();
registrationRestTwo.setEmail(newRegisterEmailTwo);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRestTwo)))
.andExpect(status().isCreated());
@@ -2477,6 +2485,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2525,6 +2534,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2574,6 +2584,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2641,6 +2652,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2709,6 +2721,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2756,6 +2769,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(eperson.getEmail());
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -2805,6 +2819,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -3137,6 +3152,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -3182,6 +3198,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
registrationRest.setEmail(newRegisterEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(registrationRest)))
.andExpect(status().isCreated());
@@ -3417,4 +3434,4 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
}
}
}

View File

@@ -7,6 +7,9 @@
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.repository.RegistrationRestRepository.TYPE_FORGOT;
import static org.dspace.app.rest.repository.RegistrationRestRepository.TYPE_QUERY_PARAM;
import static org.dspace.app.rest.repository.RegistrationRestRepository.TYPE_REGISTER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -29,6 +32,7 @@ import org.dspace.app.rest.matcher.RegistrationMatcher;
import org.dspace.app.rest.model.RegistrationRest;
import org.dspace.app.rest.repository.RegistrationRestRepository;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.builder.EPersonBuilder;
import org.dspace.eperson.CaptchaServiceImpl;
import org.dspace.eperson.InvalidReCaptchaException;
import org.dspace.eperson.RegistrationData;
@@ -111,6 +115,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(email);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isCreated());
@@ -127,6 +132,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
try {
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isCreated());
@@ -137,6 +143,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
String newEmail = "newEPersonTest@gmail.com";
registrationRest.setEmail(newEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isCreated());
@@ -149,6 +156,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
newEmail = "newEPersonTestTwo@gmail.com";
registrationRest.setEmail(newEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().is(HttpServletResponse.SC_UNAUTHORIZED));
@@ -165,6 +173,90 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
}
}
@Test
public void testRegisterDomainRegistered() throws Exception {
List<RegistrationData> registrationDataList = registrationDataDAO.findAll(context, RegistrationData.class);
try {
configurationService.setProperty("authentication-password.domain.valid", "test.com");
RegistrationRest registrationRest = new RegistrationRest();
String email = "testPerson@test.com";
registrationRest.setEmail(email);
ObjectMapper mapper = new ObjectMapper();
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isCreated());
registrationDataList = registrationDataDAO.findAll(context, RegistrationData.class);
assertEquals(1, registrationDataList.size());
assertTrue(StringUtils.equalsIgnoreCase(registrationDataList.get(0).getEmail(), email));
} finally {
Iterator<RegistrationData> iterator = registrationDataList.iterator();
while (iterator.hasNext()) {
RegistrationData registrationData = iterator.next();
registrationDataDAO.delete(context, registrationData);
}
}
}
@Test
public void testRegisterDomainNotRegistered() throws Exception {
List<RegistrationData> registrationDataList;
try {
configurationService.setProperty("authentication-password.domain.valid", "test.com");
RegistrationRest registrationRest = new RegistrationRest();
String email = "testPerson@bladibla.com";
registrationRest.setEmail(email);
ObjectMapper mapper = new ObjectMapper();
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isUnprocessableEntity());
} finally {
registrationDataList = registrationDataDAO.findAll(context, RegistrationData.class);
Iterator<RegistrationData> iterator = registrationDataList.iterator();
while (iterator.hasNext()) {
RegistrationData registrationData = iterator.next();
registrationDataDAO.delete(context, registrationData);
}
}
}
@Test
public void testRegisterDomainNotRegisteredMailAddressRegistred() throws Exception {
List<RegistrationData> registrationDataList = registrationDataDAO.findAll(context, RegistrationData.class);
try {
context.turnOffAuthorisationSystem();
String email = "test@gmail.com";
EPersonBuilder.createEPerson(context)
.withEmail(email)
.withCanLogin(true)
.build();
context.restoreAuthSystemState();
configurationService.setProperty("authentication-password.domain.valid", "test.com");
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(email);
ObjectMapper mapper = new ObjectMapper();
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isUnprocessableEntity());
registrationDataList = registrationDataDAO.findAll(context, RegistrationData.class);
assertEquals(0, registrationDataList.size());
} finally {
Iterator<RegistrationData> iterator = registrationDataList.iterator();
while (iterator.hasNext()) {
RegistrationData registrationData = iterator.next();
registrationDataDAO.delete(context, registrationData);
}
}
}
@Test
public void forgotPasswordTest() throws Exception {
configurationService.setProperty("user.registration", false);
@@ -177,6 +269,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(eperson.getEmail());
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_FORGOT)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isCreated());
@@ -226,6 +319,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
String captchaToken = "invalid-captcha-Token";
// when reCAPTCHA enabled and request contains Invalid "X-Recaptcha-Token” header
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.header("X-Recaptcha-Token", captchaToken)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
@@ -262,12 +356,14 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
try {
// will throw InvalidReCaptchaException because 'X-Recaptcha-Token' not equal captchaToken
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.header("X-Recaptcha-Token", captchaToken1)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isForbidden());
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.header("X-Recaptcha-Token", captchaToken)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
@@ -280,6 +376,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
String newEmail = "newEPersonTest@gmail.com";
registrationRest.setEmail(newEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.header("X-Recaptcha-Token", captchaToken)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
@@ -295,6 +392,7 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
newEmail = "newEPersonTestTwo@gmail.com";
registrationRest.setEmail(newEmail);
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, TYPE_REGISTER)
.header("X-Recaptcha-Token", captchaToken)
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
@@ -321,4 +419,27 @@ public class RegistrationRestRepositoryIT extends AbstractControllerIntegrationT
captchaService.init();
}
@Test
public void accountEndpoint_WithoutAccountTypeParam() throws Exception {
ObjectMapper mapper = new ObjectMapper();
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(eperson.getEmail());
getClient().perform(post("/api/eperson/registrations")
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isBadRequest());
}
@Test
public void accountEndpoint_WrongAccountTypeParam() throws Exception {
ObjectMapper mapper = new ObjectMapper();
RegistrationRest registrationRest = new RegistrationRest();
registrationRest.setEmail(eperson.getEmail());
getClient().perform(post("/api/eperson/registrations")
.param(TYPE_QUERY_PARAM, "nonValidValue")
.content(mapper.writeValueAsBytes(registrationRest))
.contentType(contentType))
.andExpect(status().isBadRequest());
}
}

View File

@@ -0,0 +1,500 @@
/**
* 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.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
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.dspace.alerts.AllowSessionsEnum;
import org.dspace.alerts.SystemWideAlert;
import org.dspace.app.rest.model.SystemWideAlertRest;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.builder.SystemWideAlertBuilder;
import org.junit.Test;
/**
* Test class to test the operations in the SystemWideAlertRestRepository
*/
public class SystemWideAlertRestRepositoryIT extends AbstractControllerIntegrationTest {
@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 = 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);
getClient(authToken).perform(get("/api/system/systemwidealerts/"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.systemwidealerts", containsInAnyOrder(
allOf(
hasJsonPath("$.alertId", is(systemWideAlert1.getID())),
hasJsonPath("$.message", is(systemWideAlert1.getMessage())),
hasJsonPath("$.allowSessions", is(systemWideAlert1.getAllowSessions().getValue())),
hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlert1.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlert1.isActive()))
),
allOf(
hasJsonPath("$.alertId", is(systemWideAlert2.getID())),
hasJsonPath("$.message", is(systemWideAlert2.getMessage())),
hasJsonPath("$.allowSessions", is(systemWideAlert2.getAllowSessions().getValue())),
hasJsonPath("$.countdownTo", is(systemWideAlert2.getCountdownTo())),
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 = 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().getValue())),
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(
hasJsonPath("$.alertId", is(systemWideAlert1.getID())),
hasJsonPath("$.message", is(systemWideAlert1.getMessage())),
hasJsonPath("$.allowSessions",
is(systemWideAlert1.getAllowSessions().getValue())),
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().getValue())),
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().getValue())),
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().getValue())),
hasJsonPath("$.countdownTo", is(systemWideAlert3.getCountdownTo())),
hasJsonPath("$.active", is(systemWideAlert3.isActive()))
)
)));
}
@Test
public void createTest() throws Exception {
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setMessage("Alert test message");
systemWideAlertRest.setCountdownTo(new Date());
systemWideAlertRest.setAllowSessions(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue());
systemWideAlertRest.setActive(true);
ObjectMapper mapper = new ObjectMapper();
String authToken = getAuthToken(admin.getEmail(), password);
AtomicReference<Integer> idRef = new AtomicReference<>();
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
getClient(authToken).perform(post("/api/system/systemwidealerts/")
.content(mapper.writeValueAsBytes(systemWideAlertRest))
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(
jsonPath("$", allOf(
hasJsonPath("$.alertId"),
hasJsonPath("$.message", is(systemWideAlertRest.getMessage())),
hasJsonPath("$.allowSessions",
is(systemWideAlertRest.getAllowSessions())),
hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlertRest.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlertRest.isActive()))
)
))
.andDo(result -> idRef
.set((read(result.getResponse().getContentAsString(), "$.alertId"))));
getClient(authToken).perform(get("/api/system/systemwidealerts/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", allOf(
hasJsonPath("$.alertId", is(idRef.get())),
hasJsonPath("$.message", is(systemWideAlertRest.getMessage())),
hasJsonPath("$.allowSessions", is(systemWideAlertRest.getAllowSessions())),
hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlertRest.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlertRest.isActive()))
)
));
}
@Test
public void createForbiddenTest() throws Exception {
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setMessage("Alert test message");
systemWideAlertRest.setCountdownTo(new Date());
systemWideAlertRest.setAllowSessions(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue());
systemWideAlertRest.setActive(true);
ObjectMapper mapper = new ObjectMapper();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(post("/api/system/systemwidealerts/")
.content(mapper.writeValueAsBytes(systemWideAlertRest))
.contentType(contentType))
.andExpect(status().isForbidden());
}
@Test
public void createUnAuthorizedTest() throws Exception {
SystemWideAlertRest systemWideAlertRest = new SystemWideAlertRest();
systemWideAlertRest.setMessage("Alert test message");
systemWideAlertRest.setCountdownTo(new Date());
systemWideAlertRest.setAllowSessions(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue());
systemWideAlertRest.setActive(true);
ObjectMapper mapper = new ObjectMapper();
getClient().perform(post("/api/system/systemwidealerts/")
.content(mapper.writeValueAsBytes(systemWideAlertRest))
.contentType(contentType))
.andExpect(status().isUnauthorized());
}
@Test
public void createWhenAlreadyExistsTest() throws Exception {
context.turnOffAuthorisationSystem();
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");
systemWideAlertRest.setCountdownTo(new Date());
systemWideAlertRest.setAllowSessions(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue());
systemWideAlertRest.setActive(true);
ObjectMapper mapper = new ObjectMapper();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(post("/api/system/systemwidealerts/")
.content(mapper.writeValueAsBytes(systemWideAlertRest))
.contentType(contentType))
.andExpect(status().isBadRequest());
}
@Test
public void putTest() throws Exception {
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());
systemWideAlertRest.setMessage("Updated alert test message");
systemWideAlertRest.setCountdownTo(new Date());
systemWideAlertRest.setAllowSessions(AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY.getValue());
systemWideAlertRest.setActive(true);
ObjectMapper mapper = new ObjectMapper();
String authToken = getAuthToken(admin.getEmail(), password);
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
getClient(authToken).perform(put("/api/system/systemwidealerts/" + systemWideAlert.getID())
.content(mapper.writeValueAsBytes(systemWideAlertRest))
.contentType(contentType))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", allOf(
hasJsonPath("$.alertId"),
hasJsonPath("$.message", is(systemWideAlertRest.getMessage())),
hasJsonPath("$.allowSessions",
is(systemWideAlertRest.getAllowSessions())),
hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlertRest.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlertRest.isActive()))
)
));
getClient(authToken).perform(get("/api/system/systemwidealerts/" + systemWideAlert.getID()))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", allOf(
hasJsonPath("$.alertId", is(systemWideAlert.getID())),
hasJsonPath("$.message", is(systemWideAlertRest.getMessage())),
hasJsonPath("$.allowSessions", is(systemWideAlertRest.getAllowSessions())),
hasJsonPath("$.countdownTo",
startsWith(sdf.format(systemWideAlertRest.getCountdownTo()))),
hasJsonPath("$.active", is(systemWideAlertRest.isActive()))
)
));
}
}

View File

@@ -338,7 +338,7 @@ handle.dir = ${dspace.dir}/handle-server
# Whether to enable the DSpace listhandles resolver that lists all available
# handles for this DSpace installation.
# Defaults to "false" which means is possible to obtain the list of handles
# of this DSpace installation, whenever the `handle.remote-resolver.enabled = true`.
# of this DSpace installation, whenever the `handle.remote-resolver.enabled = true`.
# handle.hide.listhandles = false
##### Authorization system configuration - Delegate ADMIN #####
@@ -1228,8 +1228,6 @@ plugin.named.org.dspace.sort.OrderFormatDelegate= \
# starting with the value of the link clicked on.
#
# The default below defines the authors to link to other publications by that author
#
# TODO: UNSUPPORTED in DSpace 7.0
webui.browse.link.1 = author:dc.contributor.*
#### Display browse frequencies
@@ -1539,10 +1537,10 @@ log.report.dir = ${dspace.dir}/log
# The below example will run this task daily, every 5 minutes
# google.analytics.cron = 0 0/5 * * * ?
# Defines a Measurement Protocol API Secret to be used to track interactions which occur outside of the user's browser.
# Defines a Measurement Protocol API Secret to be used to track interactions which occur outside of the user's browser.
# For example , this is required to track downloads of bitstreams. This setting is only used by Google Analytics 4.
# For more details see https://developers.google.com/analytics/devguides/collection/protocol/ga4
# google.analytics.api-secret =
# google.analytics.api-secret =
####################################################################
#---------------------------------------------------------------#

View File

@@ -54,6 +54,7 @@
<mapping class="org.dspace.content.EntityType"/>
<mapping class="org.dspace.scripts.Process"/>
<mapping class="org.dspace.alerts.SystemWideAlert"/>
<mapping class="org.dspace.content.MetadataField"/>
<mapping class="org.dspace.content.MetadataSchema"/>

View File

@@ -6,6 +6,9 @@
#---------------------------------------------------------------#
#
# self-registration can be disabled completely by setting the user.registration property to false
# user.registration = false
# Only emails ending in the following domains are allowed to self-register
# Example - example.com domain : @example.com
# Example - MIT domain and all .ac.uk domains: @mit.edu, .ac.uk

View File

@@ -46,6 +46,7 @@ rest.properties.exposed = google.recaptcha.key.site
rest.properties.exposed = google.recaptcha.version
rest.properties.exposed = google.recaptcha.mode
rest.properties.exposed = cc.license.jurisdiction
rest.properties.exposed = authentication-password.domain.valid
#---------------------------------------------------------------#
# These configs are used by the deprecated REST (v4-6) module #

View File

@@ -34,6 +34,8 @@
<bean class="org.dspace.content.dao.impl.ProcessDAOImpl"/>
<bean class="org.dspace.alerts.dao.impl.SystemWideAlertDAOImpl"/>
<bean class="org.dspace.eperson.dao.impl.EPersonDAOImpl"/>
<bean class="org.dspace.eperson.dao.impl.Group2GroupCacheDAOImpl"/>
<bean class="org.dspace.eperson.dao.impl.GroupDAOImpl"/>

View File

@@ -59,6 +59,8 @@
<bean class="org.dspace.scripts.ProcessServiceImpl"/>
<bean class="org.dspace.scripts.ScriptServiceImpl"/>
<bean class="org.dspace.alerts.SystemWideAlertServiceImpl"/>
<bean class="org.dspace.content.authority.ChoiceAuthorityServiceImpl"/>
<bean class="org.dspace.content.authority.MetadataAuthorityServiceImpl" lazy-init="true"/>