mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-16 22:43:12 +00:00
CST-5249 dpspace.cfg conflicts fix
This commit is contained in:
@@ -7,18 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.sitemap;
|
package org.dspace.app.sitemap;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
@@ -29,12 +21,8 @@ import org.apache.commons.cli.Options;
|
|||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.content.Collection;
|
|
||||||
import org.dspace.content.Community;
|
|
||||||
import org.dspace.content.Item;
|
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
import org.dspace.content.service.CommunityService;
|
import org.dspace.content.service.CommunityService;
|
||||||
@@ -43,6 +31,7 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.LogHelper;
|
import org.dspace.core.LogHelper;
|
||||||
import org.dspace.discovery.DiscoverQuery;
|
import org.dspace.discovery.DiscoverQuery;
|
||||||
import org.dspace.discovery.DiscoverResult;
|
import org.dspace.discovery.DiscoverResult;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
import org.dspace.discovery.SearchService;
|
import org.dspace.discovery.SearchService;
|
||||||
import org.dspace.discovery.SearchServiceException;
|
import org.dspace.discovery.SearchServiceException;
|
||||||
import org.dspace.discovery.SearchUtils;
|
import org.dspace.discovery.SearchUtils;
|
||||||
@@ -68,6 +57,7 @@ public class GenerateSitemaps {
|
|||||||
private static final ConfigurationService configurationService =
|
private static final ConfigurationService configurationService =
|
||||||
DSpaceServicesFactory.getInstance().getConfigurationService();
|
DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
private static final SearchService searchService = SearchUtils.getSearchService();
|
private static final SearchService searchService = SearchUtils.getSearchService();
|
||||||
|
private static final int PAGE_SIZE = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
@@ -87,11 +77,6 @@ public class GenerateSitemaps {
|
|||||||
"do not generate sitemaps.org protocol sitemap");
|
"do not generate sitemaps.org protocol sitemap");
|
||||||
options.addOption("b", "no_htmlmap", false,
|
options.addOption("b", "no_htmlmap", false,
|
||||||
"do not generate a basic HTML sitemap");
|
"do not generate a basic HTML sitemap");
|
||||||
options.addOption("a", "ping_all", false,
|
|
||||||
"ping configured search engines");
|
|
||||||
options
|
|
||||||
.addOption("p", "ping", true,
|
|
||||||
"ping specified search engine URL");
|
|
||||||
options
|
options
|
||||||
.addOption("d", "delete", false,
|
.addOption("d", "delete", false,
|
||||||
"delete sitemaps dir and its contents");
|
"delete sitemaps dir and its contents");
|
||||||
@@ -116,14 +101,13 @@ public class GenerateSitemaps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check -- if no sitemap generation or pinging to do, or deletion, print usage
|
* Sanity check -- if no sitemap generation or deletion, print usage
|
||||||
*/
|
*/
|
||||||
if (line.getArgs().length != 0 || line.hasOption('d') || line.hasOption('b')
|
if (line.getArgs().length != 0 || line.hasOption('d') || line.hasOption('b')
|
||||||
&& line.hasOption('s') && !line.hasOption('g')
|
&& line.hasOption('s') && !line.hasOption('g')
|
||||||
&& !line.hasOption('m') && !line.hasOption('y')
|
&& !line.hasOption('m') && !line.hasOption('y')) {
|
||||||
&& !line.hasOption('p')) {
|
|
||||||
System.err
|
System.err
|
||||||
.println("Nothing to do (no sitemap to generate, no search engines to ping)");
|
.println("Nothing to do (no sitemap to generate)");
|
||||||
hf.printHelp(usage, options);
|
hf.printHelp(usage, options);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@@ -137,20 +121,6 @@ public class GenerateSitemaps {
|
|||||||
deleteSitemaps();
|
deleteSitemaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.hasOption('a')) {
|
|
||||||
pingConfiguredSearchEngines();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.hasOption('p')) {
|
|
||||||
try {
|
|
||||||
pingSearchEngine(line.getOptionValue('p'));
|
|
||||||
} catch (MalformedURLException me) {
|
|
||||||
System.err
|
|
||||||
.println("Bad search engine URL (include all except sitemap URL)");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,171 +181,113 @@ public class GenerateSitemaps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context c = new Context(Context.Mode.READ_ONLY);
|
Context c = new Context(Context.Mode.READ_ONLY);
|
||||||
|
int offset = 0;
|
||||||
List<Community> comms = communityService.findAll(c);
|
long commsCount = 0;
|
||||||
|
long collsCount = 0;
|
||||||
for (Community comm : comms) {
|
long itemsCount = 0;
|
||||||
String url = uiURLStem + "communities/" + comm.getID();
|
|
||||||
|
|
||||||
if (makeHTMLMap) {
|
|
||||||
html.addURL(url, null);
|
|
||||||
}
|
|
||||||
if (makeSitemapOrg) {
|
|
||||||
sitemapsOrg.addURL(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.uncacheEntity(comm);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Collection> colls = collectionService.findAll(c);
|
|
||||||
|
|
||||||
for (Collection coll : colls) {
|
|
||||||
String url = uiURLStem + "collections/" + coll.getID();
|
|
||||||
|
|
||||||
if (makeHTMLMap) {
|
|
||||||
html.addURL(url, null);
|
|
||||||
}
|
|
||||||
if (makeSitemapOrg) {
|
|
||||||
sitemapsOrg.addURL(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.uncacheEntity(coll);
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<Item> allItems = itemService.findAll(c);
|
|
||||||
int itemCount = 0;
|
|
||||||
|
|
||||||
while (allItems.hasNext()) {
|
|
||||||
Item i = allItems.next();
|
|
||||||
|
|
||||||
DiscoverQuery entityQuery = new DiscoverQuery();
|
|
||||||
entityQuery.setQuery("search.uniqueid:\"Item-" + i.getID() + "\" and entityType:*");
|
|
||||||
entityQuery.addSearchField("entityType");
|
|
||||||
|
|
||||||
try {
|
|
||||||
DiscoverResult discoverResult = searchService.search(c, entityQuery);
|
|
||||||
|
|
||||||
String url;
|
|
||||||
if (CollectionUtils.isNotEmpty(discoverResult.getIndexableObjects())
|
|
||||||
&& CollectionUtils.isNotEmpty(discoverResult.getSearchDocument(
|
|
||||||
discoverResult.getIndexableObjects().get(0)).get(0).getSearchFieldValues("entityType"))
|
|
||||||
&& StringUtils.isNotBlank(discoverResult.getSearchDocument(
|
|
||||||
discoverResult.getIndexableObjects().get(0)).get(0).getSearchFieldValues("entityType").get(0))
|
|
||||||
) {
|
|
||||||
url = uiURLStem + "entities/" + StringUtils.lowerCase(discoverResult.getSearchDocument(
|
|
||||||
discoverResult.getIndexableObjects().get(0))
|
|
||||||
.get(0).getSearchFieldValues("entityType").get(0)) + "/" + i.getID();
|
|
||||||
} else {
|
|
||||||
url = uiURLStem + "items/" + i.getID();
|
|
||||||
}
|
|
||||||
Date lastMod = i.getLastModified();
|
|
||||||
|
|
||||||
if (makeHTMLMap) {
|
|
||||||
html.addURL(url, lastMod);
|
|
||||||
}
|
|
||||||
if (makeSitemapOrg) {
|
|
||||||
sitemapsOrg.addURL(url, lastMod);
|
|
||||||
}
|
|
||||||
} catch (SearchServiceException e) {
|
|
||||||
log.error("Failed getting entitytype through solr for item " + i.getID() + ": " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
c.uncacheEntity(i);
|
|
||||||
|
|
||||||
itemCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (makeHTMLMap) {
|
|
||||||
int files = html.finish();
|
|
||||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
|
||||||
"type=html,num_files=" + files + ",communities="
|
|
||||||
+ comms.size() + ",collections=" + colls.size()
|
|
||||||
+ ",items=" + itemCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (makeSitemapOrg) {
|
|
||||||
int files = sitemapsOrg.finish();
|
|
||||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
|
||||||
"type=html,num_files=" + files + ",communities="
|
|
||||||
+ comms.size() + ",collections=" + colls.size()
|
|
||||||
+ ",items=" + itemCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ping all search engines configured in {@code dspace.cfg}.
|
|
||||||
*
|
|
||||||
* @throws UnsupportedEncodingException theoretically should never happen
|
|
||||||
*/
|
|
||||||
public static void pingConfiguredSearchEngines()
|
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
String[] engineURLs = configurationService
|
|
||||||
.getArrayProperty("sitemap.engineurls");
|
|
||||||
|
|
||||||
if (ArrayUtils.isEmpty(engineURLs)) {
|
|
||||||
log.warn("No search engine URLs configured to ping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < engineURLs.length; i++) {
|
|
||||||
try {
|
|
||||||
pingSearchEngine(engineURLs[i]);
|
|
||||||
} catch (MalformedURLException me) {
|
|
||||||
log.warn("Bad search engine URL in configuration: "
|
|
||||||
+ engineURLs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ping the given search engine.
|
|
||||||
*
|
|
||||||
* @param engineURL Search engine URL minus protocol etc, e.g.
|
|
||||||
* {@code www.google.com}
|
|
||||||
* @throws MalformedURLException if the passed in URL is malformed
|
|
||||||
* @throws UnsupportedEncodingException theoretically should never happen
|
|
||||||
*/
|
|
||||||
public static void pingSearchEngine(String engineURL)
|
|
||||||
throws MalformedURLException, UnsupportedEncodingException {
|
|
||||||
// Set up HTTP proxy
|
|
||||||
if ((StringUtils.isNotBlank(configurationService.getProperty("http.proxy.host")))
|
|
||||||
&& (StringUtils.isNotBlank(configurationService.getProperty("http.proxy.port")))) {
|
|
||||||
System.setProperty("proxySet", "true");
|
|
||||||
System.setProperty("proxyHost", configurationService
|
|
||||||
.getProperty("http.proxy.host"));
|
|
||||||
System.getProperty("proxyPort", configurationService
|
|
||||||
.getProperty("http.proxy.port"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String sitemapURL = configurationService.getProperty("dspace.ui.url")
|
|
||||||
+ "/sitemap";
|
|
||||||
|
|
||||||
URL url = new URL(engineURL + URLEncoder.encode(sitemapURL, "UTF-8"));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpURLConnection connection = (HttpURLConnection) url
|
DiscoverQuery discoveryQuery = new DiscoverQuery();
|
||||||
.openConnection();
|
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||||
|
discoveryQuery.setQuery("search.resourcetype:Community");
|
||||||
|
do {
|
||||||
|
discoveryQuery.setStart(offset);
|
||||||
|
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||||
|
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||||
|
commsCount = discoverResult.getTotalSearchResults();
|
||||||
|
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(
|
for (IndexableObject doc : docs) {
|
||||||
connection.getInputStream()));
|
String url = uiURLStem + "communities/" + doc.getID();
|
||||||
|
c.uncacheEntity(doc.getIndexedObject());
|
||||||
|
|
||||||
String inputLine;
|
if (makeHTMLMap) {
|
||||||
StringBuffer resp = new StringBuffer();
|
html.addURL(url, null);
|
||||||
while ((inputLine = in.readLine()) != null) {
|
}
|
||||||
resp.append(inputLine).append("\n");
|
if (makeSitemapOrg) {
|
||||||
|
sitemapsOrg.addURL(url, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += PAGE_SIZE;
|
||||||
|
} while (offset < commsCount);
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
discoveryQuery = new DiscoverQuery();
|
||||||
|
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||||
|
discoveryQuery.setQuery("search.resourcetype:Collection");
|
||||||
|
do {
|
||||||
|
discoveryQuery.setStart(offset);
|
||||||
|
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||||
|
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||||
|
collsCount = discoverResult.getTotalSearchResults();
|
||||||
|
|
||||||
|
for (IndexableObject doc : docs) {
|
||||||
|
String url = uiURLStem + "collections/" + doc.getID();
|
||||||
|
c.uncacheEntity(doc.getIndexedObject());
|
||||||
|
|
||||||
|
if (makeHTMLMap) {
|
||||||
|
html.addURL(url, null);
|
||||||
|
}
|
||||||
|
if (makeSitemapOrg) {
|
||||||
|
sitemapsOrg.addURL(url, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += PAGE_SIZE;
|
||||||
|
} while (offset < collsCount);
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
discoveryQuery = new DiscoverQuery();
|
||||||
|
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||||
|
discoveryQuery.setQuery("search.resourcetype:Item");
|
||||||
|
discoveryQuery.addSearchField("search.entitytype");
|
||||||
|
do {
|
||||||
|
|
||||||
|
discoveryQuery.setStart(offset);
|
||||||
|
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||||
|
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||||
|
itemsCount = discoverResult.getTotalSearchResults();
|
||||||
|
|
||||||
|
for (IndexableObject doc : docs) {
|
||||||
|
String url;
|
||||||
|
List<String> entityTypeFieldValues = discoverResult.getSearchDocument(doc).get(0)
|
||||||
|
.getSearchFieldValues("search.entitytype");
|
||||||
|
if (CollectionUtils.isNotEmpty(entityTypeFieldValues)) {
|
||||||
|
url = uiURLStem + "entities/" + StringUtils.lowerCase(entityTypeFieldValues.get(0)) + "/"
|
||||||
|
+ doc.getID();
|
||||||
|
} else {
|
||||||
|
url = uiURLStem + "items/" + doc.getID();
|
||||||
|
}
|
||||||
|
Date lastMod = doc.getLastModified();
|
||||||
|
c.uncacheEntity(doc.getIndexedObject());
|
||||||
|
|
||||||
|
if (makeHTMLMap) {
|
||||||
|
html.addURL(url, null);
|
||||||
|
}
|
||||||
|
if (makeSitemapOrg) {
|
||||||
|
sitemapsOrg.addURL(url, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += PAGE_SIZE;
|
||||||
|
} while (offset < itemsCount);
|
||||||
|
|
||||||
|
if (makeHTMLMap) {
|
||||||
|
int files = html.finish();
|
||||||
|
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||||
|
"type=html,num_files=" + files + ",communities="
|
||||||
|
+ commsCount + ",collections=" + collsCount
|
||||||
|
+ ",items=" + itemsCount));
|
||||||
}
|
}
|
||||||
in.close();
|
|
||||||
|
|
||||||
if (connection.getResponseCode() == 200) {
|
if (makeSitemapOrg) {
|
||||||
log.info("Pinged " + url.toString() + " successfully");
|
int files = sitemapsOrg.finish();
|
||||||
} else {
|
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||||
log.warn("Error response pinging " + url.toString() + ":\n"
|
"type=html,num_files=" + files + ",communities="
|
||||||
+ resp);
|
+ commsCount + ",collections=" + collsCount
|
||||||
|
+ ",items=" + itemsCount));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (SearchServiceException e) {
|
||||||
log.warn("Error pinging " + url.toString(), e);
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
c.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import org.dspace.content.Collection;
|
|||||||
import org.dspace.content.MetadataSchemaEnum;
|
import org.dspace.content.MetadataSchemaEnum;
|
||||||
import org.dspace.core.Utils;
|
import org.dspace.core.Utils;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.NamedNodeMap;
|
import org.w3c.dom.NamedNodeMap;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
@@ -158,7 +159,8 @@ public class DCInputsReader {
|
|||||||
throws DCInputsReaderException {
|
throws DCInputsReaderException {
|
||||||
SubmissionConfig config;
|
SubmissionConfig config;
|
||||||
try {
|
try {
|
||||||
config = new SubmissionConfigReader().getSubmissionConfigByCollection(collectionHandle);
|
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
|
||||||
|
.getSubmissionConfigByCollection(collectionHandle);
|
||||||
String formName = config.getSubmissionName();
|
String formName = config.getSubmissionName();
|
||||||
if (formName == null) {
|
if (formName == null) {
|
||||||
throw new DCInputsReaderException("No form designated as default");
|
throw new DCInputsReaderException("No form designated as default");
|
||||||
@@ -180,7 +182,8 @@ public class DCInputsReader {
|
|||||||
throws DCInputsReaderException {
|
throws DCInputsReaderException {
|
||||||
SubmissionConfig config;
|
SubmissionConfig config;
|
||||||
try {
|
try {
|
||||||
config = new SubmissionConfigReader().getSubmissionConfigByName(name);
|
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
|
||||||
|
.getSubmissionConfigByName(name);
|
||||||
String formName = config.getSubmissionName();
|
String formName = config.getSubmissionName();
|
||||||
if (formName == null) {
|
if (formName == null) {
|
||||||
throw new DCInputsReaderException("No form designated as default");
|
throw new DCInputsReaderException("No form designated as default");
|
||||||
|
@@ -153,6 +153,22 @@ public interface AuthenticationMethod {
|
|||||||
public List<Group> getSpecialGroups(Context context, HttpServletRequest request)
|
public List<Group> getSpecialGroups(Context context, HttpServletRequest request)
|
||||||
throws SQLException;
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the special groups returned by
|
||||||
|
* {@link org.dspace.authenticate.AuthenticationMethod#getSpecialGroups(Context, HttpServletRequest)}
|
||||||
|
* should be implicitly be added to the groups related to the current user. By
|
||||||
|
* default this is true if the authentication method is the actual
|
||||||
|
* authentication mechanism used by the user.
|
||||||
|
* @param context A valid DSpace context.
|
||||||
|
* @param request The request that started this operation, or null if not
|
||||||
|
* applicable.
|
||||||
|
* @return true is the special groups must be considered, false
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
public default boolean areSpecialGroupsApplicable(Context context, HttpServletRequest request) {
|
||||||
|
return getName().equals(context.getAuthenticationMethod());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate the given or implicit credentials.
|
* Authenticate the given or implicit credentials.
|
||||||
* This is the heart of the authentication method: test the
|
* This is the heart of the authentication method: test the
|
||||||
|
@@ -179,10 +179,15 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
|||||||
int totalLen = 0;
|
int totalLen = 0;
|
||||||
|
|
||||||
for (AuthenticationMethod method : getAuthenticationMethodStack()) {
|
for (AuthenticationMethod method : getAuthenticationMethodStack()) {
|
||||||
List<Group> gl = method.getSpecialGroups(context, request);
|
|
||||||
if (gl.size() > 0) {
|
if (method.areSpecialGroupsApplicable(context, request)) {
|
||||||
result.addAll(gl);
|
|
||||||
totalLen += gl.size();
|
List<Group> gl = method.getSpecialGroups(context, request);
|
||||||
|
if (gl.size() > 0) {
|
||||||
|
result.addAll(gl);
|
||||||
|
totalLen += gl.size();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -252,6 +252,11 @@ public class IPAuthentication implements AuthenticationMethod {
|
|||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areSpecialGroupsApplicable(Context context, HttpServletRequest request) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int authenticate(Context context, String username, String password,
|
public int authenticate(Context context, String username, String password,
|
||||||
String realm, HttpServletRequest request) throws SQLException {
|
String realm, HttpServletRequest request) throws SQLException {
|
||||||
|
@@ -494,6 +494,8 @@ public class LDAPAuthentication
|
|||||||
try {
|
try {
|
||||||
SearchControls ctrls = new SearchControls();
|
SearchControls ctrls = new SearchControls();
|
||||||
ctrls.setSearchScope(ldap_search_scope_value);
|
ctrls.setSearchScope(ldap_search_scope_value);
|
||||||
|
// Fetch both user attributes '*' (eg. uid, cn) and operational attributes '+' (eg. memberOf)
|
||||||
|
ctrls.setReturningAttributes(new String[] {"*", "+"});
|
||||||
|
|
||||||
String searchName;
|
String searchName;
|
||||||
if (useTLS) {
|
if (useTLS) {
|
||||||
@@ -700,21 +702,21 @@ public class LDAPAuthentication
|
|||||||
/*
|
/*
|
||||||
* Add authenticated users to the group defined in dspace.cfg by
|
* Add authenticated users to the group defined in dspace.cfg by
|
||||||
* the authentication-ldap.login.groupmap.* key.
|
* the authentication-ldap.login.groupmap.* key.
|
||||||
*
|
*
|
||||||
* @param dn
|
* @param dn
|
||||||
* The string containing distinguished name of the user
|
* The string containing distinguished name of the user
|
||||||
*
|
*
|
||||||
* @param group
|
* @param group
|
||||||
* List of strings with LDAP dn of groups
|
* List of strings with LDAP dn of groups
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* DSpace context
|
* DSpace context
|
||||||
*/
|
*/
|
||||||
private void assignGroups(String dn, ArrayList<String> group, Context context) {
|
private void assignGroups(String dn, ArrayList<String> group, Context context) {
|
||||||
if (StringUtils.isNotBlank(dn)) {
|
if (StringUtils.isNotBlank(dn)) {
|
||||||
System.out.println("dn:" + dn);
|
System.out.println("dn:" + dn);
|
||||||
int i = 1;
|
int groupmapIndex = 1;
|
||||||
String groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + i);
|
String groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + groupmapIndex);
|
||||||
boolean cmp;
|
boolean cmp;
|
||||||
|
|
||||||
|
|
||||||
@@ -725,52 +727,75 @@ public class LDAPAuthentication
|
|||||||
String ldapSearchString = t[0];
|
String ldapSearchString = t[0];
|
||||||
String dspaceGroupName = t[1];
|
String dspaceGroupName = t[1];
|
||||||
|
|
||||||
// list of strings with dn from LDAP groups
|
if (group == null) {
|
||||||
// inner loop
|
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
||||||
Iterator<String> groupIterator = group.iterator();
|
|
||||||
while (groupIterator.hasNext()) {
|
|
||||||
|
|
||||||
// save the current entry from iterator for further use
|
|
||||||
String currentGroup = groupIterator.next();
|
|
||||||
|
|
||||||
// very much the old code from DSpace <= 7.5
|
|
||||||
if (currentGroup == null) {
|
|
||||||
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
|
||||||
} else {
|
|
||||||
cmp = StringUtils.equalsIgnoreCase(currentGroup, ldapSearchString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmp) {
|
if (cmp) {
|
||||||
// assign user to this group
|
assignGroup(context, groupmapIndex, dspaceGroupName);
|
||||||
try {
|
}
|
||||||
Group ldapGroup = groupService.findByName(context, dspaceGroupName);
|
} else {
|
||||||
if (ldapGroup != null) {
|
// list of strings with dn from LDAP groups
|
||||||
groupService.addMember(context, ldapGroup, context.getCurrentUser());
|
// inner loop
|
||||||
groupService.update(context, ldapGroup);
|
Iterator<String> groupIterator = group.iterator();
|
||||||
} else {
|
while (groupIterator.hasNext()) {
|
||||||
// The group does not exist
|
|
||||||
log.warn(LogHelper.getHeader(context,
|
// save the current entry from iterator for further use
|
||||||
"ldap_assignGroupsBasedOnLdapDn",
|
String currentGroup = groupIterator.next();
|
||||||
"Group defined in authentication-ldap.login.groupmap." + i
|
|
||||||
+ " does not exist :: " + dspaceGroupName));
|
// very much the old code from DSpace <= 7.5
|
||||||
}
|
if (currentGroup == null) {
|
||||||
} catch (AuthorizeException ae) {
|
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
||||||
log.debug(LogHelper.getHeader(context,
|
} else {
|
||||||
"assignGroupsBasedOnLdapDn could not authorize addition to " +
|
cmp = StringUtils.equalsIgnoreCase(currentGroup, ldapSearchString);
|
||||||
"group",
|
}
|
||||||
dspaceGroupName));
|
|
||||||
} catch (SQLException e) {
|
if (cmp) {
|
||||||
log.debug(LogHelper.getHeader(context, "assignGroupsBasedOnLdapDn could not find group",
|
assignGroup(context, groupmapIndex, dspaceGroupName);
|
||||||
dspaceGroupName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + ++i);
|
groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + ++groupmapIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the current authenticated user to the specified group
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* DSpace context
|
||||||
|
*
|
||||||
|
* @param groupmapIndex
|
||||||
|
* authentication-ldap.login.groupmap.* key index defined in dspace.cfg
|
||||||
|
*
|
||||||
|
* @param dspaceGroupName
|
||||||
|
* The DSpace group to add the user to
|
||||||
|
*/
|
||||||
|
private void assignGroup(Context context, int groupmapIndex, String dspaceGroupName) {
|
||||||
|
try {
|
||||||
|
Group ldapGroup = groupService.findByName(context, dspaceGroupName);
|
||||||
|
if (ldapGroup != null) {
|
||||||
|
groupService.addMember(context, ldapGroup, context.getCurrentUser());
|
||||||
|
groupService.update(context, ldapGroup);
|
||||||
|
} else {
|
||||||
|
// The group does not exist
|
||||||
|
log.warn(LogHelper.getHeader(context,
|
||||||
|
"ldap_assignGroupsBasedOnLdapDn",
|
||||||
|
"Group defined in authentication-ldap.login.groupmap." + groupmapIndex
|
||||||
|
+ " does not exist :: " + dspaceGroupName));
|
||||||
|
}
|
||||||
|
} catch (AuthorizeException ae) {
|
||||||
|
log.debug(LogHelper.getHeader(context,
|
||||||
|
"assignGroupsBasedOnLdapDn could not authorize addition to " +
|
||||||
|
"group",
|
||||||
|
dspaceGroupName));
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.debug(LogHelper.getHeader(context, "assignGroupsBasedOnLdapDn could not find group",
|
||||||
|
dspaceGroupName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUsed(final Context context, final HttpServletRequest request) {
|
public boolean isUsed(final Context context, final HttpServletRequest request) {
|
||||||
if (request != null &&
|
if (request != null &&
|
||||||
|
@@ -451,7 +451,7 @@ public class AuthorizeServiceImpl implements AuthorizeService {
|
|||||||
if (e == null) {
|
if (e == null) {
|
||||||
return false; // anonymous users can't be admins....
|
return false; // anonymous users can't be admins....
|
||||||
} else {
|
} else {
|
||||||
return groupService.isMember(c, e, Group.ADMIN);
|
return groupService.isMember(c, e, c.getAdminGroup());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -276,6 +276,11 @@ public class BitstreamServiceImpl extends DSpaceObjectServiceImpl<Bitstream> imp
|
|||||||
//Remove our bitstream from all our bundles
|
//Remove our bitstream from all our bundles
|
||||||
final List<Bundle> bundles = bitstream.getBundles();
|
final List<Bundle> bundles = bitstream.getBundles();
|
||||||
for (Bundle bundle : bundles) {
|
for (Bundle bundle : bundles) {
|
||||||
|
authorizeService.authorizeAction(context, bundle, Constants.REMOVE);
|
||||||
|
//We also need to remove the bitstream id when it's set as bundle's primary bitstream
|
||||||
|
if (bitstream.equals(bundle.getPrimaryBitstream())) {
|
||||||
|
bundle.unsetPrimaryBitstreamID();
|
||||||
|
}
|
||||||
bundle.removeBitstream(bitstream);
|
bundle.removeBitstream(bitstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -126,7 +126,7 @@ public class Bundle extends DSpaceObject implements DSpaceObjectLegacySupport {
|
|||||||
* Unset the primary bitstream ID of the bundle
|
* Unset the primary bitstream ID of the bundle
|
||||||
*/
|
*/
|
||||||
public void unsetPrimaryBitstreamID() {
|
public void unsetPrimaryBitstreamID() {
|
||||||
primaryBitstream = null;
|
setPrimaryBitstreamID(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -25,7 +25,6 @@ import org.dspace.app.util.DCInputSet;
|
|||||||
import org.dspace.app.util.DCInputsReader;
|
import org.dspace.app.util.DCInputsReader;
|
||||||
import org.dspace.app.util.DCInputsReaderException;
|
import org.dspace.app.util.DCInputsReaderException;
|
||||||
import org.dspace.app.util.SubmissionConfig;
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
@@ -35,6 +34,8 @@ import org.dspace.core.service.PluginService;
|
|||||||
import org.dspace.discovery.configuration.DiscoveryConfigurationService;
|
import org.dspace.discovery.configuration.DiscoveryConfigurationService;
|
||||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +89,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
protected Map<String, DSpaceControlledVocabularyIndex> vocabularyIndexMap = new HashMap<>();
|
protected Map<String, DSpaceControlledVocabularyIndex> vocabularyIndexMap = new HashMap<>();
|
||||||
|
|
||||||
// the item submission reader
|
// the item submission reader
|
||||||
private SubmissionConfigReader itemSubmissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ConfigurationService configurationService;
|
protected ConfigurationService configurationService;
|
||||||
@@ -135,7 +136,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
private synchronized void init() {
|
private synchronized void init() {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
try {
|
try {
|
||||||
itemSubmissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
} catch (SubmissionConfigReaderException e) {
|
} catch (SubmissionConfigReaderException e) {
|
||||||
// the system is in an illegal state as the submission definition is not valid
|
// the system is in an illegal state as the submission definition is not valid
|
||||||
throw new IllegalStateException("Error reading the item submission configuration: " + e.getMessage(),
|
throw new IllegalStateException("Error reading the item submission configuration: " + e.getMessage(),
|
||||||
@@ -240,7 +241,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
// there is an authority configured for the metadata valid for some collections,
|
// there is an authority configured for the metadata valid for some collections,
|
||||||
// check if it is the requested collection
|
// check if it is the requested collection
|
||||||
Map<String, ChoiceAuthority> controllerFormDef = controllerFormDefinitions.get(fieldKey);
|
Map<String, ChoiceAuthority> controllerFormDef = controllerFormDefinitions.get(fieldKey);
|
||||||
SubmissionConfig submissionConfig = itemSubmissionConfigReader
|
SubmissionConfig submissionConfig = submissionConfigService
|
||||||
.getSubmissionConfigByCollection(collection.getHandle());
|
.getSubmissionConfigByCollection(collection.getHandle());
|
||||||
String submissionName = submissionConfig.getSubmissionName();
|
String submissionName = submissionConfig.getSubmissionName();
|
||||||
// check if the requested collection has a submission definition that use an authority for the metadata
|
// check if the requested collection has a submission definition that use an authority for the metadata
|
||||||
@@ -262,14 +263,14 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearCache() {
|
public void clearCache() throws SubmissionConfigReaderException {
|
||||||
controller.clear();
|
controller.clear();
|
||||||
authorities.clear();
|
authorities.clear();
|
||||||
presentation.clear();
|
presentation.clear();
|
||||||
closed.clear();
|
closed.clear();
|
||||||
controllerFormDefinitions.clear();
|
controllerFormDefinitions.clear();
|
||||||
authoritiesFormDefinitions.clear();
|
authoritiesFormDefinitions.clear();
|
||||||
itemSubmissionConfigReader = null;
|
submissionConfigService.reload();
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +320,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
*/
|
*/
|
||||||
private void autoRegisterChoiceAuthorityFromInputReader() {
|
private void autoRegisterChoiceAuthorityFromInputReader() {
|
||||||
try {
|
try {
|
||||||
List<SubmissionConfig> submissionConfigs = itemSubmissionConfigReader
|
List<SubmissionConfig> submissionConfigs = submissionConfigService
|
||||||
.getAllSubmissionConfigs(Integer.MAX_VALUE, 0);
|
.getAllSubmissionConfigs(Integer.MAX_VALUE, 0);
|
||||||
DCInputsReader dcInputsReader = new DCInputsReader();
|
DCInputsReader dcInputsReader = new DCInputsReader();
|
||||||
|
|
||||||
@@ -490,10 +491,11 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
|||||||
init();
|
init();
|
||||||
ChoiceAuthority ma = controller.get(fieldKey);
|
ChoiceAuthority ma = controller.get(fieldKey);
|
||||||
if (ma == null && collection != null) {
|
if (ma == null && collection != null) {
|
||||||
SubmissionConfigReader configReader;
|
SubmissionConfigService configReaderService;
|
||||||
try {
|
try {
|
||||||
configReader = new SubmissionConfigReader();
|
configReaderService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
SubmissionConfig submissionName = configReader.getSubmissionConfigByCollection(collection.getHandle());
|
SubmissionConfig submissionName = configReaderService
|
||||||
|
.getSubmissionConfigByCollection(collection.getHandle());
|
||||||
ma = controllerFormDefinitions.get(fieldKey).get(submissionName.getSubmissionName());
|
ma = controllerFormDefinitions.get(fieldKey).get(submissionName.getSubmissionName());
|
||||||
} catch (SubmissionConfigReaderException e) {
|
} catch (SubmissionConfigReaderException e) {
|
||||||
// the system is in an illegal state as the submission definition is not valid
|
// the system is in an illegal state as the submission definition is not valid
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.content.authority.service;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
import org.dspace.content.authority.Choice;
|
import org.dspace.content.authority.Choice;
|
||||||
@@ -174,7 +175,7 @@ public interface ChoiceAuthorityService {
|
|||||||
/**
|
/**
|
||||||
* This method has been created to have a way of clearing the cache kept inside the service
|
* This method has been created to have a way of clearing the cache kept inside the service
|
||||||
*/
|
*/
|
||||||
public void clearCache();
|
public void clearCache() throws SubmissionConfigReaderException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should we store the authority key (if any) for such field key and collection?
|
* Should we store the authority key (if any) for such field key and collection?
|
||||||
|
@@ -68,9 +68,9 @@ public class BitstreamDAOImpl extends AbstractHibernateDSODAO<Bitstream> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Bitstream> findBitstreamsWithNoRecentChecksum(Context context) throws SQLException {
|
public List<Bitstream> findBitstreamsWithNoRecentChecksum(Context context) throws SQLException {
|
||||||
Query query = createQuery(context,
|
Query query = createQuery(context, "SELECT b FROM MostRecentChecksum c RIGHT JOIN Bitstream b " +
|
||||||
"select b from Bitstream b where b not in (select c.bitstream from " +
|
"ON c.bitstream = b WHERE c IS NULL" );
|
||||||
"MostRecentChecksum c)");
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -83,13 +83,14 @@ public abstract class AbstractHibernateDSODAO<T extends DSpaceObject> extends Ab
|
|||||||
if (CollectionUtils.isNotEmpty(metadataFields) || StringUtils.isNotBlank(additionalWhere)) {
|
if (CollectionUtils.isNotEmpty(metadataFields) || StringUtils.isNotBlank(additionalWhere)) {
|
||||||
//Add the where query on metadata
|
//Add the where query on metadata
|
||||||
query.append(" WHERE ");
|
query.append(" WHERE ");
|
||||||
|
// Group the 'OR' clauses below in outer parentheses, e.g. "WHERE (clause1 OR clause2 OR clause3)".
|
||||||
|
// Grouping these 'OR' clauses allows for later code to append 'AND' clauses without unexpected behaviors
|
||||||
|
query.append("(");
|
||||||
for (int i = 0; i < metadataFields.size(); i++) {
|
for (int i = 0; i < metadataFields.size(); i++) {
|
||||||
MetadataField metadataField = metadataFields.get(i);
|
MetadataField metadataField = metadataFields.get(i);
|
||||||
if (StringUtils.isNotBlank(operator)) {
|
if (StringUtils.isNotBlank(operator)) {
|
||||||
query.append(" (");
|
|
||||||
query.append("lower(STR(" + metadataField.toString()).append(".value)) ").append(operator)
|
query.append("lower(STR(" + metadataField.toString()).append(".value)) ").append(operator)
|
||||||
.append(" lower(:queryParam)");
|
.append(" lower(:queryParam)");
|
||||||
query.append(")");
|
|
||||||
if (i < metadataFields.size() - 1) {
|
if (i < metadataFields.size() - 1) {
|
||||||
query.append(" OR ");
|
query.append(" OR ");
|
||||||
}
|
}
|
||||||
@@ -102,6 +103,7 @@ public abstract class AbstractHibernateDSODAO<T extends DSpaceObject> extends Ab
|
|||||||
}
|
}
|
||||||
query.append(additionalWhere);
|
query.append(additionalWhere);
|
||||||
}
|
}
|
||||||
|
query.append(")");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -128,6 +128,11 @@ public class Context implements AutoCloseable {
|
|||||||
|
|
||||||
private DBConnection dbConnection;
|
private DBConnection dbConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default administrator group
|
||||||
|
*/
|
||||||
|
private Group adminGroup;
|
||||||
|
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
READ_ONLY,
|
READ_ONLY,
|
||||||
READ_WRITE,
|
READ_WRITE,
|
||||||
@@ -810,6 +815,15 @@ public class Context implements AutoCloseable {
|
|||||||
readOnlyCache.clear();
|
readOnlyCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When going to READ_ONLY, flush database changes to ensure that the current data is retrieved
|
||||||
|
if (newMode == Mode.READ_ONLY && mode != Mode.READ_ONLY) {
|
||||||
|
try {
|
||||||
|
dbConnection.flushSession();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
log.warn("Unable to flush database changes after switching to READ_ONLY mode", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//save the new mode
|
//save the new mode
|
||||||
mode = newMode;
|
mode = newMode;
|
||||||
}
|
}
|
||||||
@@ -951,4 +965,15 @@ public class Context implements AutoCloseable {
|
|||||||
public boolean isContextUserSwitched() {
|
public boolean isContextUserSwitched() {
|
||||||
return currentUserPreviousState != null;
|
return currentUserPreviousState != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default "Administrator" group for DSpace administrators.
|
||||||
|
* The result is cached in the 'adminGroup' field, so it is only looked up once.
|
||||||
|
* This is done to improve performance, as this method is called quite often.
|
||||||
|
*/
|
||||||
|
public Group getAdminGroup() throws SQLException {
|
||||||
|
return (adminGroup == null) ? EPersonServiceFactory.getInstance()
|
||||||
|
.getGroupService()
|
||||||
|
.findByName(this, Group.ADMIN) : adminGroup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -148,4 +148,12 @@ public interface DBConnection<T> {
|
|||||||
* @throws java.sql.SQLException passed through.
|
* @throws java.sql.SQLException passed through.
|
||||||
*/
|
*/
|
||||||
public <E extends ReloadableEntity> void uncacheEntity(E entity) throws SQLException;
|
public <E extends ReloadableEntity> void uncacheEntity(E entity) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a manual flush. This synchronizes the in-memory state of the Session
|
||||||
|
* with the database (write changes to the database)
|
||||||
|
*
|
||||||
|
* @throws SQLException passed through.
|
||||||
|
*/
|
||||||
|
public void flushSession() throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -337,4 +337,17 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a manual flush. This synchronizes the in-memory state of the Session
|
||||||
|
* with the database (write changes to the database)
|
||||||
|
*
|
||||||
|
* @throws SQLException passed through.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void flushSession() throws SQLException {
|
||||||
|
if (getSession().isDirty()) {
|
||||||
|
getSession().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -152,17 +152,10 @@ public class Curation extends DSpaceRunnable<CurationScriptConfiguration> {
|
|||||||
super.handler.logInfo("Curating id: " + entry.getObjectId());
|
super.handler.logInfo("Curating id: " + entry.getObjectId());
|
||||||
}
|
}
|
||||||
curator.clear();
|
curator.clear();
|
||||||
// does entry relate to a DSO or workflow object?
|
for (String taskName : entry.getTaskNames()) {
|
||||||
if (entry.getObjectId().indexOf('/') > 0) {
|
curator.addTask(taskName);
|
||||||
for (String taskName : entry.getTaskNames()) {
|
|
||||||
curator.addTask(taskName);
|
|
||||||
}
|
|
||||||
curator.curate(context, entry.getObjectId());
|
|
||||||
} else {
|
|
||||||
// TODO: Remove this exception once curation tasks are supported by configurable workflow
|
|
||||||
// e.g. see https://github.com/DSpace/DSpace/pull/3157
|
|
||||||
throw new IllegalArgumentException("curation for workflow items is no longer supported");
|
|
||||||
}
|
}
|
||||||
|
curator.curate(context, entry.getObjectId());
|
||||||
}
|
}
|
||||||
queue.release(this.queue, ticket, true);
|
queue.release(this.queue, ticket, true);
|
||||||
return ticket;
|
return ticket;
|
||||||
|
@@ -13,6 +13,7 @@ import java.sql.SQLException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -139,40 +140,47 @@ public class XmlWorkflowCuratorServiceImpl
|
|||||||
item.setOwningCollection(wfi.getCollection());
|
item.setOwningCollection(wfi.getCollection());
|
||||||
for (Task task : step.tasks) {
|
for (Task task : step.tasks) {
|
||||||
curator.addTask(task.name);
|
curator.addTask(task.name);
|
||||||
curator.curate(c, item);
|
// Check whether the task is configured to be queued rather than automatically run
|
||||||
int status = curator.getStatus(task.name);
|
if (StringUtils.isNotEmpty(step.queue)) {
|
||||||
String result = curator.getResult(task.name);
|
// queue attribute has been set in the FlowStep configuration: add task to configured queue
|
||||||
String action = "none";
|
curator.queue(c, item.getID().toString(), step.queue);
|
||||||
switch (status) {
|
} else {
|
||||||
case Curator.CURATE_FAIL:
|
// Task is configured to be run automatically
|
||||||
// task failed - notify any contacts the task has assigned
|
curator.curate(c, item);
|
||||||
if (task.powers.contains("reject")) {
|
int status = curator.getStatus(task.name);
|
||||||
action = "reject";
|
String result = curator.getResult(task.name);
|
||||||
}
|
String action = "none";
|
||||||
notifyContacts(c, wfi, task, "fail", action, result);
|
switch (status) {
|
||||||
// if task so empowered, reject submission and terminate
|
case Curator.CURATE_FAIL:
|
||||||
if ("reject".equals(action)) {
|
// task failed - notify any contacts the task has assigned
|
||||||
workflowService.sendWorkflowItemBackSubmission(c, wfi,
|
if (task.powers.contains("reject")) {
|
||||||
c.getCurrentUser(), null,
|
action = "reject";
|
||||||
task.name + ": " + result);
|
}
|
||||||
return false;
|
notifyContacts(c, wfi, task, "fail", action, result);
|
||||||
}
|
// if task so empowered, reject submission and terminate
|
||||||
break;
|
if ("reject".equals(action)) {
|
||||||
case Curator.CURATE_SUCCESS:
|
workflowService.sendWorkflowItemBackSubmission(c, wfi,
|
||||||
if (task.powers.contains("approve")) {
|
c.getCurrentUser(), null,
|
||||||
action = "approve";
|
task.name + ": " + result);
|
||||||
}
|
return false;
|
||||||
notifyContacts(c, wfi, task, "success", action, result);
|
}
|
||||||
if ("approve".equals(action)) {
|
break;
|
||||||
// cease further task processing and advance submission
|
case Curator.CURATE_SUCCESS:
|
||||||
return true;
|
if (task.powers.contains("approve")) {
|
||||||
}
|
action = "approve";
|
||||||
break;
|
}
|
||||||
case Curator.CURATE_ERROR:
|
notifyContacts(c, wfi, task, "success", action, result);
|
||||||
notifyContacts(c, wfi, task, "error", action, result);
|
if ("approve".equals(action)) {
|
||||||
break;
|
// cease further task processing and advance submission
|
||||||
default:
|
return true;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
case Curator.CURATE_ERROR:
|
||||||
|
notifyContacts(c, wfi, task, "error", action, result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
curator.clear();
|
curator.clear();
|
||||||
}
|
}
|
||||||
|
@@ -154,7 +154,11 @@ public class IndexEventConsumer implements Consumer {
|
|||||||
|
|
||||||
case Event.REMOVE:
|
case Event.REMOVE:
|
||||||
case Event.ADD:
|
case Event.ADD:
|
||||||
if (object == null) {
|
// At this time, ADD and REMOVE actions are ignored on SITE object. They are only triggered for
|
||||||
|
// top-level communities. No action is necessary as Community itself is indexed (or deleted) separately.
|
||||||
|
if (event.getSubjectType() == Constants.SITE) {
|
||||||
|
log.debug(event.getEventTypeAsString() + " event triggered for Site object. Skipping it.");
|
||||||
|
} else if (object == null) {
|
||||||
log.warn(event.getEventTypeAsString() + " event, could not get object for "
|
log.warn(event.getEventTypeAsString() + " event, could not get object for "
|
||||||
+ event.getObjectTypeAsString() + " id="
|
+ event.getObjectTypeAsString() + " id="
|
||||||
+ event.getObjectID()
|
+ event.getObjectID()
|
||||||
@@ -201,6 +205,10 @@ public class IndexEventConsumer implements Consumer {
|
|||||||
@Override
|
@Override
|
||||||
public void end(Context ctx) throws Exception {
|
public void end(Context ctx) throws Exception {
|
||||||
|
|
||||||
|
// Change the mode to readonly to improve performance
|
||||||
|
Context.Mode originalMode = ctx.getCurrentMode();
|
||||||
|
ctx.setMode(Context.Mode.READ_ONLY);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (String uid : uniqueIdsToDelete) {
|
for (String uid : uniqueIdsToDelete) {
|
||||||
try {
|
try {
|
||||||
@@ -230,6 +238,8 @@ public class IndexEventConsumer implements Consumer {
|
|||||||
uniqueIdsToDelete.clear();
|
uniqueIdsToDelete.clear();
|
||||||
createdItemsToUpdate.clear();
|
createdItemsToUpdate.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.setMode(originalMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1031,9 +1031,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
|||||||
// Add information about our search fields
|
// Add information about our search fields
|
||||||
for (String field : searchFields) {
|
for (String field : searchFields) {
|
||||||
List<String> valuesAsString = new ArrayList<>();
|
List<String> valuesAsString = new ArrayList<>();
|
||||||
for (Object o : doc.getFieldValues(field)) {
|
Optional.ofNullable(doc.getFieldValues(field))
|
||||||
valuesAsString.add(String.valueOf(o));
|
.ifPresent(l -> l.forEach(o -> valuesAsString.add(String.valueOf(o))));
|
||||||
}
|
|
||||||
resultDoc.addSearchField(field, valuesAsString.toArray(new String[valuesAsString.size()]));
|
resultDoc.addSearchField(field, valuesAsString.toArray(new String[valuesAsString.size()]));
|
||||||
}
|
}
|
||||||
result.addSearchDocument(indexableObject, resultDoc);
|
result.addSearchDocument(indexableObject, resultDoc);
|
||||||
|
@@ -188,32 +188,98 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EPerson> search(Context context, String query, int offset, int limit) throws SQLException {
|
public List<EPerson> search(Context context, String query, int offset, int limit) throws SQLException {
|
||||||
try {
|
List<EPerson> ePersons = new ArrayList<>();
|
||||||
List<EPerson> ePerson = new ArrayList<>();
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
EPerson person = find(context, UUID.fromString(query));
|
if (uuid == null) {
|
||||||
if (person != null) {
|
// Search by firstname & lastname (NOTE: email will also be included automatically)
|
||||||
ePerson.add(person);
|
|
||||||
}
|
|
||||||
return ePerson;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||||
if (StringUtils.isBlank(query)) {
|
if (StringUtils.isBlank(query)) {
|
||||||
query = null;
|
query = null;
|
||||||
}
|
}
|
||||||
return ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField),
|
ePersons = ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||||
Arrays.asList(firstNameField, lastNameField), offset, limit);
|
Arrays.asList(firstNameField, lastNameField), offset, limit);
|
||||||
|
} else {
|
||||||
|
// Search by UUID
|
||||||
|
EPerson person = find(context, uuid);
|
||||||
|
if (person != null) {
|
||||||
|
ePersons.add(person);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return ePersons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int searchResultCount(Context context, String query) throws SQLException {
|
public int searchResultCount(Context context, String query) throws SQLException {
|
||||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
int result = 0;
|
||||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
if (StringUtils.isBlank(query)) {
|
if (uuid == null) {
|
||||||
query = null;
|
// Count results found by firstname & lastname (email is also included automatically)
|
||||||
|
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||||
|
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||||
|
if (StringUtils.isBlank(query)) {
|
||||||
|
query = null;
|
||||||
|
}
|
||||||
|
result = ePersonDAO.searchResultCount(context, query, Arrays.asList(firstNameField, lastNameField));
|
||||||
|
} else {
|
||||||
|
// Search by UUID
|
||||||
|
EPerson person = find(context, uuid);
|
||||||
|
if (person != null) {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ePersonDAO.searchResultCount(context, query, Arrays.asList(firstNameField, lastNameField));
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EPerson> searchNonMembers(Context context, String query, Group excludeGroup, int offset, int limit)
|
||||||
|
throws SQLException {
|
||||||
|
List<EPerson> ePersons = new ArrayList<>();
|
||||||
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
|
if (uuid == null) {
|
||||||
|
// Search by firstname & lastname (NOTE: email will also be included automatically)
|
||||||
|
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||||
|
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||||
|
if (StringUtils.isBlank(query)) {
|
||||||
|
query = null;
|
||||||
|
}
|
||||||
|
ePersons = ePersonDAO.searchNotMember(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||||
|
excludeGroup, Arrays.asList(firstNameField, lastNameField),
|
||||||
|
offset, limit);
|
||||||
|
} else {
|
||||||
|
// Search by UUID
|
||||||
|
EPerson person = find(context, uuid);
|
||||||
|
// Verify EPerson is NOT a member of the given excludeGroup before adding
|
||||||
|
if (person != null && !groupService.isDirectMember(excludeGroup, person)) {
|
||||||
|
ePersons.add(person);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ePersons;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int searchNonMembersCount(Context context, String query, Group excludeGroup) throws SQLException {
|
||||||
|
int result = 0;
|
||||||
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
|
if (uuid == null) {
|
||||||
|
// Count results found by firstname & lastname (email is also included automatically)
|
||||||
|
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||||
|
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||||
|
if (StringUtils.isBlank(query)) {
|
||||||
|
query = null;
|
||||||
|
}
|
||||||
|
result = ePersonDAO.searchNotMemberCount(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||||
|
excludeGroup);
|
||||||
|
} else {
|
||||||
|
// Search by UUID
|
||||||
|
EPerson person = find(context, uuid);
|
||||||
|
// Verify EPerson is NOT a member of the given excludeGroup before counting
|
||||||
|
if (person != null && !groupService.isDirectMember(excludeGroup, person)) {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -309,10 +375,13 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
|||||||
throw new AuthorizeException(
|
throw new AuthorizeException(
|
||||||
"You must be an admin to delete an EPerson");
|
"You must be an admin to delete an EPerson");
|
||||||
}
|
}
|
||||||
|
// Get all workflow-related groups that the current EPerson belongs to
|
||||||
Set<Group> workFlowGroups = getAllWorkFlowGroups(context, ePerson);
|
Set<Group> workFlowGroups = getAllWorkFlowGroups(context, ePerson);
|
||||||
for (Group group: workFlowGroups) {
|
for (Group group: workFlowGroups) {
|
||||||
List<EPerson> ePeople = groupService.allMembers(context, group);
|
// Get total number of unique EPerson objs who are a member of this group (or subgroup)
|
||||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
int totalMembers = groupService.countAllMembers(context, group);
|
||||||
|
// If only one EPerson is a member, then we cannot delete the last member of this group.
|
||||||
|
if (totalMembers == 1) {
|
||||||
throw new EmptyWorkflowGroupException(ePerson.getID(), group.getID());
|
throw new EmptyWorkflowGroupException(ePerson.getID(), group.getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,14 +645,29 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException {
|
public List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException {
|
||||||
|
return findByGroups(c, groups, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EPerson> findByGroups(Context c, Set<Group> groups, int pageSize, int offset) throws SQLException {
|
||||||
//Make sure we at least have one group, if not don't even bother searching.
|
//Make sure we at least have one group, if not don't even bother searching.
|
||||||
if (CollectionUtils.isNotEmpty(groups)) {
|
if (CollectionUtils.isNotEmpty(groups)) {
|
||||||
return ePersonDAO.findByGroups(c, groups);
|
return ePersonDAO.findByGroups(c, groups, pageSize, offset);
|
||||||
} else {
|
} else {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countByGroups(Context c, Set<Group> groups) throws SQLException {
|
||||||
|
//Make sure we at least have one group, if not don't even bother counting.
|
||||||
|
if (CollectionUtils.isNotEmpty(groups)) {
|
||||||
|
return ePersonDAO.countByGroups(c, groups);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EPerson> findEPeopleWithSubscription(Context context) throws SQLException {
|
public List<EPerson> findEPeopleWithSubscription(Context context) throws SQLException {
|
||||||
return ePersonDAO.findAllSubscribers(context);
|
return ePersonDAO.findAllSubscribers(context);
|
||||||
|
@@ -98,7 +98,11 @@ public class Group extends DSpaceObject implements DSpaceObjectLegacySupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return EPerson members of a Group
|
* Return EPerson members of a Group.
|
||||||
|
* <P>
|
||||||
|
* WARNING: This method may have bad performance for Groups with large numbers of EPerson members.
|
||||||
|
* Therefore, only use this when you need to access every EPerson member. Instead, consider using
|
||||||
|
* EPersonService.findByGroups() for a paginated list of EPersons.
|
||||||
*
|
*
|
||||||
* @return list of EPersons
|
* @return list of EPersons
|
||||||
*/
|
*/
|
||||||
@@ -143,9 +147,13 @@ public class Group extends DSpaceObject implements DSpaceObjectLegacySupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return Group members of a Group.
|
* Return Group members (i.e. direct subgroups) of a Group.
|
||||||
|
* <P>
|
||||||
|
* WARNING: This method may have bad performance for Groups with large numbers of Subgroups.
|
||||||
|
* Therefore, only use this when you need to access every Subgroup. Instead, consider using
|
||||||
|
* GroupService.findByParent() for a paginated list of Subgroups.
|
||||||
*
|
*
|
||||||
* @return list of groups
|
* @return list of subgroups
|
||||||
*/
|
*/
|
||||||
public List<Group> getMemberGroups() {
|
public List<Group> getMemberGroups() {
|
||||||
return groups;
|
return groups;
|
||||||
|
@@ -179,8 +179,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
for (CollectionRole collectionRole : collectionRoles) {
|
for (CollectionRole collectionRole : collectionRoles) {
|
||||||
if (StringUtils.equals(collectionRole.getRoleId(), role.getId())
|
if (StringUtils.equals(collectionRole.getRoleId(), role.getId())
|
||||||
&& claimedTask.getWorkflowItem().getCollection() == collectionRole.getCollection()) {
|
&& claimedTask.getWorkflowItem().getCollection() == collectionRole.getCollection()) {
|
||||||
List<EPerson> ePeople = allMembers(context, group);
|
// Count number of EPersons who are *direct* members of this group
|
||||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group));
|
||||||
|
// Count number of Groups which have this groupParent as a direct parent
|
||||||
|
int totalChildGroups = countByParent(context, group);
|
||||||
|
// If this group has only one direct EPerson and *zero* child groups, then we cannot delete the
|
||||||
|
// EPerson or we will leave this group empty.
|
||||||
|
if (totalDirectEPersons == 1 && totalChildGroups == 0) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Refused to remove user " + ePerson
|
"Refused to remove user " + ePerson
|
||||||
.getID() + " from workflow group because the group " + group
|
.getID() + " from workflow group because the group " + group
|
||||||
@@ -191,8 +196,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!poolTasks.isEmpty()) {
|
if (!poolTasks.isEmpty()) {
|
||||||
List<EPerson> ePeople = allMembers(context, group);
|
// Count number of EPersons who are *direct* members of this group
|
||||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group));
|
||||||
|
// Count number of Groups which have this groupParent as a direct parent
|
||||||
|
int totalChildGroups = countByParent(context, group);
|
||||||
|
// If this group has only one direct EPerson and *zero* child groups, then we cannot delete the
|
||||||
|
// EPerson or we will leave this group empty.
|
||||||
|
if (totalDirectEPersons == 1 && totalChildGroups == 0) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Refused to remove user " + ePerson
|
"Refused to remove user " + ePerson
|
||||||
.getID() + " from workflow group because the group " + group
|
.getID() + " from workflow group because the group " + group
|
||||||
@@ -212,9 +222,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
if (!collectionRoles.isEmpty()) {
|
if (!collectionRoles.isEmpty()) {
|
||||||
List<PoolTask> poolTasks = poolTaskService.findByGroup(context, groupParent);
|
List<PoolTask> poolTasks = poolTaskService.findByGroup(context, groupParent);
|
||||||
if (!poolTasks.isEmpty()) {
|
if (!poolTasks.isEmpty()) {
|
||||||
List<EPerson> parentPeople = allMembers(context, groupParent);
|
// Count number of Groups which have this groupParent as a direct parent
|
||||||
List<EPerson> childPeople = allMembers(context, childGroup);
|
int totalChildGroups = countByParent(context, groupParent);
|
||||||
if (childPeople.containsAll(parentPeople)) {
|
// Count number of EPersons who are *direct* members of this group
|
||||||
|
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(groupParent));
|
||||||
|
// If this group has only one childGroup and *zero* direct EPersons, then we cannot delete the
|
||||||
|
// childGroup or we will leave this group empty.
|
||||||
|
if (totalChildGroups == 1 && totalDirectEPersons == 0) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Refused to remove sub group " + childGroup
|
"Refused to remove sub group " + childGroup
|
||||||
.getID() + " from workflow group because the group " + groupParent
|
.getID() + " from workflow group because the group " + groupParent
|
||||||
@@ -368,7 +382,8 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
|
|
||||||
// Get all groups which are a member of this group
|
// Get all groups which are a member of this group
|
||||||
List<Group2GroupCache> group2GroupCaches = group2GroupCacheDAO.findByParent(c, g);
|
List<Group2GroupCache> group2GroupCaches = group2GroupCacheDAO.findByParent(c, g);
|
||||||
Set<Group> groups = new HashSet<>();
|
// Initialize HashSet based on List size to avoid Set resizing. See https://stackoverflow.com/a/21822273
|
||||||
|
Set<Group> groups = new HashSet<>((int) (group2GroupCaches.size() / 0.75 + 1));
|
||||||
for (Group2GroupCache group2GroupCache : group2GroupCaches) {
|
for (Group2GroupCache group2GroupCache : group2GroupCaches) {
|
||||||
groups.add(group2GroupCache.getChild());
|
groups.add(group2GroupCache.getChild());
|
||||||
}
|
}
|
||||||
@@ -381,6 +396,23 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
return new ArrayList<>(childGroupChildren);
|
return new ArrayList<>(childGroupChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countAllMembers(Context context, Group group) throws SQLException {
|
||||||
|
// Get all groups which are a member of this group
|
||||||
|
List<Group2GroupCache> group2GroupCaches = group2GroupCacheDAO.findByParent(context, group);
|
||||||
|
// Initialize HashSet based on List size + current 'group' to avoid Set resizing.
|
||||||
|
// See https://stackoverflow.com/a/21822273
|
||||||
|
Set<Group> groups = new HashSet<>((int) ((group2GroupCaches.size() + 1) / 0.75 + 1));
|
||||||
|
for (Group2GroupCache group2GroupCache : group2GroupCaches) {
|
||||||
|
groups.add(group2GroupCache.getChild());
|
||||||
|
}
|
||||||
|
// Append current group as well
|
||||||
|
groups.add(group);
|
||||||
|
|
||||||
|
// Return total number of unique EPerson objects in any of these groups
|
||||||
|
return ePersonService.countByGroups(context, groups);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group find(Context context, UUID id) throws SQLException {
|
public Group find(Context context, UUID id) throws SQLException {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
@@ -428,17 +460,17 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Group> search(Context context, String groupIdentifier) throws SQLException {
|
public List<Group> search(Context context, String query) throws SQLException {
|
||||||
return search(context, groupIdentifier, -1, -1);
|
return search(context, query, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Group> search(Context context, String groupIdentifier, int offset, int limit) throws SQLException {
|
public List<Group> search(Context context, String query, int offset, int limit) throws SQLException {
|
||||||
List<Group> groups = new ArrayList<>();
|
List<Group> groups = new ArrayList<>();
|
||||||
UUID uuid = UUIDUtils.fromString(groupIdentifier);
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
//Search by group name
|
//Search by group name
|
||||||
groups = groupDAO.findByNameLike(context, groupIdentifier, offset, limit);
|
groups = groupDAO.findByNameLike(context, query, offset, limit);
|
||||||
} else {
|
} else {
|
||||||
//Search by group id
|
//Search by group id
|
||||||
Group group = find(context, uuid);
|
Group group = find(context, uuid);
|
||||||
@@ -451,12 +483,12 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int searchResultCount(Context context, String groupIdentifier) throws SQLException {
|
public int searchResultCount(Context context, String query) throws SQLException {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
UUID uuid = UUIDUtils.fromString(groupIdentifier);
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
//Search by group name
|
//Search by group name
|
||||||
result = groupDAO.countByNameLike(context, groupIdentifier);
|
result = groupDAO.countByNameLike(context, query);
|
||||||
} else {
|
} else {
|
||||||
//Search by group id
|
//Search by group id
|
||||||
Group group = find(context, uuid);
|
Group group = find(context, uuid);
|
||||||
@@ -468,6 +500,44 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Group> searchNonMembers(Context context, String query, Group excludeParentGroup,
|
||||||
|
int offset, int limit) throws SQLException {
|
||||||
|
List<Group> groups = new ArrayList<>();
|
||||||
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
|
if (uuid == null) {
|
||||||
|
// Search by group name
|
||||||
|
groups = groupDAO.findByNameLikeAndNotMember(context, query, excludeParentGroup, offset, limit);
|
||||||
|
} else if (!uuid.equals(excludeParentGroup.getID())) {
|
||||||
|
// Search by group id
|
||||||
|
Group group = find(context, uuid);
|
||||||
|
// Verify it is NOT a member of the given excludeParentGroup before adding
|
||||||
|
if (group != null && !isMember(excludeParentGroup, group)) {
|
||||||
|
groups.add(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int searchNonMembersCount(Context context, String query, Group excludeParentGroup) throws SQLException {
|
||||||
|
int result = 0;
|
||||||
|
UUID uuid = UUIDUtils.fromString(query);
|
||||||
|
if (uuid == null) {
|
||||||
|
// Search by group name
|
||||||
|
result = groupDAO.countByNameLikeAndNotMember(context, query, excludeParentGroup);
|
||||||
|
} else if (!uuid.equals(excludeParentGroup.getID())) {
|
||||||
|
// Search by group id
|
||||||
|
Group group = find(context, uuid);
|
||||||
|
// Verify it is NOT a member of the given excludeParentGroup before adding
|
||||||
|
if (group != null && !isMember(excludeParentGroup, group)) {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Context context, Group group) throws SQLException {
|
public void delete(Context context, Group group) throws SQLException {
|
||||||
if (group.isPermanent()) {
|
if (group.isPermanent()) {
|
||||||
@@ -829,4 +899,20 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
|||||||
public String getName(Group dso) {
|
public String getName(Group dso) {
|
||||||
return dso.getName();
|
return dso.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException {
|
||||||
|
if (parent == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return groupDAO.findByParent(context, parent, pageSize, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countByParent(Context context, Group parent) throws SQLException {
|
||||||
|
if (parent == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return groupDAO.countByParent(context, parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,12 +33,91 @@ public interface EPersonDAO extends DSpaceObjectDAO<EPerson>, DSpaceObjectLegacy
|
|||||||
|
|
||||||
public EPerson findByNetid(Context context, String netid) throws SQLException;
|
public EPerson findByNetid(Context context, String netid) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search all EPersons by the given MetadataField objects, sorting by the given sort fields.
|
||||||
|
* <P>
|
||||||
|
* NOTE: As long as a query is specified, the EPerson's email address is included in the search alongside any given
|
||||||
|
* metadata fields.
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query the text to search EPersons for
|
||||||
|
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||||
|
* @param sortFields the metadata field(s) to sort the results by
|
||||||
|
* @param offset the position of the first result to return
|
||||||
|
* @param limit how many results return
|
||||||
|
* @return List of matching EPerson objects
|
||||||
|
* @throws SQLException if an error occurs
|
||||||
|
*/
|
||||||
public List<EPerson> search(Context context, String query, List<MetadataField> queryFields,
|
public List<EPerson> search(Context context, String query, List<MetadataField> queryFields,
|
||||||
List<MetadataField> sortFields, int offset, int limit) throws SQLException;
|
List<MetadataField> sortFields, int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count number of EPersons who match a search on the given metadata fields. This returns the count of total
|
||||||
|
* results for the same query using the 'search()', and therefore can be used to provide pagination.
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query the text to search EPersons for
|
||||||
|
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||||
|
* @return total number of EPersons who match the query
|
||||||
|
* @throws SQLException if an error occurs
|
||||||
|
*/
|
||||||
public int searchResultCount(Context context, String query, List<MetadataField> queryFields) throws SQLException;
|
public int searchResultCount(Context context, String query, List<MetadataField> queryFields) throws SQLException;
|
||||||
|
|
||||||
public List<EPerson> findByGroups(Context context, Set<Group> groups) throws SQLException;
|
/**
|
||||||
|
* Search all EPersons via their firstname, lastname, email (fuzzy match), limited to those EPersons which are NOT
|
||||||
|
* a member of the given group. This may be used to search across EPersons which are valid to add as members to the
|
||||||
|
* given group.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param query the text to search EPersons for
|
||||||
|
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||||
|
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||||
|
* @param offset the position of the first result to return
|
||||||
|
* @param limit how many results return
|
||||||
|
* @return EPersons matching the query (which are not members of the given group)
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
List<EPerson> searchNotMember(Context context, String query, List<MetadataField> queryFields, Group excludeGroup,
|
||||||
|
List<MetadataField> sortFields, int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count number of EPersons that match a given search (fuzzy match) across firstname, lastname and email. This
|
||||||
|
* search is limited to those EPersons which are NOT a member of the given group. This may be used
|
||||||
|
* (with searchNotMember()) to perform a paginated search across EPersons which are valid to add to the given group.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param query querystring to fuzzy match against.
|
||||||
|
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||||
|
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||||
|
* @return Groups matching the query (which are not members of the given parent)
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
int searchNotMemberCount(Context context, String query, List<MetadataField> queryFields, Group excludeGroup)
|
||||||
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all EPersons who are a member of one or more of the listed groups in a paginated fashion. This returns
|
||||||
|
* EPersons ordered by UUID.
|
||||||
|
*
|
||||||
|
* @param context current Context
|
||||||
|
* @param groups Set of group(s) to check membership in
|
||||||
|
* @param pageSize number of EPerson objects to load at one time. Set to <=0 to disable pagination
|
||||||
|
* @param offset number of page to load (starting with 1). Set to <=0 to disable pagination
|
||||||
|
* @return List of all EPersons who are a member of one or more groups.
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
List<EPerson> findByGroups(Context context, Set<Group> groups, int pageSize, int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count total number of EPersons who are a member of one or more of the listed groups. This provides the total
|
||||||
|
* number of results to expect from corresponding findByGroups() for pagination purposes.
|
||||||
|
*
|
||||||
|
* @param context current Context
|
||||||
|
* @param groups Set of group(s) to check membership in
|
||||||
|
* @return total number of (unique) EPersons who are a member of one or more groups.
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
int countByGroups(Context context, Set<Group> groups) throws SQLException;
|
||||||
|
|
||||||
public List<EPerson> findWithPasswordWithoutDigestAlgorithm(Context context) throws SQLException;
|
public List<EPerson> findWithPasswordWithoutDigestAlgorithm(Context context) throws SQLException;
|
||||||
|
|
||||||
|
@@ -135,6 +135,38 @@ public interface GroupDAO extends DSpaceObjectDAO<Group>, DSpaceObjectLegacySupp
|
|||||||
*/
|
*/
|
||||||
int countByNameLike(Context context, String groupName) throws SQLException;
|
int countByNameLike(Context context, String groupName) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search all groups via their name (fuzzy match), limited to those groups which are NOT a member of the given
|
||||||
|
* parent group. This may be used to search across groups which are valid to add to the given parent group.
|
||||||
|
* <P>
|
||||||
|
* NOTE: The parent group itself is also excluded from the search.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param groupName Group name to fuzzy match against.
|
||||||
|
* @param excludeParent Parent Group to exclude results from. Groups under this parent will never be returned.
|
||||||
|
* @param offset Offset to use for pagination (-1 to disable)
|
||||||
|
* @param limit The maximum number of results to return (-1 to disable)
|
||||||
|
* @return Groups matching the query (which are not members of the given parent)
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
List<Group> findByNameLikeAndNotMember(Context context, String groupName, Group excludeParent,
|
||||||
|
int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count number of groups that match a given name (fuzzy match), limited to those groups which are NOT a member of
|
||||||
|
* the given parent group. This may be used (with findByNameLikeAndNotMember()) to search across groups which are
|
||||||
|
* valid to add to the given parent group.
|
||||||
|
* <P>
|
||||||
|
* NOTE: The parent group itself is also excluded from the count.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param groupName Group name to fuzzy match against.
|
||||||
|
* @param excludeParent Parent Group to exclude results from. Groups under this parent will never be returned.
|
||||||
|
* @return Groups matching the query (which are not members of the given parent)
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
int countByNameLikeAndNotMember(Context context, String groupName, Group excludeParent) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a group by its name and the membership of the given EPerson
|
* Find a group by its name and the membership of the given EPerson
|
||||||
*
|
*
|
||||||
@@ -146,4 +178,28 @@ public interface GroupDAO extends DSpaceObjectDAO<Group>, DSpaceObjectLegacySupp
|
|||||||
*/
|
*/
|
||||||
Group findByIdAndMembership(Context context, UUID id, EPerson ePerson) throws SQLException;
|
Group findByIdAndMembership(Context context, UUID id, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all groups which are members of a given parent group.
|
||||||
|
* This provides the same behavior as group.getMemberGroups(), but in a paginated fashion.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param parent Parent Group to search within
|
||||||
|
* @param pageSize how many results return
|
||||||
|
* @param offset the position of the first result to return
|
||||||
|
* @return Groups matching the query
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of groups which are members of a given parent group.
|
||||||
|
* This provides the same behavior as group.getMemberGroups().size(), but with better performance for large groups.
|
||||||
|
* This method may be used with findByParent() to perform pagination.
|
||||||
|
*
|
||||||
|
* @param context The DSpace context
|
||||||
|
* @param parent Parent Group to search within
|
||||||
|
* @return Number of Groups matching the query
|
||||||
|
* @throws SQLException if database error
|
||||||
|
*/
|
||||||
|
int countByParent(Context context, Group parent) throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -70,17 +70,9 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
|||||||
String queryString = "SELECT " + EPerson.class.getSimpleName()
|
String queryString = "SELECT " + EPerson.class.getSimpleName()
|
||||||
.toLowerCase() + " FROM EPerson as " + EPerson.class
|
.toLowerCase() + " FROM EPerson as " + EPerson.class
|
||||||
.getSimpleName().toLowerCase() + " ";
|
.getSimpleName().toLowerCase() + " ";
|
||||||
if (query != null) {
|
|
||||||
query = "%" + query.toLowerCase() + "%";
|
|
||||||
}
|
|
||||||
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, sortFields, null);
|
|
||||||
|
|
||||||
if (0 <= offset) {
|
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, null,
|
||||||
hibernateQuery.setFirstResult(offset);
|
sortFields, null, limit, offset);
|
||||||
}
|
|
||||||
if (0 <= limit) {
|
|
||||||
hibernateQuery.setMaxResults(limit);
|
|
||||||
}
|
|
||||||
return list(hibernateQuery);
|
return list(hibernateQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +84,28 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
|||||||
return count(hibernateQuery);
|
return count(hibernateQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EPerson> searchNotMember(Context context, String query, List<MetadataField> queryFields,
|
||||||
|
Group excludeGroup, List<MetadataField> sortFields,
|
||||||
|
int offset, int limit) throws SQLException {
|
||||||
|
String queryString = "SELECT " + EPerson.class.getSimpleName()
|
||||||
|
.toLowerCase() + " FROM EPerson as " + EPerson.class
|
||||||
|
.getSimpleName().toLowerCase() + " ";
|
||||||
|
|
||||||
|
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, excludeGroup,
|
||||||
|
sortFields, null, limit, offset);
|
||||||
|
return list(hibernateQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int searchNotMemberCount(Context context, String query, List<MetadataField> queryFields,
|
||||||
|
Group excludeGroup) throws SQLException {
|
||||||
|
String queryString = "SELECT count(*) FROM EPerson as " + EPerson.class.getSimpleName().toLowerCase();
|
||||||
|
|
||||||
|
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, excludeGroup,
|
||||||
|
Collections.EMPTY_LIST, null, -1, -1);
|
||||||
|
return count(hibernateQuery);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EPerson> findAll(Context context, MetadataField metadataSortField, String sortField, int pageSize,
|
public List<EPerson> findAll(Context context, MetadataField metadataSortField, String sortField, int pageSize,
|
||||||
int offset) throws SQLException {
|
int offset) throws SQLException {
|
||||||
@@ -105,19 +119,43 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
|||||||
sortFields = Collections.singletonList(metadataSortField);
|
sortFields = Collections.singletonList(metadataSortField);
|
||||||
}
|
}
|
||||||
|
|
||||||
Query query = getSearchQuery(context, queryString, null, ListUtils.EMPTY_LIST, sortFields, sortField, pageSize,
|
Query query = getSearchQuery(context, queryString, null, ListUtils.EMPTY_LIST, null,
|
||||||
offset);
|
sortFields, sortField, pageSize, offset);
|
||||||
return list(query);
|
return list(query);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EPerson> findByGroups(Context context, Set<Group> groups) throws SQLException {
|
public List<EPerson> findByGroups(Context context, Set<Group> groups, int pageSize, int offset)
|
||||||
|
throws SQLException {
|
||||||
Query query = createQuery(context,
|
Query query = createQuery(context,
|
||||||
"SELECT DISTINCT e FROM EPerson e " +
|
"SELECT DISTINCT e FROM EPerson e " +
|
||||||
"JOIN e.groups g " +
|
"JOIN e.groups g " +
|
||||||
"WHERE g.id IN (:idList) ");
|
"WHERE g.id IN (:idList) ");
|
||||||
|
|
||||||
|
List<UUID> idList = new ArrayList<>(groups.size());
|
||||||
|
for (Group group : groups) {
|
||||||
|
idList.add(group.getID());
|
||||||
|
}
|
||||||
|
query.setParameter("idList", idList);
|
||||||
|
|
||||||
|
if (pageSize > 0) {
|
||||||
|
query.setMaxResults(pageSize);
|
||||||
|
}
|
||||||
|
if (offset > 0) {
|
||||||
|
query.setFirstResult(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countByGroups(Context context, Set<Group> groups) throws SQLException {
|
||||||
|
Query query = createQuery(context,
|
||||||
|
"SELECT count(DISTINCT e) FROM EPerson e " +
|
||||||
|
"JOIN e.groups g " +
|
||||||
|
"WHERE g.id IN (:idList) ");
|
||||||
|
|
||||||
List<UUID> idList = new ArrayList<>(groups.size());
|
List<UUID> idList = new ArrayList<>(groups.size());
|
||||||
for (Group group : groups) {
|
for (Group group : groups) {
|
||||||
idList.add(group.getID());
|
idList.add(group.getID());
|
||||||
@@ -125,7 +163,7 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
|||||||
|
|
||||||
query.setParameter("idList", idList);
|
query.setParameter("idList", idList);
|
||||||
|
|
||||||
return list(query);
|
return count(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -154,43 +192,88 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
|||||||
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
||||||
List<MetadataField> queryFields, List<MetadataField> sortFields, String sortField)
|
List<MetadataField> queryFields, List<MetadataField> sortFields, String sortField)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return getSearchQuery(context, queryString, queryParam, queryFields, sortFields, sortField, -1, -1);
|
return getSearchQuery(context, queryString, queryParam, queryFields, null, sortFields, sortField, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a search query across EPersons based on the given metadata fields and sorted based on the given metadata
|
||||||
|
* field(s) or database column.
|
||||||
|
* <P>
|
||||||
|
* NOTE: the EPerson's email address is included in the search alongside any given metadata fields.
|
||||||
|
*
|
||||||
|
* @param context DSpace Context
|
||||||
|
* @param queryString String which defines the beginning "SELECT" for the SQL query
|
||||||
|
* @param queryParam Actual text being searched for
|
||||||
|
* @param queryFields List of metadata fields to search within
|
||||||
|
* @param excludeGroup Optional Group which should be excluded from search. Any EPersons who are members
|
||||||
|
* of this group will not be included in the results.
|
||||||
|
* @param sortFields Optional List of metadata fields to sort by (should not be specified if sortField is used)
|
||||||
|
* @param sortField Optional database column to sort on (should not be specified if sortFields is used)
|
||||||
|
* @param pageSize how many results return
|
||||||
|
* @param offset the position of the first result to return
|
||||||
|
* @return built Query object
|
||||||
|
* @throws SQLException if error occurs
|
||||||
|
*/
|
||||||
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
||||||
List<MetadataField> queryFields, List<MetadataField> sortFields, String sortField,
|
List<MetadataField> queryFields, Group excludeGroup,
|
||||||
int pageSize, int offset) throws SQLException {
|
List<MetadataField> sortFields, String sortField,
|
||||||
|
int pageSize, int offset) throws SQLException {
|
||||||
|
// Initialize SQL statement using the passed in "queryString"
|
||||||
StringBuilder queryBuilder = new StringBuilder();
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
queryBuilder.append(queryString);
|
queryBuilder.append(queryString);
|
||||||
|
|
||||||
Set<MetadataField> metadataFieldsToJoin = new LinkedHashSet<>();
|
Set<MetadataField> metadataFieldsToJoin = new LinkedHashSet<>();
|
||||||
metadataFieldsToJoin.addAll(queryFields);
|
metadataFieldsToJoin.addAll(queryFields);
|
||||||
metadataFieldsToJoin.addAll(sortFields);
|
metadataFieldsToJoin.addAll(sortFields);
|
||||||
|
|
||||||
|
// Append necessary join information for MetadataFields we will search within
|
||||||
if (!CollectionUtils.isEmpty(metadataFieldsToJoin)) {
|
if (!CollectionUtils.isEmpty(metadataFieldsToJoin)) {
|
||||||
addMetadataLeftJoin(queryBuilder, EPerson.class.getSimpleName().toLowerCase(), metadataFieldsToJoin);
|
addMetadataLeftJoin(queryBuilder, EPerson.class.getSimpleName().toLowerCase(), metadataFieldsToJoin);
|
||||||
}
|
}
|
||||||
if (queryParam != null) {
|
// Always append a search on EPerson "email" based on query
|
||||||
|
if (StringUtils.isNotBlank(queryParam)) {
|
||||||
addMetadataValueWhereQuery(queryBuilder, queryFields, "like",
|
addMetadataValueWhereQuery(queryBuilder, queryFields, "like",
|
||||||
EPerson.class.getSimpleName().toLowerCase() + ".email like :queryParam");
|
EPerson.class.getSimpleName().toLowerCase() + ".email like :queryParam");
|
||||||
}
|
}
|
||||||
|
// If excludeGroup is specified, exclude members of that group from results
|
||||||
|
// This uses a subquery to find the excluded group & verify that it is not in the EPerson list of "groups"
|
||||||
|
if (excludeGroup != null) {
|
||||||
|
// If query params exist, then we already have a WHERE clause (see above) and just need to append an AND
|
||||||
|
if (StringUtils.isNotBlank(queryParam)) {
|
||||||
|
queryBuilder.append(" AND ");
|
||||||
|
} else {
|
||||||
|
// no WHERE clause yet, so this is the start of the WHERE
|
||||||
|
queryBuilder.append(" WHERE ");
|
||||||
|
}
|
||||||
|
queryBuilder.append("(FROM Group g where g.id = :group_id) NOT IN elements (")
|
||||||
|
.append(EPerson.class.getSimpleName().toLowerCase()).append(".groups)");
|
||||||
|
}
|
||||||
|
// Add sort/order by info to query, if specified
|
||||||
if (!CollectionUtils.isEmpty(sortFields) || StringUtils.isNotBlank(sortField)) {
|
if (!CollectionUtils.isEmpty(sortFields) || StringUtils.isNotBlank(sortField)) {
|
||||||
addMetadataSortQuery(queryBuilder, sortFields, Collections.singletonList(sortField));
|
addMetadataSortQuery(queryBuilder, sortFields, Collections.singletonList(sortField));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the final SQL SELECT statement (based on included params above)
|
||||||
Query query = createQuery(context, queryBuilder.toString());
|
Query query = createQuery(context, queryBuilder.toString());
|
||||||
|
// Set pagesize & offset for pagination
|
||||||
if (pageSize > 0) {
|
if (pageSize > 0) {
|
||||||
query.setMaxResults(pageSize);
|
query.setMaxResults(pageSize);
|
||||||
}
|
}
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
query.setFirstResult(offset);
|
query.setFirstResult(offset);
|
||||||
}
|
}
|
||||||
|
// Set all parameters to the SQL SELECT statement (based on included params above)
|
||||||
if (StringUtils.isNotBlank(queryParam)) {
|
if (StringUtils.isNotBlank(queryParam)) {
|
||||||
query.setParameter("queryParam", "%" + queryParam.toLowerCase() + "%");
|
query.setParameter("queryParam", "%" + queryParam.toLowerCase() + "%");
|
||||||
}
|
}
|
||||||
for (MetadataField metadataField : metadataFieldsToJoin) {
|
for (MetadataField metadataField : metadataFieldsToJoin) {
|
||||||
query.setParameter(metadataField.toString(), metadataField.getID());
|
query.setParameter(metadataField.toString(), metadataField.getID());
|
||||||
}
|
}
|
||||||
|
if (excludeGroup != null) {
|
||||||
|
query.setParameter("group_id", excludeGroup.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
@@ -164,6 +164,41 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
|
|||||||
return count(query);
|
return count(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Group> findByNameLikeAndNotMember(Context context, String groupName, Group excludeParent,
|
||||||
|
int offset, int limit) throws SQLException {
|
||||||
|
Query query = createQuery(context,
|
||||||
|
"FROM Group " +
|
||||||
|
"WHERE lower(name) LIKE lower(:group_name) " +
|
||||||
|
"AND id != :parent_id " +
|
||||||
|
"AND (from Group g where g.id = :parent_id) not in elements (parentGroups)");
|
||||||
|
query.setParameter("parent_id", excludeParent.getID());
|
||||||
|
query.setParameter("group_name", "%" + StringUtils.trimToEmpty(groupName) + "%");
|
||||||
|
|
||||||
|
if (0 <= offset) {
|
||||||
|
query.setFirstResult(offset);
|
||||||
|
}
|
||||||
|
if (0 <= limit) {
|
||||||
|
query.setMaxResults(limit);
|
||||||
|
}
|
||||||
|
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||||
|
|
||||||
|
return list(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countByNameLikeAndNotMember(Context context, String groupName, Group excludeParent) throws SQLException {
|
||||||
|
Query query = createQuery(context,
|
||||||
|
"SELECT count(*) FROM Group " +
|
||||||
|
"WHERE lower(name) LIKE lower(:group_name) " +
|
||||||
|
"AND id != :parent_id " +
|
||||||
|
"AND (from Group g where g.id = :parent_id) not in elements (parentGroups)");
|
||||||
|
query.setParameter("parent_id", excludeParent.getID());
|
||||||
|
query.setParameter("group_name", "%" + StringUtils.trimToEmpty(groupName) + "%");
|
||||||
|
|
||||||
|
return count(query);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(Context context, Group group) throws SQLException {
|
public void delete(Context context, Group group) throws SQLException {
|
||||||
Query query = getHibernateSession(context)
|
Query query = getHibernateSession(context)
|
||||||
@@ -196,4 +231,29 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
|
|||||||
return count(createQuery(context, "SELECT count(*) FROM Group"));
|
return count(createQuery(context, "SELECT count(*) FROM Group"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException {
|
||||||
|
Query query = createQuery(context,
|
||||||
|
"SELECT g FROM Group g JOIN g.parentGroups pg " +
|
||||||
|
"WHERE pg.id = :parent_id");
|
||||||
|
query.setParameter("parent_id", parent.getID());
|
||||||
|
if (pageSize > 0) {
|
||||||
|
query.setMaxResults(pageSize);
|
||||||
|
}
|
||||||
|
if (offset > 0) {
|
||||||
|
query.setFirstResult(offset);
|
||||||
|
}
|
||||||
|
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||||
|
|
||||||
|
return list(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countByParent(Context context, Group parent) throws SQLException {
|
||||||
|
Query query = createQuery(context, "SELECT count(g) FROM Group g JOIN g.parentGroups pg " +
|
||||||
|
"WHERE pg.id = :parent_id");
|
||||||
|
query.setParameter("parent_id", parent.getID());
|
||||||
|
|
||||||
|
return count(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -98,9 +98,9 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
|||||||
*
|
*
|
||||||
* @param context The relevant DSpace Context.
|
* @param context The relevant DSpace Context.
|
||||||
* @param query The search string
|
* @param query The search string
|
||||||
* @param offset Inclusive offset
|
* @param offset Inclusive offset (the position of the first result to return)
|
||||||
* @param limit Maximum number of matches returned
|
* @param limit Maximum number of matches returned
|
||||||
* @return array of EPerson objects
|
* @return List of matching EPerson objects
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<EPerson> search(Context context, String query, int offset, int limit)
|
public List<EPerson> search(Context context, String query, int offset, int limit)
|
||||||
@@ -118,6 +118,34 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
|||||||
public int searchResultCount(Context context, String query)
|
public int searchResultCount(Context context, String query)
|
||||||
throws SQLException;
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the EPersons that match the search query which are NOT currently members of the given Group. The search
|
||||||
|
* query is run against firstname, lastname or email.
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query The search string
|
||||||
|
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||||
|
* @param offset Inclusive offset (the position of the first result to return)
|
||||||
|
* @param limit Maximum number of matches returned
|
||||||
|
* @return List of matching EPerson objects
|
||||||
|
* @throws SQLException if error
|
||||||
|
*/
|
||||||
|
List<EPerson> searchNonMembers(Context context, String query, Group excludeGroup,
|
||||||
|
int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of EPersons that match the search query which are NOT currently members of the given
|
||||||
|
* Group. The search query is run against firstname, lastname or email. Can be used with searchNonMembers() to
|
||||||
|
* support pagination
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query The search string
|
||||||
|
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||||
|
* @return List of matching EPerson objects
|
||||||
|
* @throws SQLException if error
|
||||||
|
*/
|
||||||
|
int searchNonMembersCount(Context context, String query, Group excludeGroup) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all the {@code EPerson}s in a specific order by field.
|
* Find all the {@code EPerson}s in a specific order by field.
|
||||||
* The sortable fields are:
|
* The sortable fields are:
|
||||||
@@ -252,14 +280,42 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
|||||||
public List<String> getDeleteConstraints(Context context, EPerson ePerson) throws SQLException;
|
public List<String> getDeleteConstraints(Context context, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all accounts which belong to at least one of the specified groups.
|
* Retrieve all EPerson accounts which belong to at least one of the specified groups.
|
||||||
|
* <P>
|
||||||
|
* WARNING: This method may have bad performance issues for Groups with a very large number of members,
|
||||||
|
* as it will load all member EPerson objects into memory.
|
||||||
|
* <P>
|
||||||
|
* For better performance, use the paginated version of this method.
|
||||||
*
|
*
|
||||||
* @param c The relevant DSpace Context.
|
* @param c The relevant DSpace Context.
|
||||||
* @param groups set of eperson groups
|
* @param groups set of eperson groups
|
||||||
* @return a list of epeople
|
* @return a list of epeople
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException;
|
List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all EPerson accounts which belong to at least one of the specified groups, in a paginated fashion.
|
||||||
|
*
|
||||||
|
* @param c The relevant DSpace Context.
|
||||||
|
* @param groups Set of group(s) to check membership in
|
||||||
|
* @param pageSize number of EPerson objects to load at one time. Set to <=0 to disable pagination
|
||||||
|
* @param offset number of page to load (starting with 1). Set to <=0 to disable pagination
|
||||||
|
* @return a list of epeople
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
List<EPerson> findByGroups(Context c, Set<Group> groups, int pageSize, int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all EPerson accounts which belong to at least one of the specified groups. This provides the total
|
||||||
|
* number of results to expect from corresponding findByGroups() for pagination purposes.
|
||||||
|
*
|
||||||
|
* @param c The relevant DSpace Context.
|
||||||
|
* @param groups Set of group(s) to check membership in
|
||||||
|
* @return total number of (unique) EPersons who are a member of one or more groups.
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
int countByGroups(Context c, Set<Group> groups) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all accounts which are subscribed to receive information about new items.
|
* Retrieve all accounts which are subscribed to receive information about new items.
|
||||||
|
@@ -189,9 +189,11 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
|||||||
Set<Group> allMemberGroupsSet(Context context, EPerson ePerson) throws SQLException;
|
Set<Group> allMemberGroupsSet(Context context, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all of the epeople who are a member of the
|
* Get all of the EPerson objects who are a member of the specified group, or a member of a subgroup of the
|
||||||
* specified group, or a member of a sub-group of the
|
|
||||||
* specified group, etc.
|
* specified group, etc.
|
||||||
|
* <P>
|
||||||
|
* WARNING: This method may have bad performance for Groups with a very large number of members, as it will load
|
||||||
|
* all member EPerson objects into memory. Only use if you need access to *every* EPerson object at once.
|
||||||
*
|
*
|
||||||
* @param context The relevant DSpace Context.
|
* @param context The relevant DSpace Context.
|
||||||
* @param group Group object
|
* @param group Group object
|
||||||
@@ -200,6 +202,18 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
|||||||
*/
|
*/
|
||||||
public List<EPerson> allMembers(Context context, Group group) throws SQLException;
|
public List<EPerson> allMembers(Context context, Group group) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all of the EPerson objects who are a member of the specified group, or a member of a subgroup of the
|
||||||
|
* specified group, etc.
|
||||||
|
* In other words, this will return the size of "allMembers()" without having to load all EPerson objects into
|
||||||
|
* memory.
|
||||||
|
* @param context current DSpace context
|
||||||
|
* @param group Group object
|
||||||
|
* @return count of EPerson object members
|
||||||
|
* @throws SQLException if error
|
||||||
|
*/
|
||||||
|
int countAllMembers(Context context, Group group) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the group by its name - assumes name is unique
|
* Find the group by its name - assumes name is unique
|
||||||
*
|
*
|
||||||
@@ -247,37 +261,67 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
|||||||
public List<Group> findAll(Context context, int sortField) throws SQLException;
|
public List<Group> findAll(Context context, int sortField) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the groups that match the search query across eperson_group_id or name
|
* Find the Groups that match the query across both Group name and Group ID. This is an unpaginated search,
|
||||||
|
* which means it will load all matching groups into memory at once. This may provide POOR PERFORMANCE when a large
|
||||||
|
* number of groups are matched.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param groupIdentifier The group name or group ID
|
* @param query The search string used to search across group name or group ID
|
||||||
* @return array of Group objects
|
* @return List of matching Group objects
|
||||||
* @throws SQLException if error
|
* @throws SQLException if error
|
||||||
*/
|
*/
|
||||||
public List<Group> search(Context context, String groupIdentifier) throws SQLException;
|
List<Group> search(Context context, String query) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the groups that match the search query across eperson_group_id or name
|
* Find the Groups that match the query across both Group name and Group ID. This method supports pagination,
|
||||||
|
* which provides better performance than the above non-paginated search() method.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param groupIdentifier The group name or group ID
|
* @param query The search string used to search across group name or group ID
|
||||||
* @param offset Inclusive offset
|
* @param offset Inclusive offset (the position of the first result to return)
|
||||||
* @param limit Maximum number of matches returned
|
* @param limit Maximum number of matches returned
|
||||||
* @return array of Group objects
|
* @return List of matching Group objects
|
||||||
* @throws SQLException if error
|
* @throws SQLException if error
|
||||||
*/
|
*/
|
||||||
public List<Group> search(Context context, String groupIdentifier, int offset, int limit) throws SQLException;
|
List<Group> search(Context context, String query, int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of groups returned by a specific query, without the overhead
|
* Returns the total number of Groups returned by a specific query. Search is performed based on Group name
|
||||||
* of creating the Group objects to store the results.
|
* and Group ID. May be used with search() above to support pagination of matching Groups.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param query The search string
|
* @param query The search string used to search across group name or group ID
|
||||||
* @return the number of groups matching the query
|
* @return the number of groups matching the query
|
||||||
* @throws SQLException if error
|
* @throws SQLException if error
|
||||||
*/
|
*/
|
||||||
public int searchResultCount(Context context, String query) throws SQLException;
|
int searchResultCount(Context context, String query) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the groups that match the search query which are NOT currently members (subgroups)
|
||||||
|
* of the given parentGroup
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query The search string used to search across group name or group ID
|
||||||
|
* @param excludeParentGroup Parent group to exclude results from
|
||||||
|
* @param offset Inclusive offset (the position of the first result to return)
|
||||||
|
* @param limit Maximum number of matches returned
|
||||||
|
* @return List of matching Group objects
|
||||||
|
* @throws SQLException if error
|
||||||
|
*/
|
||||||
|
List<Group> searchNonMembers(Context context, String query, Group excludeParentGroup,
|
||||||
|
int offset, int limit) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of groups that match the search query which are NOT currently members (subgroups)
|
||||||
|
* of the given parentGroup. Can be used with searchNonMembers() to support pagination.
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param query The search string used to search across group name or group ID
|
||||||
|
* @param excludeParentGroup Parent group to exclude results from
|
||||||
|
* @return the number of Groups matching the query
|
||||||
|
* @throws SQLException if error
|
||||||
|
*/
|
||||||
|
int searchNonMembersCount(Context context, String query, Group excludeParentGroup) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if group has no direct or indirect members
|
* Return true if group has no direct or indirect members
|
||||||
@@ -327,4 +371,29 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
|||||||
*/
|
*/
|
||||||
List<Group> findByMetadataField(Context context, String searchValue, MetadataField metadataField)
|
List<Group> findByMetadataField(Context context, String searchValue, MetadataField metadataField)
|
||||||
throws SQLException;
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all groups which are a member of the given Parent group
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace Context.
|
||||||
|
* @param parent The parent Group to search on
|
||||||
|
* @param pageSize how many results return
|
||||||
|
* @param offset the position of the first result to return
|
||||||
|
* @return List of all groups which are members of the parent group
|
||||||
|
* @throws SQLException database exception if error
|
||||||
|
*/
|
||||||
|
List<Group> findByParent(Context context, Group parent, int pageSize, int offset)
|
||||||
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return number of groups which are a member of the given Parent group.
|
||||||
|
* Can be used with findByParent() for pagination of all groups within a given Parent group.
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace Context.
|
||||||
|
* @param parent The parent Group to search on
|
||||||
|
* @return number of groups which are members of the parent group
|
||||||
|
* @throws SQLException database exception if error
|
||||||
|
*/
|
||||||
|
int countByParent(Context context, Group parent)
|
||||||
|
throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.consumer;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.IndexingService;
|
||||||
|
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||||
|
import org.dspace.event.Consumer;
|
||||||
|
import org.dspace.event.Event;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumer implementation to be used for Item Submission Configuration
|
||||||
|
*
|
||||||
|
* @author paulo.graca at fccn.pt
|
||||||
|
*/
|
||||||
|
public class SubmissionConfigConsumer implements Consumer {
|
||||||
|
/**
|
||||||
|
* log4j logger
|
||||||
|
*/
|
||||||
|
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionConfigConsumer.class);
|
||||||
|
|
||||||
|
IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
|
.getServiceByName(IndexingService.class.getName(),
|
||||||
|
IndexingService.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() throws Exception {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consume(Context ctx, Event event) throws Exception {
|
||||||
|
int st = event.getSubjectType();
|
||||||
|
int et = event.getEventType();
|
||||||
|
|
||||||
|
|
||||||
|
if ( st == Constants.COLLECTION ) {
|
||||||
|
switch (et) {
|
||||||
|
case Event.MODIFY_METADATA:
|
||||||
|
// Submission configuration it's based on solr
|
||||||
|
// for collection's entity type but, at this point
|
||||||
|
// that info isn't indexed yet, we need to force it
|
||||||
|
DSpaceObject subject = event.getSubject(ctx);
|
||||||
|
Collection collectionFromDSOSubject = (Collection) subject;
|
||||||
|
indexer.indexContent(ctx, new IndexableCollection (collectionFromDSOSubject), true, false, false);
|
||||||
|
indexer.commit();
|
||||||
|
|
||||||
|
log.debug("SubmissionConfigConsumer occured: " + event.toString());
|
||||||
|
// reload submission configurations
|
||||||
|
SubmissionServiceFactory.getInstance().getSubmissionConfigService().reload();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.debug("SubmissionConfigConsumer occured: " + event.toString());
|
||||||
|
// reload submission configurations
|
||||||
|
SubmissionServiceFactory.getInstance().getSubmissionConfigService().reload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void end(Context ctx) throws Exception {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish(Context ctx) throws Exception {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.factory;
|
||||||
|
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract factory to get services for submission, use SubmissionServiceFactory.getInstance() to retrieve an
|
||||||
|
* implementation
|
||||||
|
*
|
||||||
|
* @author paulo.graca at fccn.pt
|
||||||
|
*/
|
||||||
|
public abstract class SubmissionServiceFactory {
|
||||||
|
|
||||||
|
public abstract SubmissionConfigService getSubmissionConfigService() throws SubmissionConfigReaderException;
|
||||||
|
|
||||||
|
public static SubmissionServiceFactory getInstance() {
|
||||||
|
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
|
.getServiceByName("submissionServiceFactory", SubmissionServiceFactory.class);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.factory;
|
||||||
|
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory implementation to get services for submission, use SubmissionServiceFactory.getInstance() to
|
||||||
|
* retrieve an implementation
|
||||||
|
*
|
||||||
|
* @author paulo.graca at fccn.pt
|
||||||
|
*/
|
||||||
|
public class SubmissionServiceFactoryImpl extends SubmissionServiceFactory {
|
||||||
|
@Autowired(required = true)
|
||||||
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubmissionConfigService getSubmissionConfigService() throws SubmissionConfigReaderException {
|
||||||
|
return submissionConfigService;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.service;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item Submission Configuration Service
|
||||||
|
* enables interaction with a submission config like
|
||||||
|
* getting a config by a collection name or handle
|
||||||
|
* as also retrieving submission configuration steps
|
||||||
|
*
|
||||||
|
* @author paulo.graca at fccn.pt
|
||||||
|
*/
|
||||||
|
public interface SubmissionConfigService {
|
||||||
|
|
||||||
|
public void reload() throws SubmissionConfigReaderException;
|
||||||
|
|
||||||
|
public String getDefaultSubmissionConfigName();
|
||||||
|
|
||||||
|
public List<SubmissionConfig> getAllSubmissionConfigs(Integer limit, Integer offset);
|
||||||
|
|
||||||
|
public int countSubmissionConfigs();
|
||||||
|
|
||||||
|
public SubmissionConfig getSubmissionConfigByCollection(String collectionHandle);
|
||||||
|
|
||||||
|
public SubmissionConfig getSubmissionConfigByName(String submitName);
|
||||||
|
|
||||||
|
public SubmissionStepConfig getStepConfig(String stepID)
|
||||||
|
throws SubmissionConfigReaderException;
|
||||||
|
|
||||||
|
public List<Collection> getCollectionsBySubmissionConfig(Context context, String submitName)
|
||||||
|
throws IllegalStateException, SQLException, SubmissionConfigReaderException;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* 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.submit.service;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
|
import org.dspace.app.util.SubmissionConfigReader;
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation for Submission Config service
|
||||||
|
*
|
||||||
|
* @author paulo.graca at fccn.pt
|
||||||
|
*/
|
||||||
|
public class SubmissionConfigServiceImpl implements SubmissionConfigService, InitializingBean {
|
||||||
|
|
||||||
|
protected SubmissionConfigReader submissionConfigReader;
|
||||||
|
|
||||||
|
public SubmissionConfigServiceImpl () throws SubmissionConfigReaderException {
|
||||||
|
submissionConfigReader = new SubmissionConfigReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
submissionConfigReader.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() throws SubmissionConfigReaderException {
|
||||||
|
submissionConfigReader.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultSubmissionConfigName() {
|
||||||
|
return submissionConfigReader.getDefaultSubmissionConfigName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SubmissionConfig> getAllSubmissionConfigs(Integer limit, Integer offset) {
|
||||||
|
return submissionConfigReader.getAllSubmissionConfigs(limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countSubmissionConfigs() {
|
||||||
|
return submissionConfigReader.countSubmissionConfigs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubmissionConfig getSubmissionConfigByCollection(String collectionHandle) {
|
||||||
|
return submissionConfigReader.getSubmissionConfigByCollection(collectionHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubmissionConfig getSubmissionConfigByName(String submitName) {
|
||||||
|
return submissionConfigReader.getSubmissionConfigByName(submitName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubmissionStepConfig getStepConfig(String stepID) throws SubmissionConfigReaderException {
|
||||||
|
return submissionConfigReader.getStepConfig(stepID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Collection> getCollectionsBySubmissionConfig(Context context, String submitName)
|
||||||
|
throws IllegalStateException, SQLException {
|
||||||
|
return submissionConfigReader.getCollectionsBySubmissionConfig(context, submitName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -35,6 +35,8 @@ public class SolrUtils {
|
|||||||
* @return date formatter compatible with Solr.
|
* @return date formatter compatible with Solr.
|
||||||
*/
|
*/
|
||||||
public static DateFormat getDateFormatter() {
|
public static DateFormat getDateFormatter() {
|
||||||
return new SimpleDateFormat(SolrUtils.SOLR_DATE_FORMAT);
|
DateFormat formatter = new SimpleDateFormat(SolrUtils.SOLR_DATE_FORMAT);
|
||||||
|
formatter.setTimeZone(SOLR_TIME_ZONE);
|
||||||
|
return formatter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,34 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Unset any primary bitstream that is marked as deleted
|
||||||
|
UPDATE bundle
|
||||||
|
SET primary_bitstream_id = NULL
|
||||||
|
WHERE primary_bitstream_id IN
|
||||||
|
( SELECT bs.uuid
|
||||||
|
FROM bitstream AS bs
|
||||||
|
INNER JOIN bundle as bl ON bs.uuid = bl.primary_bitstream_id
|
||||||
|
WHERE bs.deleted IS TRUE );
|
||||||
|
|
||||||
|
-- Unset any primary bitstream that don't belong to bundle's bitstream list
|
||||||
|
UPDATE bundle
|
||||||
|
SET primary_bitstream_id = NULL
|
||||||
|
WHERE primary_bitstream_id IN
|
||||||
|
( SELECT bl.primary_bitstream_id
|
||||||
|
FROM bundle as bl
|
||||||
|
WHERE bl.primary_bitstream_id IS NOT NULL
|
||||||
|
AND bl.primary_bitstream_id NOT IN
|
||||||
|
( SELECT bitstream_id
|
||||||
|
FROM bundle2bitstream AS b2b
|
||||||
|
WHERE b2b.bundle_id = bl.uuid
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
@@ -14,6 +14,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.AbstractUnitTest;
|
import org.dspace.AbstractUnitTest;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -65,7 +66,8 @@ public class SubmissionConfigTest extends AbstractUnitTest {
|
|||||||
|
|
||||||
// Get submission configuration
|
// Get submission configuration
|
||||||
SubmissionConfig submissionConfig =
|
SubmissionConfig submissionConfig =
|
||||||
new SubmissionConfigReader().getSubmissionConfigByCollection(typeBindHandle);
|
SubmissionServiceFactory.getInstance().getSubmissionConfigService()
|
||||||
|
.getSubmissionConfigByCollection(typeBindHandle);
|
||||||
// Submission name should match name defined in item-submission.xml
|
// Submission name should match name defined in item-submission.xml
|
||||||
assertEquals(typeBindSubmissionName, submissionConfig.getSubmissionName());
|
assertEquals(typeBindSubmissionName, submissionConfig.getSubmissionName());
|
||||||
// Step 0 - our process only has one step. It should not be null and have the ID typebindtest
|
// Step 0 - our process only has one step. It should not be null and have the ID typebindtest
|
||||||
|
@@ -16,6 +16,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.dspace.alerts.service.SystemWideAlertService;
|
import org.dspace.alerts.service.SystemWideAlertService;
|
||||||
import org.dspace.app.requestitem.factory.RequestItemServiceFactory;
|
import org.dspace.app.requestitem.factory.RequestItemServiceFactory;
|
||||||
import org.dspace.app.requestitem.service.RequestItemService;
|
import org.dspace.app.requestitem.service.RequestItemService;
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
@@ -52,6 +53,8 @@ import org.dspace.qaevent.service.QAEventService;
|
|||||||
import org.dspace.scripts.factory.ScriptServiceFactory;
|
import org.dspace.scripts.factory.ScriptServiceFactory;
|
||||||
import org.dspace.scripts.service.ProcessService;
|
import org.dspace.scripts.service.ProcessService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.dspace.supervision.factory.SupervisionOrderServiceFactory;
|
import org.dspace.supervision.factory.SupervisionOrderServiceFactory;
|
||||||
import org.dspace.supervision.service.SupervisionOrderService;
|
import org.dspace.supervision.service.SupervisionOrderService;
|
||||||
import org.dspace.utils.DSpace;
|
import org.dspace.utils.DSpace;
|
||||||
@@ -109,6 +112,7 @@ public abstract class AbstractBuilder<T, S> {
|
|||||||
static OrcidQueueService orcidQueueService;
|
static OrcidQueueService orcidQueueService;
|
||||||
static OrcidTokenService orcidTokenService;
|
static OrcidTokenService orcidTokenService;
|
||||||
static SystemWideAlertService systemWideAlertService;
|
static SystemWideAlertService systemWideAlertService;
|
||||||
|
static SubmissionConfigService submissionConfigService;
|
||||||
static SubscribeService subscribeService;
|
static SubscribeService subscribeService;
|
||||||
static SupervisionOrderService supervisionOrderService;
|
static SupervisionOrderService supervisionOrderService;
|
||||||
static QAEventService qaEventService;
|
static QAEventService qaEventService;
|
||||||
@@ -173,6 +177,11 @@ public abstract class AbstractBuilder<T, S> {
|
|||||||
orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService();
|
orcidTokenService = OrcidServiceFactory.getInstance().getOrcidTokenService();
|
||||||
systemWideAlertService = DSpaceServicesFactory.getInstance().getServiceManager()
|
systemWideAlertService = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||||
.getServicesByType(SystemWideAlertService.class).get(0);
|
.getServicesByType(SystemWideAlertService.class).get(0);
|
||||||
|
try {
|
||||||
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
|
} catch (SubmissionConfigReaderException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
subscribeService = ContentServiceFactory.getInstance().getSubscribeService();
|
subscribeService = ContentServiceFactory.getInstance().getSubscribeService();
|
||||||
supervisionOrderService = SupervisionOrderServiceFactory.getInstance().getSupervisionOrderService();
|
supervisionOrderService = SupervisionOrderServiceFactory.getInstance().getSupervisionOrderService();
|
||||||
qaEventService = new DSpace().getSingletonService(QAEventService.class);
|
qaEventService = new DSpace().getSingletonService(QAEventService.class);
|
||||||
@@ -210,6 +219,7 @@ public abstract class AbstractBuilder<T, S> {
|
|||||||
versioningService = null;
|
versioningService = null;
|
||||||
orcidTokenService = null;
|
orcidTokenService = null;
|
||||||
systemWideAlertService = null;
|
systemWideAlertService = null;
|
||||||
|
submissionConfigService = null;
|
||||||
subscribeService = null;
|
subscribeService = null;
|
||||||
supervisionOrderService = null;
|
supervisionOrderService = null;
|
||||||
qaEventService = null;
|
qaEventService = null;
|
||||||
|
@@ -432,6 +432,51 @@ public class BitstreamTest extends AbstractDSpaceObjectTest {
|
|||||||
assertThat("testExpunge 0", bitstreamService.find(context, bitstreamId), nullValue());
|
assertThat("testExpunge 0", bitstreamService.find(context, bitstreamId), nullValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of delete method, of class Bitstream.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDeleteBitstreamAndUnsetPrimaryBitstreamID()
|
||||||
|
throws IOException, SQLException, AuthorizeException {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community owningCommunity = communityService.create(null, context);
|
||||||
|
Collection collection = collectionService.create(context, owningCommunity);
|
||||||
|
WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false);
|
||||||
|
Item item = installItemService.installItem(context, workspaceItem);
|
||||||
|
Bundle b = bundleService.create(context, item, "TESTBUNDLE");
|
||||||
|
|
||||||
|
// Allow Bundle REMOVE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy).authorizeAction(context, b, Constants.REMOVE);
|
||||||
|
// Allow Bitstream WRITE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy)
|
||||||
|
.authorizeAction(any(Context.class), any(Bitstream.class), eq(Constants.WRITE));
|
||||||
|
// Allow Bitstream DELETE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy)
|
||||||
|
.authorizeAction(any(Context.class), any(Bitstream.class), eq(Constants.DELETE));
|
||||||
|
|
||||||
|
//set a value different than default
|
||||||
|
File f = new File(testProps.get("test.bitstream").toString());
|
||||||
|
|
||||||
|
// Create a new bitstream, which we can delete.
|
||||||
|
Bitstream delBS = bitstreamService.create(context, new FileInputStream(f));
|
||||||
|
bundleService.addBitstream(context, b, delBS);
|
||||||
|
// set primary bitstream
|
||||||
|
b.setPrimaryBitstreamID(delBS);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
// Test that delete will flag the bitstream as deleted
|
||||||
|
assertFalse("testDeleteBitstreamAndUnsetPrimaryBitstreamID 0", delBS.isDeleted());
|
||||||
|
assertThat("testDeleteBitstreamAndUnsetPrimaryBitstreamID 1", b.getPrimaryBitstream(), equalTo(delBS));
|
||||||
|
// Delete bitstream
|
||||||
|
bitstreamService.delete(context, delBS);
|
||||||
|
assertTrue("testDeleteBitstreamAndUnsetPrimaryBitstreamID 2", delBS.isDeleted());
|
||||||
|
|
||||||
|
// Now test if the primary bitstream was unset from bundle
|
||||||
|
assertThat("testDeleteBitstreamAndUnsetPrimaryBitstreamID 3", b.getPrimaryBitstream(), equalTo(null));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of retrieve method, of class Bitstream.
|
* Test of retrieve method, of class Bitstream.
|
||||||
*/
|
*/
|
||||||
|
@@ -513,6 +513,41 @@ public class BundleTest extends AbstractDSpaceObjectTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test removeBitstream method and also the unsetPrimaryBitstreamID method, of class Bundle.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveBitstreamAuthAndUnsetPrimaryBitstreamID()
|
||||||
|
throws IOException, SQLException, AuthorizeException {
|
||||||
|
// Allow Item WRITE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy).authorizeAction(context, item, Constants.WRITE);
|
||||||
|
// Allow Bundle ADD permissions
|
||||||
|
doNothing().when(authorizeServiceSpy).authorizeAction(context, b, Constants.ADD);
|
||||||
|
// Allow Bundle REMOVE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy).authorizeAction(context, b, Constants.REMOVE);
|
||||||
|
// Allow Bitstream WRITE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy)
|
||||||
|
.authorizeAction(any(Context.class), any(Bitstream.class), eq(Constants.WRITE));
|
||||||
|
// Allow Bitstream DELETE permissions
|
||||||
|
doNothing().when(authorizeServiceSpy)
|
||||||
|
.authorizeAction(any(Context.class), any(Bitstream.class), eq(Constants.DELETE));
|
||||||
|
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
//set a value different than default
|
||||||
|
File f = new File(testProps.get("test.bitstream").toString());
|
||||||
|
Bitstream bs = bitstreamService.create(context, new FileInputStream(f));
|
||||||
|
bundleService.addBitstream(context, b, bs);
|
||||||
|
b.setPrimaryBitstreamID(bs);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
assertThat("testRemoveBitstreamAuthAndUnsetPrimaryBitstreamID 0", b.getPrimaryBitstream(), equalTo(bs));
|
||||||
|
//remove bitstream
|
||||||
|
bundleService.removeBitstream(context, b, bs);
|
||||||
|
//is -1 when not set
|
||||||
|
assertThat("testRemoveBitstreamAuthAndUnsetPrimaryBitstreamID 1", b.getPrimaryBitstream(), equalTo(null));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of update method, of class Bundle.
|
* Test of update method, of class Bundle.
|
||||||
*/
|
*/
|
||||||
|
47
dspace-api/src/test/java/org/dspace/core/ContextIT.java
Normal file
47
dspace-api/src/test/java/org/dspace/core/ContextIT.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 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.core;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.authorize.ResourcePolicy;
|
||||||
|
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ContextIT extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPoliciesNewCommunityAfterReadOnlyModeChange() throws Exception {
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
// First disable the index consumer. The indexing process calls the authorizeService
|
||||||
|
// function used in this test and may affect the test
|
||||||
|
context.setDispatcher("noindex");
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
context.setMode(Context.Mode.READ_ONLY);
|
||||||
|
|
||||||
|
List<ResourcePolicy> policies = authorizeService.getPoliciesActionFilter(context, parentCommunity,
|
||||||
|
Constants.READ);
|
||||||
|
|
||||||
|
assertEquals("Should return the default anonymous group read policy", 1, policies.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -8,17 +8,23 @@
|
|||||||
package org.dspace.eperson;
|
package org.dspace.eperson;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
|
|
||||||
import org.apache.commons.codec.DecoderException;
|
import org.apache.commons.codec.DecoderException;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.AbstractUnitTest;
|
import org.dspace.AbstractUnitTest;
|
||||||
@@ -274,63 +280,184 @@ public class EPersonTest extends AbstractUnitTest {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of search method, of class EPerson.
|
* Test of search() and searchResultCount() methods of EPersonService
|
||||||
|
* NOTE: Pagination is not verified here because it is tested in EPersonRestRepositoryIT
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearch_Context_String()
|
public void testSearchAndCountByNameEmail() throws SQLException, AuthorizeException, IOException {
|
||||||
throws Exception
|
List<EPerson> allEPeopleAdded = new ArrayList<>();
|
||||||
{
|
Group testGroup = createGroup("TestingGroup");
|
||||||
System.out.println("search");
|
try {
|
||||||
Context context = null;
|
// Create 4 EPersons. Add a few to a test group to verify group membership doesn't matter
|
||||||
String query = "";
|
EPerson eperson1 = createEPersonAndAddToGroup("eperson1@example.com", "Jane", "Doe", testGroup);
|
||||||
EPerson[] expResult = null;
|
EPerson eperson2 = createEPerson("eperson2@example.com", "John", "Doe");
|
||||||
EPerson[] result = EPerson.search(context, query);
|
EPerson eperson3 = createEPersonAndAddToGroup("eperson3@example.com", "John", "Smith", testGroup);
|
||||||
assertEquals(expResult, result);
|
EPerson eperson4 = createEPerson("eperson4@example.com", "Doe", "Smith");
|
||||||
// TODO review the generated test code and remove the default call to fail.
|
allEPeopleAdded.addAll(Arrays.asList(eperson1, eperson2, eperson3, eperson4));
|
||||||
fail("The test case is a prototype.");
|
|
||||||
|
List<EPerson> allJohns = Arrays.asList(eperson2, eperson3);
|
||||||
|
List<EPerson> searchJohnResults = ePersonService.search(context, "John", -1, -1);
|
||||||
|
assertTrue(searchJohnResults.containsAll(allJohns));
|
||||||
|
assertEquals(searchJohnResults.size(), ePersonService.searchResultCount(context, "John"));
|
||||||
|
|
||||||
|
List<EPerson> allDoes = Arrays.asList(eperson1, eperson2, eperson4);
|
||||||
|
List<EPerson> searchDoeResults = ePersonService.search(context, "Doe", -1, -1);
|
||||||
|
assertTrue(searchDoeResults.containsAll(allDoes));
|
||||||
|
assertEquals(searchDoeResults.size(), ePersonService.searchResultCount(context, "Doe"));
|
||||||
|
|
||||||
|
List<EPerson> allSmiths = Arrays.asList(eperson3, eperson4);
|
||||||
|
List<EPerson> searchSmithResults = ePersonService.search(context, "Smith", -1, -1);
|
||||||
|
assertTrue(searchSmithResults.containsAll(allSmiths));
|
||||||
|
assertEquals(searchSmithResults.size(), ePersonService.searchResultCount(context, "Smith"));
|
||||||
|
|
||||||
|
// Assert search on example.com returns everyone
|
||||||
|
List<EPerson> searchEmailResults = ePersonService.search(context, "example.com", -1, -1);
|
||||||
|
assertTrue(searchEmailResults.containsAll(allEPeopleAdded));
|
||||||
|
assertEquals(searchEmailResults.size(), ePersonService.searchResultCount(context, "example.com"));
|
||||||
|
|
||||||
|
// Assert exact email search returns just one
|
||||||
|
List<EPerson> exactEmailResults = ePersonService.search(context, "eperson1@example.com", -1, -1);
|
||||||
|
assertTrue(exactEmailResults.contains(eperson1));
|
||||||
|
assertEquals(exactEmailResults.size(), ePersonService.searchResultCount(context, "eperson1@example.com"));
|
||||||
|
|
||||||
|
// Assert UUID search returns exact match
|
||||||
|
List<EPerson> uuidResults = ePersonService.search(context, eperson4.getID().toString(), -1, -1);
|
||||||
|
assertTrue(uuidResults.contains(eperson4));
|
||||||
|
assertEquals(1, uuidResults.size());
|
||||||
|
assertEquals(uuidResults.size(), ePersonService.searchResultCount(context, eperson4.getID().toString()));
|
||||||
|
} finally {
|
||||||
|
// Remove all Groups & EPersons we added for this test
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
groupService.delete(context, testGroup);
|
||||||
|
for (EPerson ePerson : allEPeopleAdded) {
|
||||||
|
ePersonService.delete(context, ePerson);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of search method, of class EPerson.
|
* Test of searchNonMembers() and searchNonMembersCount() methods of EPersonService
|
||||||
|
* NOTE: Pagination is not verified here because it is tested in EPersonRestRepositoryIT
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearch_4args()
|
public void testSearchAndCountByNameEmailNonMembers() throws SQLException, AuthorizeException, IOException {
|
||||||
throws Exception
|
List<EPerson> allEPeopleAdded = new ArrayList<>();
|
||||||
{
|
Group testGroup1 = createGroup("TestingGroup1");
|
||||||
System.out.println("search");
|
Group testGroup2 = createGroup("TestingGroup2");
|
||||||
Context context = null;
|
Group testGroup3 = createGroup("TestingGroup3");
|
||||||
String query = "";
|
try {
|
||||||
int offset = 0;
|
// Create two EPersons in Group 1
|
||||||
int limit = 0;
|
EPerson eperson1 = createEPersonAndAddToGroup("eperson1@example.com", "Jane", "Doe", testGroup1);
|
||||||
EPerson[] expResult = null;
|
EPerson eperson2 = createEPersonAndAddToGroup("eperson2@example.com", "John", "Smith", testGroup1);
|
||||||
EPerson[] result = EPerson.search(context, query, offset, limit);
|
|
||||||
assertEquals(expResult, result);
|
|
||||||
// TODO review the generated test code and remove the default call to fail.
|
|
||||||
fail("The test case is a prototype.");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
// Create one more EPerson, and add it and a previous EPerson to Group 2
|
||||||
* Test of searchResultCount method, of class EPerson.
|
EPerson eperson3 = createEPersonAndAddToGroup("eperson3@example.com", "John", "Doe", testGroup2);
|
||||||
*/
|
context.turnOffAuthorisationSystem();
|
||||||
/*
|
groupService.addMember(context, testGroup2, eperson2);
|
||||||
@Test
|
groupService.update(context, testGroup2);
|
||||||
public void testSearchResultCount()
|
ePersonService.update(context, eperson2);
|
||||||
throws Exception
|
context.restoreAuthSystemState();
|
||||||
{
|
|
||||||
System.out.println("searchResultCount");
|
// Create 2 more EPersons with no group memberships
|
||||||
Context context = null;
|
EPerson eperson4 = createEPerson("eperson4@example.com", "John", "Anthony");
|
||||||
String query = "";
|
EPerson eperson5 = createEPerson("eperson5@example.org", "Smith", "Doe");
|
||||||
int expResult = 0;
|
allEPeopleAdded.addAll(Arrays.asList(eperson1, eperson2, eperson3, eperson4, eperson5));
|
||||||
int result = EPerson.searchResultCount(context, query);
|
|
||||||
assertEquals(expResult, result);
|
// FIRST, test search by last name
|
||||||
// TODO review the generated test code and remove the default call to fail.
|
// Verify all Does match a nonMember search of Group3 (which is an empty group)
|
||||||
fail("The test case is a prototype.");
|
List<EPerson> allDoes = Arrays.asList(eperson1, eperson3, eperson5);
|
||||||
|
List<EPerson> searchDoeResults = ePersonService.searchNonMembers(context, "Doe", testGroup3, -1, -1);
|
||||||
|
assertTrue(searchDoeResults.containsAll(allDoes));
|
||||||
|
assertEquals(searchDoeResults.size(), ePersonService.searchNonMembersCount(context, "Doe", testGroup3));
|
||||||
|
|
||||||
|
// Verify searching "Doe" with Group 2 *excludes* the one which is already a member
|
||||||
|
List<EPerson> allNonMemberDoes = Arrays.asList(eperson1, eperson5);
|
||||||
|
List<EPerson> searchNonMemberDoeResults = ePersonService.searchNonMembers(context, "Doe", testGroup2,
|
||||||
|
-1, -1);
|
||||||
|
assertTrue(searchNonMemberDoeResults.containsAll(allNonMemberDoes));
|
||||||
|
assertFalse(searchNonMemberDoeResults.contains(eperson3));
|
||||||
|
assertEquals(searchNonMemberDoeResults.size(), ePersonService.searchNonMembersCount(context, "Doe",
|
||||||
|
testGroup2));
|
||||||
|
|
||||||
|
// Verify searching "Doe" with Group 1 *excludes* the one which is already a member
|
||||||
|
allNonMemberDoes = Arrays.asList(eperson3, eperson5);
|
||||||
|
searchNonMemberDoeResults = ePersonService.searchNonMembers(context, "Doe", testGroup1, -1, -1);
|
||||||
|
assertTrue(searchNonMemberDoeResults.containsAll(allNonMemberDoes));
|
||||||
|
assertFalse(searchNonMemberDoeResults.contains(eperson1));
|
||||||
|
assertEquals(searchNonMemberDoeResults.size(), ePersonService.searchNonMembersCount(context, "Doe",
|
||||||
|
testGroup1));
|
||||||
|
|
||||||
|
// SECOND, test search by first name
|
||||||
|
// Verify all Johns match a nonMember search of Group3 (which is an empty group)
|
||||||
|
List<EPerson> allJohns = Arrays.asList(eperson2, eperson3, eperson4);
|
||||||
|
List<EPerson> searchJohnResults = ePersonService.searchNonMembers(context, "John",
|
||||||
|
testGroup3, -1, -1);
|
||||||
|
assertTrue(searchJohnResults.containsAll(allJohns));
|
||||||
|
assertEquals(searchJohnResults.size(), ePersonService.searchNonMembersCount(context, "John",
|
||||||
|
testGroup3));
|
||||||
|
|
||||||
|
// Verify searching "John" with Group 2 *excludes* the two who are already a member
|
||||||
|
List<EPerson> allNonMemberJohns = Arrays.asList(eperson4);
|
||||||
|
List<EPerson> searchNonMemberJohnResults = ePersonService.searchNonMembers(context, "John",
|
||||||
|
testGroup2, -1, -1);
|
||||||
|
assertTrue(searchNonMemberJohnResults.containsAll(allNonMemberJohns));
|
||||||
|
assertFalse(searchNonMemberJohnResults.contains(eperson2));
|
||||||
|
assertFalse(searchNonMemberJohnResults.contains(eperson3));
|
||||||
|
assertEquals(searchNonMemberJohnResults.size(), ePersonService.searchNonMembersCount(context, "John",
|
||||||
|
testGroup2));
|
||||||
|
|
||||||
|
// FINALLY, test search by email
|
||||||
|
// Assert search on example.com excluding Group 1 returns just those not in that group
|
||||||
|
List<EPerson> exampleNonMembers = Arrays.asList(eperson3, eperson4);
|
||||||
|
List<EPerson> searchEmailResults = ePersonService.searchNonMembers(context, "example.com",
|
||||||
|
testGroup1, -1, -1);
|
||||||
|
assertTrue(searchEmailResults.containsAll(exampleNonMembers));
|
||||||
|
assertFalse(searchEmailResults.contains(eperson1));
|
||||||
|
assertFalse(searchEmailResults.contains(eperson2));
|
||||||
|
assertEquals(searchEmailResults.size(), ePersonService.searchNonMembersCount(context, "example.com",
|
||||||
|
testGroup1));
|
||||||
|
|
||||||
|
// Assert exact email search returns just one (if not in group)
|
||||||
|
List<EPerson> exactEmailResults = ePersonService.searchNonMembers(context, "eperson1@example.com",
|
||||||
|
testGroup2, -1, -1);
|
||||||
|
assertTrue(exactEmailResults.contains(eperson1));
|
||||||
|
assertEquals(exactEmailResults.size(), ePersonService.searchNonMembersCount(context, "eperson1@example.com",
|
||||||
|
testGroup2));
|
||||||
|
// But, change the group to one they are a member of, and they won't be included
|
||||||
|
exactEmailResults = ePersonService.searchNonMembers(context, "eperson1@example.com",
|
||||||
|
testGroup1, -1, -1);
|
||||||
|
assertFalse(exactEmailResults.contains(eperson1));
|
||||||
|
assertEquals(exactEmailResults.size(), ePersonService.searchNonMembersCount(context, "eperson1@example.com",
|
||||||
|
testGroup1));
|
||||||
|
|
||||||
|
// Assert UUID search returns exact match (if not in group)
|
||||||
|
List<EPerson> uuidResults = ePersonService.searchNonMembers(context, eperson3.getID().toString(),
|
||||||
|
testGroup1, -1, -1);
|
||||||
|
assertTrue(uuidResults.contains(eperson3));
|
||||||
|
assertEquals(1, uuidResults.size());
|
||||||
|
assertEquals(uuidResults.size(), ePersonService.searchNonMembersCount(context, eperson3.getID().toString(),
|
||||||
|
testGroup1));
|
||||||
|
// But, change the group to one they are a member of, and you'll get no results
|
||||||
|
uuidResults = ePersonService.searchNonMembers(context, eperson3.getID().toString(),
|
||||||
|
testGroup2, -1, -1);
|
||||||
|
assertFalse(uuidResults.contains(eperson3));
|
||||||
|
assertEquals(0, uuidResults.size());
|
||||||
|
assertEquals(uuidResults.size(), ePersonService.searchNonMembersCount(context, eperson3.getID().toString(),
|
||||||
|
testGroup2));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
// Remove all Groups & EPersons we added for this test
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
groupService.delete(context, testGroup1);
|
||||||
|
groupService.delete(context, testGroup2);
|
||||||
|
groupService.delete(context, testGroup3);
|
||||||
|
for (EPerson ePerson : allEPeopleAdded) {
|
||||||
|
ePersonService.delete(context, ePerson);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of findAll method, of class EPerson.
|
* Test of findAll method, of class EPerson.
|
||||||
@@ -1029,6 +1156,57 @@ public class EPersonTest extends AbstractUnitTest {
|
|||||||
wfi.getSubmitter());
|
wfi.getSubmitter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findAndCountByGroups() throws SQLException, AuthorizeException, IOException {
|
||||||
|
// Create a group with 3 EPerson members
|
||||||
|
Group group = createGroup("parentGroup");
|
||||||
|
EPerson eperson1 = createEPersonAndAddToGroup("test1@example.com", group);
|
||||||
|
EPerson eperson2 = createEPersonAndAddToGroup("test2@example.com", group);
|
||||||
|
EPerson eperson3 = createEPersonAndAddToGroup("test3@example.com", group);
|
||||||
|
groupService.update(context, group);
|
||||||
|
|
||||||
|
Group group2 = null;
|
||||||
|
EPerson eperson4 = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Assert that findByGroup is the same list of EPersons as getMembers() when pagination is ignored
|
||||||
|
// (NOTE: Pagination is tested in GroupRestRepositoryIT)
|
||||||
|
// NOTE: isEqualCollection() must be used for comparison because Hibernate's "PersistentBag" cannot be
|
||||||
|
// compared directly to a List. See https://stackoverflow.com/a/57399383/3750035
|
||||||
|
assertTrue(
|
||||||
|
CollectionUtils.isEqualCollection(group.getMembers(),
|
||||||
|
ePersonService.findByGroups(context, Set.of(group), -1, -1)));
|
||||||
|
// Assert countByGroups is the same as the size of members
|
||||||
|
assertEquals(group.getMembers().size(), ePersonService.countByGroups(context, Set.of(group)));
|
||||||
|
|
||||||
|
// Add another group with duplicate EPerson
|
||||||
|
group2 = createGroup("anotherGroup");
|
||||||
|
groupService.addMember(context, group2, eperson1);
|
||||||
|
groupService.update(context, group2);
|
||||||
|
|
||||||
|
// Verify countByGroups is still 3 (existing person should not be counted twice)
|
||||||
|
assertEquals(3, ePersonService.countByGroups(context, Set.of(group, group2)));
|
||||||
|
|
||||||
|
// Add a new EPerson to new group, verify count goes up by one
|
||||||
|
eperson4 = createEPersonAndAddToGroup("test4@example.com", group2);
|
||||||
|
assertEquals(4, ePersonService.countByGroups(context, Set.of(group, group2)));
|
||||||
|
} finally {
|
||||||
|
// Clean up our data
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
groupService.delete(context, group);
|
||||||
|
if (group2 != null) {
|
||||||
|
groupService.delete(context, group2);
|
||||||
|
}
|
||||||
|
ePersonService.delete(context, eperson1);
|
||||||
|
ePersonService.delete(context, eperson2);
|
||||||
|
ePersonService.delete(context, eperson3);
|
||||||
|
if (eperson4 != null) {
|
||||||
|
ePersonService.delete(context, eperson4);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an item, sets the specified submitter.
|
* Creates an item, sets the specified submitter.
|
||||||
*
|
*
|
||||||
@@ -1075,4 +1253,54 @@ public class EPersonTest extends AbstractUnitTest {
|
|||||||
context.restoreAuthSystemState();
|
context.restoreAuthSystemState();
|
||||||
return wsi;
|
return wsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Group createGroup(String name) throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Group group = groupService.create(context);
|
||||||
|
group.setName(name);
|
||||||
|
groupService.update(context, group);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EPerson createEPersonAndAddToGroup(String email, Group group) throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
EPerson ePerson = createEPerson(email);
|
||||||
|
groupService.addMember(context, group, ePerson);
|
||||||
|
groupService.update(context, group);
|
||||||
|
ePersonService.update(context, ePerson);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
return ePerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EPerson createEPersonAndAddToGroup(String email, String firstname, String lastname, Group group)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
EPerson ePerson = createEPerson(email, firstname, lastname);
|
||||||
|
groupService.addMember(context, group, ePerson);
|
||||||
|
groupService.update(context, group);
|
||||||
|
ePersonService.update(context, ePerson);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
return ePerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EPerson createEPerson(String email) throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
EPerson ePerson = ePersonService.create(context);
|
||||||
|
ePerson.setEmail(email);
|
||||||
|
ePersonService.update(context, ePerson);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
return ePerson;
|
||||||
|
}
|
||||||
|
protected EPerson createEPerson(String email, String firstname, String lastname)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
EPerson ePerson = ePersonService.create(context);
|
||||||
|
ePerson.setEmail(email);
|
||||||
|
ePerson.setFirstName(context, firstname);
|
||||||
|
ePerson.setLastName(context, lastname);
|
||||||
|
ePersonService.update(context, ePerson);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
return ePerson;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.eperson;
|
|||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@@ -21,6 +22,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.AbstractUnitTest;
|
import org.dspace.AbstractUnitTest;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -604,6 +606,30 @@ public class GroupTest extends AbstractUnitTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void countAllMembers() throws SQLException, AuthorizeException, EPersonDeletionException, IOException {
|
||||||
|
List<EPerson> allEPeopleAdded = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
allEPeopleAdded.add(createEPersonAndAddToGroup("allMemberGroups1@dspace.org", topGroup));
|
||||||
|
allEPeopleAdded.add(createEPersonAndAddToGroup("allMemberGroups2@dspace.org", level1Group));
|
||||||
|
allEPeopleAdded.add(createEPersonAndAddToGroup("allMemberGroups3@dspace.org", level2Group));
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
assertEquals(3, groupService.countAllMembers(context, topGroup));
|
||||||
|
assertEquals(2, groupService.countAllMembers(context, level1Group));
|
||||||
|
assertEquals(1, groupService.countAllMembers(context, level2Group));
|
||||||
|
} finally {
|
||||||
|
// Remove all the people added (in order to not impact other tests)
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
for (EPerson ePerson : allEPeopleAdded) {
|
||||||
|
ePersonService.delete(context, ePerson);
|
||||||
|
}
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isEmpty() throws SQLException, AuthorizeException, EPersonDeletionException, IOException {
|
public void isEmpty() throws SQLException, AuthorizeException, EPersonDeletionException, IOException {
|
||||||
assertTrue(groupService.isEmpty(topGroup));
|
assertTrue(groupService.isEmpty(topGroup));
|
||||||
@@ -620,6 +646,143 @@ public class GroupTest extends AbstractUnitTest {
|
|||||||
assertTrue(groupService.isEmpty(level2Group));
|
assertTrue(groupService.isEmpty(level2Group));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findAndCountByParent() throws SQLException, AuthorizeException, IOException {
|
||||||
|
|
||||||
|
// Create a parent group with 3 child groups
|
||||||
|
Group parentGroup = createGroup("parentGroup");
|
||||||
|
Group childGroup = createGroup("childGroup");
|
||||||
|
Group child2Group = createGroup("child2Group");
|
||||||
|
Group child3Group = createGroup("child3Group");
|
||||||
|
groupService.addMember(context, parentGroup, childGroup);
|
||||||
|
groupService.addMember(context, parentGroup, child2Group);
|
||||||
|
groupService.addMember(context, parentGroup, child3Group);
|
||||||
|
groupService.update(context, parentGroup);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Assert that findByParent is the same list of groups as getMemberGroups() when pagination is ignored
|
||||||
|
// (NOTE: Pagination is tested in GroupRestRepositoryIT)
|
||||||
|
// NOTE: isEqualCollection() must be used for comparison because Hibernate's "PersistentBag" cannot be
|
||||||
|
// compared directly to a List. See https://stackoverflow.com/a/57399383/3750035
|
||||||
|
assertTrue(
|
||||||
|
CollectionUtils.isEqualCollection(parentGroup.getMemberGroups(),
|
||||||
|
groupService.findByParent(context, parentGroup, -1, -1)));
|
||||||
|
// Assert countBy parent is the same as the size of group members
|
||||||
|
assertEquals(parentGroup.getMemberGroups().size(), groupService.countByParent(context, parentGroup));
|
||||||
|
} finally {
|
||||||
|
// Clean up our data
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
groupService.delete(context, parentGroup);
|
||||||
|
groupService.delete(context, childGroup);
|
||||||
|
groupService.delete(context, child2Group);
|
||||||
|
groupService.delete(context, child3Group);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// Tests searchNonMembers() and searchNonMembersCount()
|
||||||
|
// NOTE: This does not test pagination as that is tested in GroupRestRepositoryIT in server-webapp
|
||||||
|
public void searchAndCountNonMembers() throws SQLException, AuthorizeException, IOException {
|
||||||
|
// Create a parent group with 2 child groups
|
||||||
|
Group parentGroup = createGroup("Some Parent Group");
|
||||||
|
Group someStaffGroup = createGroup("Some Other Staff");
|
||||||
|
Group someStudentsGroup = createGroup("Some Students");
|
||||||
|
groupService.addMember(context, parentGroup, someStaffGroup);
|
||||||
|
groupService.addMember(context, parentGroup, someStudentsGroup);
|
||||||
|
groupService.update(context, parentGroup);
|
||||||
|
|
||||||
|
// Create a separate parent which is not a member of the first & add two child groups to it
|
||||||
|
Group studentsNotInParentGroup = createGroup("Students not in Parent");
|
||||||
|
Group otherStudentsNotInParentGroup = createGroup("Other Students");
|
||||||
|
Group someOtherStudentsNotInParentGroup = createGroup("Some Other Students");
|
||||||
|
groupService.addMember(context, studentsNotInParentGroup, otherStudentsNotInParentGroup);
|
||||||
|
groupService.addMember(context, studentsNotInParentGroup, someOtherStudentsNotInParentGroup);
|
||||||
|
groupService.update(context, studentsNotInParentGroup);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Assert that all Groups *not* in parent group match an empty search
|
||||||
|
List<Group> notInParent = Arrays.asList(studentsNotInParentGroup, otherStudentsNotInParentGroup,
|
||||||
|
someOtherStudentsNotInParentGroup);
|
||||||
|
List<Group> nonMembersSearch = groupService.searchNonMembers(context, "", parentGroup, -1, -1);
|
||||||
|
// NOTE: Because others unit tests create groups, this search will return an undetermined number of results.
|
||||||
|
// Therefore, we just verify that our expected groups are included and others are NOT included.
|
||||||
|
assertTrue(nonMembersSearch.containsAll(notInParent));
|
||||||
|
// Verify it does NOT contain members of parentGroup
|
||||||
|
assertFalse(nonMembersSearch.contains(someStaffGroup));
|
||||||
|
assertFalse(nonMembersSearch.contains(someStudentsGroup));
|
||||||
|
// Verify it also does NOT contain the parentGroup itself
|
||||||
|
assertFalse(nonMembersSearch.contains(parentGroup));
|
||||||
|
// Verify the count for empty search matches the size of the search results
|
||||||
|
assertEquals(nonMembersSearch.size(), groupService.searchNonMembersCount(context, "", parentGroup));
|
||||||
|
|
||||||
|
// Assert a search on "Students" matches all those same groups (as they all include that word in their name)
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context, "Students", parentGroup, -1, -1);
|
||||||
|
assertTrue(nonMembersSearch.containsAll(notInParent));
|
||||||
|
//Verify an existing member group with "Students" in its name does NOT get returned
|
||||||
|
assertFalse(nonMembersSearch.contains(someStudentsGroup));
|
||||||
|
assertEquals(nonMembersSearch.size(),
|
||||||
|
groupService.searchNonMembersCount(context, "Students", parentGroup));
|
||||||
|
|
||||||
|
|
||||||
|
// Assert a search on "other" matches just two groups
|
||||||
|
// (this also tests search is case insensitive)
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context, "other", parentGroup, -1, -1);
|
||||||
|
assertTrue(nonMembersSearch.containsAll(
|
||||||
|
Arrays.asList(otherStudentsNotInParentGroup, someOtherStudentsNotInParentGroup)));
|
||||||
|
// Verify an existing member group with "Other" in its name does NOT get returned
|
||||||
|
assertFalse(nonMembersSearch.contains(someStaffGroup));
|
||||||
|
assertEquals(nonMembersSearch.size(), groupService.searchNonMembersCount(context, "other", parentGroup));
|
||||||
|
|
||||||
|
// Assert a search on "Parent" matches just one group
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context, "Parent", parentGroup, -1, -1);
|
||||||
|
assertTrue(nonMembersSearch.contains(studentsNotInParentGroup));
|
||||||
|
// Verify Parent Group itself does NOT get returned
|
||||||
|
assertFalse(nonMembersSearch.contains(parentGroup));
|
||||||
|
assertEquals(nonMembersSearch.size(), groupService.searchNonMembersCount(context, "Parent", parentGroup));
|
||||||
|
|
||||||
|
// Assert a UUID search matching a non-member group will return just that one group
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context,
|
||||||
|
someOtherStudentsNotInParentGroup.getID().toString(),
|
||||||
|
parentGroup, -1, -1);
|
||||||
|
assertEquals(1, nonMembersSearch.size());
|
||||||
|
assertTrue(nonMembersSearch.contains(someOtherStudentsNotInParentGroup));
|
||||||
|
assertEquals(nonMembersSearch.size(),
|
||||||
|
groupService.searchNonMembersCount(context,
|
||||||
|
someOtherStudentsNotInParentGroup.getID().toString(),
|
||||||
|
parentGroup));
|
||||||
|
|
||||||
|
// Assert a UUID search matching an EXISTING member will return NOTHING
|
||||||
|
// (as this group is excluded from the search)
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context, someStudentsGroup.getID().toString(),
|
||||||
|
parentGroup,-1, -1);
|
||||||
|
assertEquals(0, nonMembersSearch.size());
|
||||||
|
assertEquals(nonMembersSearch.size(),
|
||||||
|
groupService.searchNonMembersCount(context, someStudentsGroup.getID().toString(),
|
||||||
|
parentGroup));
|
||||||
|
|
||||||
|
// Assert a UUID search matching Parent Group *itself* will return NOTHING
|
||||||
|
// (as this group is excluded from the search)
|
||||||
|
nonMembersSearch = groupService.searchNonMembers(context, parentGroup.getID().toString(),
|
||||||
|
parentGroup,-1, -1);
|
||||||
|
assertEquals(0, nonMembersSearch.size());
|
||||||
|
assertEquals(nonMembersSearch.size(),
|
||||||
|
groupService.searchNonMembersCount(context, parentGroup.getID().toString(),
|
||||||
|
parentGroup));
|
||||||
|
} finally {
|
||||||
|
// Clean up our data
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
groupService.delete(context, parentGroup);
|
||||||
|
groupService.delete(context, someStaffGroup);
|
||||||
|
groupService.delete(context, someStudentsGroup);
|
||||||
|
groupService.delete(context, studentsNotInParentGroup);
|
||||||
|
groupService.delete(context, otherStudentsNotInParentGroup);
|
||||||
|
groupService.delete(context, someOtherStudentsNotInParentGroup);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Group createGroup(String name) throws SQLException, AuthorizeException {
|
protected Group createGroup(String name) throws SQLException, AuthorizeException {
|
||||||
context.turnOffAuthorisationSystem();
|
context.turnOffAuthorisationSystem();
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<!-- This is the path to the root [dspace-src] directory. -->
|
<!-- This is the path to the root [dspace-src] directory. -->
|
||||||
<root.basedir>${basedir}/..</root.basedir>
|
<root.basedir>${basedir}/..</root.basedir>
|
||||||
<xoai.version>3.3.0</xoai.version>
|
<xoai.version>3.4.0</xoai.version>
|
||||||
<jtwig.version>5.87.0.RELEASE</jtwig.version>
|
<jtwig.version>5.87.0.RELEASE</jtwig.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -55,41 +55,10 @@
|
|||||||
<artifactId>xoai</artifactId>
|
<artifactId>xoai</artifactId>
|
||||||
<version>${xoai.version}</version>
|
<version>${xoai.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
|
<!-- Use version provided by SolrJ -->
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.hamcrest</groupId>
|
<groupId>com.fasterxml.woodstox</groupId>
|
||||||
<artifactId>hamcrest-all</artifactId>
|
<artifactId>woodstox-core</artifactId>
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<!--Hard pinned below.-->
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-all</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<!-- Later version provided by SolrJ -->
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.codehaus.woodstox</groupId>
|
|
||||||
<artifactId>wstx-asl</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<!-- Later version provided by Hibernate -->
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.dom4j</groupId>
|
|
||||||
<artifactId>dom4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<!-- We don't use this test framework & it causes dependency convergence issues -->
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.lyncode</groupId>
|
|
||||||
<artifactId>test-support</artifactId>
|
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@@ -12,7 +12,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import javax.xml.transform.Source;
|
import javax.xml.transform.Source;
|
||||||
import javax.xml.transform.Transformer;
|
import javax.xml.transform.Templates;
|
||||||
import javax.xml.transform.TransformerConfigurationException;
|
import javax.xml.transform.TransformerConfigurationException;
|
||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.stream.StreamSource;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
@@ -40,8 +40,7 @@ public class DSpaceResourceResolver implements ResourceResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transformer getTransformer(String path) throws IOException,
|
public Templates getTemplates(String path) throws IOException, TransformerConfigurationException {
|
||||||
TransformerConfigurationException {
|
|
||||||
// construct a Source that reads from an InputStream
|
// construct a Source that reads from an InputStream
|
||||||
Source mySrc = new StreamSource(getResource(path));
|
Source mySrc = new StreamSource(getResource(path));
|
||||||
// specify a system ID (the path to the XSLT-file on the filesystem)
|
// specify a system ID (the path to the XSLT-file on the filesystem)
|
||||||
@@ -49,6 +48,6 @@ public class DSpaceResourceResolver implements ResourceResolver {
|
|||||||
// XSLT-files (like <xsl:import href="utils.xsl"/>)
|
// XSLT-files (like <xsl:import href="utils.xsl"/>)
|
||||||
String systemId = basePath + "/" + path;
|
String systemId = basePath + "/" + path;
|
||||||
mySrc.setSystemId(systemId);
|
mySrc.setSystemId(systemId);
|
||||||
return transformerFactory.newTransformer(mySrc);
|
return transformerFactory.newTemplates(mySrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,8 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.dspace.app.util.factory.UtilServiceFactory;
|
import org.dspace.app.util.factory.UtilServiceFactory;
|
||||||
import org.dspace.app.util.service.MetadataExposureService;
|
import org.dspace.app.util.service.MetadataExposureService;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.content.Bitstream;
|
import org.dspace.content.Bitstream;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
@@ -59,6 +61,10 @@ public class ItemUtils {
|
|||||||
|
|
||||||
private static final ConfigurationService configurationService
|
private static final ConfigurationService configurationService
|
||||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
private static final AuthorizeService authorizeService
|
||||||
|
= AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
*/
|
*/
|
||||||
@@ -163,13 +169,17 @@ public class ItemUtils {
|
|||||||
List<Bitstream> licBits = licBundle.getBitstreams();
|
List<Bitstream> licBits = licBundle.getBitstreams();
|
||||||
if (!licBits.isEmpty()) {
|
if (!licBits.isEmpty()) {
|
||||||
Bitstream licBit = licBits.get(0);
|
Bitstream licBit = licBits.get(0);
|
||||||
InputStream in;
|
if (authorizeService.authorizeActionBoolean(context, licBit, Constants.READ)) {
|
||||||
|
InputStream in;
|
||||||
in = bitstreamService.retrieve(context, licBit);
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
Utils.bufferedCopy(in, out);
|
|
||||||
license.getField().add(createValue("bin", Base64Utils.encode(out.toString())));
|
|
||||||
|
|
||||||
|
in = bitstreamService.retrieve(context, licBit);
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
Utils.bufferedCopy(in, out);
|
||||||
|
license.getField().add(createValue("bin", Base64Utils.encode(out.toString())));
|
||||||
|
} else {
|
||||||
|
log.info("Missing READ rights for license bitstream. Did not include license bitstream for item: "
|
||||||
|
+ item.getID() + ".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return license;
|
return license;
|
||||||
|
@@ -29,7 +29,7 @@ public class PipelineTest {
|
|||||||
InputStream input = PipelineTest.class.getClassLoader().getResourceAsStream("item.xml");
|
InputStream input = PipelineTest.class.getClassLoader().getResourceAsStream("item.xml");
|
||||||
InputStream xslt = PipelineTest.class.getClassLoader().getResourceAsStream("oai_dc.xsl");
|
InputStream xslt = PipelineTest.class.getClassLoader().getResourceAsStream("oai_dc.xsl");
|
||||||
String output = FileUtils.readAllText(new XSLPipeline(input, true)
|
String output = FileUtils.readAllText(new XSLPipeline(input, true)
|
||||||
.apply(factory.newTransformer(new StreamSource(xslt)))
|
.apply(factory.newTemplates(new StreamSource(xslt)))
|
||||||
.getTransformed());
|
.getTransformed());
|
||||||
|
|
||||||
assertThat(output, oai_dc().withXPath("/oai_dc:dc/dc:title", equalTo("Teste")));
|
assertThat(output, oai_dc().withXPath("/oai_dc:dc/dc:title", equalTo("Teste")));
|
||||||
|
@@ -19,13 +19,14 @@ import org.dspace.app.rest.projection.Projection;
|
|||||||
import org.dspace.app.rest.submit.DataProcessingStep;
|
import org.dspace.app.rest.submit.DataProcessingStep;
|
||||||
import org.dspace.app.rest.submit.RestProcessingStep;
|
import org.dspace.app.rest.submit.RestProcessingStep;
|
||||||
import org.dspace.app.rest.submit.SubmissionService;
|
import org.dspace.app.rest.submit.SubmissionService;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.app.util.SubmissionStepConfig;
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.content.InProgressSubmission;
|
import org.dspace.content.InProgressSubmission;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
@@ -53,13 +54,13 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission,
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SubmissionSectionConverter submissionSectionConverter;
|
private SubmissionSectionConverter submissionSectionConverter;
|
||||||
|
|
||||||
protected SubmissionConfigReader submissionConfigReader;
|
protected SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
SubmissionService submissionService;
|
SubmissionService submissionService;
|
||||||
|
|
||||||
public AInprogressItemConverter() throws SubmissionConfigReaderException {
|
public AInprogressItemConverter() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fillFromModel(T obj, R witem, Projection projection) {
|
protected void fillFromModel(T obj, R witem, Projection projection) {
|
||||||
@@ -81,7 +82,7 @@ public abstract class AInprogressItemConverter<T extends InProgressSubmission,
|
|||||||
|
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
SubmissionDefinitionRest def = converter.toRest(
|
SubmissionDefinitionRest def = converter.toRest(
|
||||||
submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle()), projection);
|
submissionConfigService.getSubmissionConfigByCollection(collection.getHandle()), projection);
|
||||||
witem.setSubmissionDefinition(def);
|
witem.setSubmissionDefinition(def);
|
||||||
for (SubmissionSectionRest sections : def.getPanels()) {
|
for (SubmissionSectionRest sections : def.getPanels()) {
|
||||||
SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections);
|
SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections);
|
||||||
|
@@ -67,7 +67,7 @@ public class ItemConverter
|
|||||||
* Overrides the parent method to include virtual metadata
|
* Overrides the parent method to include virtual metadata
|
||||||
* @param context The context
|
* @param context The context
|
||||||
* @param obj The object of which the filtered metadata will be retrieved
|
* @param obj The object of which the filtered metadata will be retrieved
|
||||||
* @return A list of object metadata (including virtual metadata) filtered based on the the hidden metadata
|
* @return A list of object metadata (including virtual metadata) filtered based on the hidden metadata
|
||||||
* configuration
|
* configuration
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -79,7 +79,7 @@ public class ItemConverter
|
|||||||
Objects.isNull(context.getCurrentUser()) || !authorizeService.isAdmin(context))) {
|
Objects.isNull(context.getCurrentUser()) || !authorizeService.isAdmin(context))) {
|
||||||
return new MetadataValueList(new ArrayList<MetadataValue>());
|
return new MetadataValueList(new ArrayList<MetadataValue>());
|
||||||
}
|
}
|
||||||
if (context != null && authorizeService.isAdmin(context)) {
|
if (context != null && (authorizeService.isAdmin(context) || itemService.canEdit(context, obj))) {
|
||||||
return new MetadataValueList(fullList);
|
return new MetadataValueList(fullList);
|
||||||
}
|
}
|
||||||
for (MetadataValue mv : fullList) {
|
for (MetadataValue mv : fullList) {
|
||||||
|
@@ -80,7 +80,7 @@ public class SubmissionDefinitionConverter implements DSpaceConverter<Submission
|
|||||||
Context context = null;
|
Context context = null;
|
||||||
try {
|
try {
|
||||||
context = ContextUtil.obtainContext(request);
|
context = ContextUtil.obtainContext(request);
|
||||||
List<Collection> collections = panelConverter.getSubmissionConfigReader()
|
List<Collection> collections = panelConverter.getSubmissionConfigService()
|
||||||
.getCollectionsBySubmissionConfig(context,
|
.getCollectionsBySubmissionConfig(context,
|
||||||
obj.getSubmissionName());
|
obj.getSubmissionName());
|
||||||
DSpaceConverter<Collection, CollectionRest> cc = converter.getConverter(Collection.class);
|
DSpaceConverter<Collection, CollectionRest> cc = converter.getConverter(Collection.class);
|
||||||
|
@@ -125,7 +125,7 @@ public class SubmissionFormConverter implements DSpaceConverter<DCInputSet, Subm
|
|||||||
dcinput.getVocabulary()));
|
dcinput.getVocabulary()));
|
||||||
selMd.setClosed(
|
selMd.setClosed(
|
||||||
isClosed(dcinput.getSchema(), dcinput.getElement(), dcinput.getQualifier(),
|
isClosed(dcinput.getSchema(), dcinput.getElement(), dcinput.getQualifier(),
|
||||||
dcinput.getPairsType(), dcinput.getVocabulary()));
|
dcinput.getPairsType(), dcinput.getVocabulary(), dcinput.isClosedVocabulary()));
|
||||||
} else {
|
} else {
|
||||||
inputRest.setType(inputType);
|
inputRest.setType(inputType);
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ public class SubmissionFormConverter implements DSpaceConverter<DCInputSet, Subm
|
|||||||
selMd.setControlledVocabulary(getAuthorityName(dcinput.getSchema(), dcinput.getElement(),
|
selMd.setControlledVocabulary(getAuthorityName(dcinput.getSchema(), dcinput.getElement(),
|
||||||
pairs.get(idx + 1), dcinput.getPairsType(), dcinput.getVocabulary()));
|
pairs.get(idx + 1), dcinput.getPairsType(), dcinput.getVocabulary()));
|
||||||
selMd.setClosed(isClosed(dcinput.getSchema(), dcinput.getElement(),
|
selMd.setClosed(isClosed(dcinput.getSchema(), dcinput.getElement(),
|
||||||
dcinput.getQualifier(), null, dcinput.getVocabulary()));
|
dcinput.getQualifier(), null, dcinput.getVocabulary(), dcinput.isClosedVocabulary()));
|
||||||
}
|
}
|
||||||
selectableMetadata.add(selMd);
|
selectableMetadata.add(selMd);
|
||||||
}
|
}
|
||||||
@@ -212,9 +212,11 @@ public class SubmissionFormConverter implements DSpaceConverter<DCInputSet, Subm
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isClosed(String schema, String element, String qualifier, String valuePairsName,
|
private boolean isClosed(String schema, String element, String qualifier, String valuePairsName,
|
||||||
String vocabularyName) {
|
String vocabularyName, boolean isClosedVocabulary) {
|
||||||
if (StringUtils.isNotBlank(valuePairsName) || StringUtils.isNotBlank(vocabularyName)) {
|
if (StringUtils.isNotBlank(valuePairsName)) {
|
||||||
return true;
|
return true;
|
||||||
|
} else if (StringUtils.isNotBlank(vocabularyName)) {
|
||||||
|
return isClosedVocabulary;
|
||||||
}
|
}
|
||||||
return authorityUtils.isClosed(schema, element, qualifier);
|
return authorityUtils.isClosed(schema, element, qualifier);
|
||||||
}
|
}
|
||||||
|
@@ -7,14 +7,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.converter;
|
package org.dspace.app.rest.converter;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.rest.model.SubmissionSectionRest;
|
import org.dspace.app.rest.model.SubmissionSectionRest;
|
||||||
import org.dspace.app.rest.model.SubmissionVisibilityRest;
|
import org.dspace.app.rest.model.SubmissionVisibilityRest;
|
||||||
import org.dspace.app.rest.model.VisibilityEnum;
|
import org.dspace.app.rest.model.VisibilityEnum;
|
||||||
import org.dspace.app.rest.projection.Projection;
|
import org.dspace.app.rest.projection.Projection;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.app.util.SubmissionStepConfig;
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +31,7 @@ public class SubmissionSectionConverter implements DSpaceConverter<SubmissionSte
|
|||||||
|
|
||||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionSectionConverter.class);
|
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionSectionConverter.class);
|
||||||
|
|
||||||
private SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubmissionSectionRest convert(SubmissionStepConfig step, Projection projection) {
|
public SubmissionSectionRest convert(SubmissionStepConfig step, Projection projection) {
|
||||||
@@ -47,8 +50,8 @@ public class SubmissionSectionConverter implements DSpaceConverter<SubmissionSte
|
|||||||
SubmissionStepConfig step;
|
SubmissionStepConfig step;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
step = getSubmissionConfigReader().getStepConfig(obj.getId());
|
step = getSubmissionConfigService().getStepConfig(obj.getId());
|
||||||
} catch (SubmissionConfigReaderException e) {
|
} catch (SQLException | IllegalStateException | SubmissionConfigReaderException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return step;
|
return step;
|
||||||
@@ -59,10 +62,11 @@ public class SubmissionSectionConverter implements DSpaceConverter<SubmissionSte
|
|||||||
return SubmissionStepConfig.class;
|
return SubmissionStepConfig.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubmissionConfigReader getSubmissionConfigReader() throws SubmissionConfigReaderException {
|
public SubmissionConfigService getSubmissionConfigService()
|
||||||
if (submissionConfigReader == null) {
|
throws SubmissionConfigReaderException, SQLException, IllegalStateException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
if (submissionConfigService == null) {
|
||||||
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
return submissionConfigReader;
|
return submissionConfigService;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,9 +38,11 @@ import org.dspace.authorize.service.ValidatePasswordService;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.EmptyWorkflowGroupException;
|
import org.dspace.eperson.EmptyWorkflowGroupException;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.eperson.RegistrationData;
|
import org.dspace.eperson.RegistrationData;
|
||||||
import org.dspace.eperson.service.AccountService;
|
import org.dspace.eperson.service.AccountService;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.dspace.eperson.service.RegistrationDataService;
|
import org.dspace.eperson.service.RegistrationDataService;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -79,6 +81,9 @@ public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, E
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RegistrationDataService registrationDataService;
|
private RegistrationDataService registrationDataService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
private final EPersonService es;
|
private final EPersonService es;
|
||||||
|
|
||||||
|
|
||||||
@@ -289,6 +294,35 @@ public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the EPersons matching the query parameter which are NOT a member of the given Group.
|
||||||
|
* The search is delegated to the
|
||||||
|
* {@link EPersonService#searchNonMembers(Context, String, Group, int, int)} method
|
||||||
|
*
|
||||||
|
* @param groupUUID the *required* group UUID to exclude results from
|
||||||
|
* @param query is the *required* query string
|
||||||
|
* @param pageable contains the pagination information
|
||||||
|
* @return a Page of EPersonRest instances matching the user query
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN') || hasAuthority('MANAGE_ACCESS_GROUP')")
|
||||||
|
@SearchRestMethod(name = "isNotMemberOf")
|
||||||
|
public Page<EPersonRest> findIsNotMemberOf(@Parameter(value = "group", required = true) UUID groupUUID,
|
||||||
|
@Parameter(value = "query", required = true) String query,
|
||||||
|
Pageable pageable) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Context context = obtainContext();
|
||||||
|
Group excludeGroup = groupService.find(context, groupUUID);
|
||||||
|
long total = es.searchNonMembersCount(context, query, excludeGroup);
|
||||||
|
List<EPerson> epersons = es.searchNonMembers(context, query, excludeGroup,
|
||||||
|
Math.toIntExact(pageable.getOffset()),
|
||||||
|
Math.toIntExact(pageable.getPageSize()));
|
||||||
|
return converter.toRestPage(epersons, pageable, total, utils.obtainProjection());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasPermission(#uuid, 'EPERSON', #patch)")
|
@PreAuthorize("hasPermission(#uuid, 'EPERSON', #patch)")
|
||||||
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, UUID uuid,
|
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, UUID uuid,
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.app.rest.repository;
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -15,7 +17,9 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import org.dspace.app.rest.model.GroupRest;
|
import org.dspace.app.rest.model.GroupRest;
|
||||||
import org.dspace.app.rest.projection.Projection;
|
import org.dspace.app.rest.projection.Projection;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
|
import org.dspace.eperson.service.EPersonService;
|
||||||
import org.dspace.eperson.service.GroupService;
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -31,6 +35,9 @@ import org.springframework.stereotype.Component;
|
|||||||
public class GroupEPersonLinkRepository extends AbstractDSpaceRestRepository
|
public class GroupEPersonLinkRepository extends AbstractDSpaceRestRepository
|
||||||
implements LinkRestRepository {
|
implements LinkRestRepository {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
EPersonService epersonService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
GroupService groupService;
|
GroupService groupService;
|
||||||
|
|
||||||
@@ -45,7 +52,11 @@ public class GroupEPersonLinkRepository extends AbstractDSpaceRestRepository
|
|||||||
if (group == null) {
|
if (group == null) {
|
||||||
throw new ResourceNotFoundException("No such group: " + groupId);
|
throw new ResourceNotFoundException("No such group: " + groupId);
|
||||||
}
|
}
|
||||||
return converter.toRestPage(group.getMembers(), optionalPageable, projection);
|
int total = epersonService.countByGroups(context, Set.of(group));
|
||||||
|
Pageable pageable = utils.getPageable(optionalPageable);
|
||||||
|
List<EPerson> members = epersonService.findByGroups(context, Set.of(group), pageable.getPageSize(),
|
||||||
|
Math.toIntExact(pageable.getOffset()));
|
||||||
|
return converter.toRestPage(members, pageable, total, projection);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.app.rest.repository;
|
package org.dspace.app.rest.repository;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -45,7 +46,11 @@ public class GroupGroupLinkRepository extends AbstractDSpaceRestRepository
|
|||||||
if (group == null) {
|
if (group == null) {
|
||||||
throw new ResourceNotFoundException("No such group: " + groupId);
|
throw new ResourceNotFoundException("No such group: " + groupId);
|
||||||
}
|
}
|
||||||
return converter.toRestPage(group.getMemberGroups(), optionalPageable, projection);
|
int total = groupService.countByParent(context, group);
|
||||||
|
Pageable pageable = utils.getPageable(optionalPageable);
|
||||||
|
List<Group> memberGroups = groupService.findByParent(context, group, pageable.getPageSize(),
|
||||||
|
Math.toIntExact(pageable.getOffset()));
|
||||||
|
return converter.toRestPage(memberGroups, pageable, total, projection);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@@ -148,6 +148,35 @@ public class GroupRestRepository extends DSpaceObjectRestRepository<Group, Group
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the Groups matching the query parameter which are NOT a member of the given parent Group.
|
||||||
|
* The search is delegated to the
|
||||||
|
* {@link GroupService#searchNonMembers(Context, String, Group, int, int)} method
|
||||||
|
*
|
||||||
|
* @param groupUUID the parent group UUID
|
||||||
|
* @param query is the *required* query string
|
||||||
|
* @param pageable contains the pagination information
|
||||||
|
* @return a Page of GroupRest instances matching the user query
|
||||||
|
*/
|
||||||
|
@PreAuthorize("hasAuthority('ADMIN') || hasAuthority('MANAGE_ACCESS_GROUP')")
|
||||||
|
@SearchRestMethod(name = "isNotMemberOf")
|
||||||
|
public Page<GroupRest> findIsNotMemberOf(@Parameter(value = "group", required = true) UUID groupUUID,
|
||||||
|
@Parameter(value = "query", required = true) String query,
|
||||||
|
Pageable pageable) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Context context = obtainContext();
|
||||||
|
Group excludeParentGroup = gs.find(context, groupUUID);
|
||||||
|
long total = gs.searchNonMembersCount(context, query, excludeParentGroup);
|
||||||
|
List<Group> groups = gs.searchNonMembers(context, query, excludeParentGroup,
|
||||||
|
Math.toIntExact(pageable.getOffset()),
|
||||||
|
Math.toIntExact(pageable.getPageSize()));
|
||||||
|
return converter.toRestPage(groups, pageable, total, utils.obtainProjection());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<GroupRest> getDomainClass() {
|
public Class<GroupRest> getDomainClass() {
|
||||||
return GroupRest.class;
|
return GroupRest.class;
|
||||||
|
@@ -242,7 +242,10 @@ public class RequestItemRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonNode responseMessageNode = requestBody.findValue("responseMessage");
|
JsonNode responseMessageNode = requestBody.findValue("responseMessage");
|
||||||
String message = responseMessageNode.asText();
|
String message = null;
|
||||||
|
if (responseMessageNode != null && !responseMessageNode.isNull()) {
|
||||||
|
message = responseMessageNode.asText();
|
||||||
|
}
|
||||||
|
|
||||||
ri.setDecision_date(new Date());
|
ri.setDecision_date(new Date());
|
||||||
requestItemService.update(context, ri);
|
requestItemService.update(context, ri);
|
||||||
|
@@ -15,12 +15,13 @@ import org.dspace.app.rest.Parameter;
|
|||||||
import org.dspace.app.rest.SearchRestMethod;
|
import org.dspace.app.rest.SearchRestMethod;
|
||||||
import org.dspace.app.rest.model.SubmissionDefinitionRest;
|
import org.dspace.app.rest.model.SubmissionDefinitionRest;
|
||||||
import org.dspace.app.util.SubmissionConfig;
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -33,18 +34,18 @@ import org.springframework.stereotype.Component;
|
|||||||
*/
|
*/
|
||||||
@Component(SubmissionDefinitionRest.CATEGORY + "." + SubmissionDefinitionRest.NAME)
|
@Component(SubmissionDefinitionRest.CATEGORY + "." + SubmissionDefinitionRest.NAME)
|
||||||
public class SubmissionDefinitionRestRepository extends DSpaceRestRepository<SubmissionDefinitionRest, String> {
|
public class SubmissionDefinitionRestRepository extends DSpaceRestRepository<SubmissionDefinitionRest, String> {
|
||||||
private SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||||
|
|
||||||
public SubmissionDefinitionRestRepository() throws SubmissionConfigReaderException {
|
public SubmissionDefinitionRestRepository() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
@Override
|
@Override
|
||||||
public SubmissionDefinitionRest findOne(Context context, String submitName) {
|
public SubmissionDefinitionRest findOne(Context context, String submitName) {
|
||||||
SubmissionConfig subConfig = submissionConfigReader.getSubmissionConfigByName(submitName);
|
SubmissionConfig subConfig = submissionConfigService.getSubmissionConfigByName(submitName);
|
||||||
if (subConfig == null) {
|
if (subConfig == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -54,8 +55,8 @@ public class SubmissionDefinitionRestRepository extends DSpaceRestRepository<Sub
|
|||||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
@Override
|
@Override
|
||||||
public Page<SubmissionDefinitionRest> findAll(Context context, Pageable pageable) {
|
public Page<SubmissionDefinitionRest> findAll(Context context, Pageable pageable) {
|
||||||
int total = submissionConfigReader.countSubmissionConfigs();
|
int total = submissionConfigService.countSubmissionConfigs();
|
||||||
List<SubmissionConfig> subConfs = submissionConfigReader.getAllSubmissionConfigs(
|
List<SubmissionConfig> subConfs = submissionConfigService.getAllSubmissionConfigs(
|
||||||
pageable.getPageSize(), Math.toIntExact(pageable.getOffset()));
|
pageable.getPageSize(), Math.toIntExact(pageable.getOffset()));
|
||||||
return converter.toRestPage(subConfs, pageable, total, utils.obtainProjection());
|
return converter.toRestPage(subConfs, pageable, total, utils.obtainProjection());
|
||||||
}
|
}
|
||||||
@@ -69,7 +70,7 @@ public class SubmissionDefinitionRestRepository extends DSpaceRestRepository<Sub
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SubmissionDefinitionRest def = converter
|
SubmissionDefinitionRest def = converter
|
||||||
.toRest(submissionConfigReader.getSubmissionConfigByCollection(col.getHandle()),
|
.toRest(submissionConfigService.getSubmissionConfigByCollection(col.getHandle()),
|
||||||
utils.obtainProjection());
|
utils.obtainProjection());
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
@@ -13,10 +13,11 @@ import java.util.List;
|
|||||||
import org.dspace.app.rest.model.SubmissionDefinitionRest;
|
import org.dspace.app.rest.model.SubmissionDefinitionRest;
|
||||||
import org.dspace.app.rest.model.SubmissionSectionRest;
|
import org.dspace.app.rest.model.SubmissionSectionRest;
|
||||||
import org.dspace.app.util.SubmissionConfig;
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.app.util.SubmissionStepConfig;
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -30,17 +31,17 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component(SubmissionDefinitionRest.CATEGORY + "." + SubmissionSectionRest.NAME)
|
@Component(SubmissionDefinitionRest.CATEGORY + "." + SubmissionSectionRest.NAME)
|
||||||
public class SubmissionPanelRestRepository extends DSpaceRestRepository<SubmissionSectionRest, String> {
|
public class SubmissionPanelRestRepository extends DSpaceRestRepository<SubmissionSectionRest, String> {
|
||||||
|
|
||||||
private SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
public SubmissionPanelRestRepository() throws SubmissionConfigReaderException {
|
public SubmissionPanelRestRepository() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
@Override
|
@Override
|
||||||
public SubmissionSectionRest findOne(Context context, String id) {
|
public SubmissionSectionRest findOne(Context context, String id) {
|
||||||
try {
|
try {
|
||||||
SubmissionStepConfig step = submissionConfigReader.getStepConfig(id);
|
SubmissionStepConfig step = submissionConfigService.getStepConfig(id);
|
||||||
return converter.toRest(step, utils.obtainProjection());
|
return converter.toRest(step, utils.obtainProjection());
|
||||||
} catch (SubmissionConfigReaderException e) {
|
} catch (SubmissionConfigReaderException e) {
|
||||||
//TODO wrap with a specific exception
|
//TODO wrap with a specific exception
|
||||||
@@ -51,7 +52,7 @@ public class SubmissionPanelRestRepository extends DSpaceRestRepository<Submissi
|
|||||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||||
@Override
|
@Override
|
||||||
public Page<SubmissionSectionRest> findAll(Context context, Pageable pageable) {
|
public Page<SubmissionSectionRest> findAll(Context context, Pageable pageable) {
|
||||||
List<SubmissionConfig> subConfs = submissionConfigReader.getAllSubmissionConfigs(
|
List<SubmissionConfig> subConfs = submissionConfigService.getAllSubmissionConfigs(
|
||||||
pageable.getPageSize(), Math.toIntExact(pageable.getOffset()));
|
pageable.getPageSize(), Math.toIntExact(pageable.getOffset()));
|
||||||
long total = 0;
|
long total = 0;
|
||||||
List<SubmissionStepConfig> stepConfs = new ArrayList<>();
|
List<SubmissionStepConfig> stepConfs = new ArrayList<>();
|
||||||
|
@@ -27,7 +27,6 @@ import org.dspace.app.rest.model.WorkflowItemRest;
|
|||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.app.rest.model.patch.Patch;
|
import org.dspace.app.rest.model.patch.Patch;
|
||||||
import org.dspace.app.rest.submit.SubmissionService;
|
import org.dspace.app.rest.submit.SubmissionService;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
@@ -40,6 +39,8 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.EPersonServiceImpl;
|
import org.dspace.eperson.EPersonServiceImpl;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.dspace.workflow.WorkflowException;
|
import org.dspace.workflow.WorkflowException;
|
||||||
import org.dspace.workflow.WorkflowService;
|
import org.dspace.workflow.WorkflowService;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
@@ -109,10 +110,10 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowIte
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected XmlWorkflowFactory workflowFactory;
|
protected XmlWorkflowFactory workflowFactory;
|
||||||
|
|
||||||
private final SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
public WorkflowItemRestRepository() throws SubmissionConfigReaderException {
|
public WorkflowItemRestRepository() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -33,7 +33,6 @@ import org.dspace.app.rest.submit.SubmissionService;
|
|||||||
import org.dspace.app.rest.submit.UploadableStep;
|
import org.dspace.app.rest.submit.UploadableStep;
|
||||||
import org.dspace.app.rest.utils.Utils;
|
import org.dspace.app.rest.utils.Utils;
|
||||||
import org.dspace.app.util.SubmissionConfig;
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.app.util.SubmissionStepConfig;
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -57,6 +56,8 @@ import org.dspace.importer.external.exception.FileMultipleOccurencesException;
|
|||||||
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||||
import org.dspace.importer.external.service.ImportService;
|
import org.dspace.importer.external.service.ImportService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -116,10 +117,10 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UriListHandlerService uriListHandlerService;
|
private UriListHandlerService uriListHandlerService;
|
||||||
|
|
||||||
private SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
public WorkspaceItemRestRepository() throws SubmissionConfigReaderException {
|
public WorkspaceItemRestRepository() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'READ')")
|
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'READ')")
|
||||||
@@ -250,7 +251,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
|||||||
}
|
}
|
||||||
|
|
||||||
SubmissionConfig submissionConfig =
|
SubmissionConfig submissionConfig =
|
||||||
submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle());
|
submissionConfigService.getSubmissionConfigByCollection(collection.getHandle());
|
||||||
List<WorkspaceItem> result = null;
|
List<WorkspaceItem> result = null;
|
||||||
List<ImportRecord> records = new ArrayList<>();
|
List<ImportRecord> records = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
|
@@ -37,7 +37,6 @@ import org.dspace.app.rest.repository.WorkflowItemRestRepository;
|
|||||||
import org.dspace.app.rest.repository.WorkspaceItemRestRepository;
|
import org.dspace.app.rest.repository.WorkspaceItemRestRepository;
|
||||||
import org.dspace.app.rest.utils.ContextUtil;
|
import org.dspace.app.rest.utils.ContextUtil;
|
||||||
import org.dspace.app.util.SubmissionConfig;
|
import org.dspace.app.util.SubmissionConfig;
|
||||||
import org.dspace.app.util.SubmissionConfigReader;
|
|
||||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.app.util.SubmissionStepConfig;
|
import org.dspace.app.util.SubmissionStepConfig;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
@@ -58,6 +57,8 @@ import org.dspace.license.service.CreativeCommonsService;
|
|||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.RequestService;
|
import org.dspace.services.RequestService;
|
||||||
import org.dspace.services.model.Request;
|
import org.dspace.services.model.Request;
|
||||||
|
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||||
|
import org.dspace.submit.service.SubmissionConfigService;
|
||||||
import org.dspace.workflow.WorkflowException;
|
import org.dspace.workflow.WorkflowException;
|
||||||
import org.dspace.workflow.WorkflowItemService;
|
import org.dspace.workflow.WorkflowItemService;
|
||||||
import org.dspace.workflow.WorkflowService;
|
import org.dspace.workflow.WorkflowService;
|
||||||
@@ -100,10 +101,10 @@ public class SubmissionService {
|
|||||||
private ConverterService converter;
|
private ConverterService converter;
|
||||||
@Autowired
|
@Autowired
|
||||||
private org.dspace.app.rest.utils.Utils utils;
|
private org.dspace.app.rest.utils.Utils utils;
|
||||||
private SubmissionConfigReader submissionConfigReader;
|
private SubmissionConfigService submissionConfigService;
|
||||||
|
|
||||||
public SubmissionService() throws SubmissionConfigReaderException {
|
public SubmissionService() throws SubmissionConfigReaderException {
|
||||||
submissionConfigReader = new SubmissionConfigReader();
|
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -329,7 +330,7 @@ public class SubmissionService {
|
|||||||
AInprogressSubmissionRest wsi, InProgressSubmission source, MultipartFile file) {
|
AInprogressSubmissionRest wsi, InProgressSubmission source, MultipartFile file) {
|
||||||
List<ErrorRest> errors = new ArrayList<ErrorRest>();
|
List<ErrorRest> errors = new ArrayList<ErrorRest>();
|
||||||
SubmissionConfig submissionConfig =
|
SubmissionConfig submissionConfig =
|
||||||
submissionConfigReader.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
submissionConfigService.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
||||||
List<Object[]> stepInstancesAndConfigs = new ArrayList<Object[]>();
|
List<Object[]> stepInstancesAndConfigs = new ArrayList<Object[]>();
|
||||||
// we need to run the preProcess of all the appropriate steps and move on to the
|
// we need to run the preProcess of all the appropriate steps and move on to the
|
||||||
// upload and postProcess step
|
// upload and postProcess step
|
||||||
@@ -396,7 +397,7 @@ public class SubmissionService {
|
|||||||
public void evaluatePatchToInprogressSubmission(Context context, HttpServletRequest request,
|
public void evaluatePatchToInprogressSubmission(Context context, HttpServletRequest request,
|
||||||
InProgressSubmission source, AInprogressSubmissionRest wsi, String section, Operation op) {
|
InProgressSubmission source, AInprogressSubmissionRest wsi, String section, Operation op) {
|
||||||
boolean sectionExist = false;
|
boolean sectionExist = false;
|
||||||
SubmissionConfig submissionConfig = submissionConfigReader
|
SubmissionConfig submissionConfig = submissionConfigService
|
||||||
.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
|
||||||
List<Object[]> stepInstancesAndConfigs = new ArrayList<Object[]>();
|
List<Object[]> stepInstancesAndConfigs = new ArrayList<Object[]>();
|
||||||
// we need to run the preProcess of all the appropriate steps and move on to the
|
// we need to run the preProcess of all the appropriate steps and move on to the
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.app.rest;
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
import static java.lang.Thread.sleep;
|
||||||
|
import static org.dspace.app.rest.matcher.GroupMatcher.matchGroupWithName;
|
||||||
import static org.dspace.app.rest.utils.RegexUtils.REGEX_UUID;
|
import static org.dspace.app.rest.utils.RegexUtils.REGEX_UUID;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
@@ -1641,6 +1642,71 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAreSpecialGroupsApplicable() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("specialGroupPwd")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("specialGroupShib")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_AND_PASS);
|
||||||
|
configurationService.setProperty("authentication-password.login.specialgroup", "specialGroupPwd");
|
||||||
|
configurationService.setProperty("authentication-shibboleth.role.faculty", "specialGroupShib");
|
||||||
|
configurationService.setProperty("authentication-shibboleth.default-roles", "faculty");
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String passwordToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(passwordToken).perform(get("/api/authn/status").param("projection", "full"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", AuthenticationStatusMatcher.matchFullEmbeds()))
|
||||||
|
.andExpect(jsonPath("$", AuthenticationStatusMatcher.matchLinks()))
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.okay", is(true)))
|
||||||
|
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||||
|
.andExpect(jsonPath("$.authenticationMethod", is("password")))
|
||||||
|
.andExpect(jsonPath("$.type", is("status")))
|
||||||
|
.andExpect(jsonPath("$._links.specialGroups.href", startsWith(REST_SERVER_URL)))
|
||||||
|
.andExpect(jsonPath("$._embedded.specialGroups._embedded.specialGroups",
|
||||||
|
Matchers.containsInAnyOrder(matchGroupWithName("specialGroupPwd"))));
|
||||||
|
|
||||||
|
getClient(passwordToken).perform(get("/api/authn/status/specialGroups").param("projection", "full"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.specialGroups",
|
||||||
|
Matchers.containsInAnyOrder(matchGroupWithName("specialGroupPwd"))));
|
||||||
|
|
||||||
|
String shibToken = getClient().perform(post("/api/authn/login")
|
||||||
|
.requestAttr("SHIB-MAIL", eperson.getEmail())
|
||||||
|
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andReturn().getResponse().getHeader(AUTHORIZATION_HEADER).replace(AUTHORIZATION_TYPE, "");
|
||||||
|
|
||||||
|
getClient(shibToken).perform(get("/api/authn/status").param("projection", "full"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", AuthenticationStatusMatcher.matchFullEmbeds()))
|
||||||
|
.andExpect(jsonPath("$", AuthenticationStatusMatcher.matchLinks()))
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.okay", is(true)))
|
||||||
|
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||||
|
.andExpect(jsonPath("$.authenticationMethod", is("shibboleth")))
|
||||||
|
.andExpect(jsonPath("$.type", is("status")))
|
||||||
|
.andExpect(jsonPath("$._links.specialGroups.href", startsWith(REST_SERVER_URL)))
|
||||||
|
.andExpect(jsonPath("$._embedded.specialGroups._embedded.specialGroups",
|
||||||
|
Matchers.containsInAnyOrder(matchGroupWithName("specialGroupShib"))));
|
||||||
|
|
||||||
|
getClient(shibToken).perform(get("/api/authn/status/specialGroups").param("projection", "full"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.specialGroups",
|
||||||
|
Matchers.containsInAnyOrder(matchGroupWithName("specialGroupShib"))));
|
||||||
|
}
|
||||||
|
|
||||||
// Get a short-lived token based on an active login token
|
// Get a short-lived token based on an active login token
|
||||||
private String getShortLivedToken(String loginToken) throws Exception {
|
private String getShortLivedToken(String loginToken) throws Exception {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
@@ -79,6 +79,7 @@ import org.dspace.eperson.Group;
|
|||||||
import org.dspace.eperson.PasswordHash;
|
import org.dspace.eperson.PasswordHash;
|
||||||
import org.dspace.eperson.service.AccountService;
|
import org.dspace.eperson.service.AccountService;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.dspace.eperson.service.RegistrationDataService;
|
import org.dspace.eperson.service.RegistrationDataService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
@@ -96,6 +97,9 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EPersonService ePersonService;
|
private EPersonService ePersonService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConfigurationService configurationService;
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
@@ -775,6 +779,242 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
.andExpect(status().isBadRequest());
|
.andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test of /epersons/search/isNotMemberOf pagination
|
||||||
|
// NOTE: Additional tests of 'isNotMemberOf' search functionality can be found in EPersonTest in 'dspace-api'
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfPaginationTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test Parent group")
|
||||||
|
.build();
|
||||||
|
// Create two EPerson in main group. These SHOULD NOT be included in pagination
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test", "Person")
|
||||||
|
.withEmail("test@example.com")
|
||||||
|
.withGroupMembership(group)
|
||||||
|
.build();
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test2", "Person")
|
||||||
|
.withEmail("test2@example.com")
|
||||||
|
.withGroupMembership(group)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create five EPersons who are NOT members of that group. These SHOULD be included in pagination
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test3", "Person")
|
||||||
|
.withEmail("test3@example.com")
|
||||||
|
.build();
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test4", "Person")
|
||||||
|
.withEmail("test4@example.com")
|
||||||
|
.build();
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test5", "Person")
|
||||||
|
.withEmail("test5@example.com")
|
||||||
|
.build();
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test6", "Person")
|
||||||
|
.withEmail("test6@example.com")
|
||||||
|
.build();
|
||||||
|
EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Test7", "Person")
|
||||||
|
.withEmail("test7@example.com")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authTokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "person")
|
||||||
|
.param("page", "0")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(0)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "person")
|
||||||
|
.param("page", "1")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(1)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "person")
|
||||||
|
.param("page", "2")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(1)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfByEmail() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group")
|
||||||
|
.build();
|
||||||
|
Group group2 = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test another group")
|
||||||
|
.build();
|
||||||
|
EPerson ePerson = EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("John", "Doe")
|
||||||
|
.withEmail("Johndoe@example.com")
|
||||||
|
.withGroupMembership(group)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Jane", "Smith")
|
||||||
|
.withEmail("janesmith@example.com")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
EPerson ePerson3 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Tom", "Doe")
|
||||||
|
.withEmail("tomdoe@example.com")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
EPerson ePerson4 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("Harry", "Prefix-Doe")
|
||||||
|
.withEmail("harrydoeprefix@example.com")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
// Search for exact email in a group the person already belongs to. Should return zero results.
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", ePerson.getEmail())
|
||||||
|
.param("group", group.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||||
|
|
||||||
|
// Search for exact email in a group the person does NOT belong to. Should return the person
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", ePerson.getEmail())
|
||||||
|
.param("group", group2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.contains(
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||||
|
|
||||||
|
// Search partial email should return all the people created above.
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", "example.com")
|
||||||
|
.param("group", group2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.containsInAnyOrder(
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson),
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson2),
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson3),
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson4)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfByUUID() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group")
|
||||||
|
.build();
|
||||||
|
Group group2 = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test another group")
|
||||||
|
.build();
|
||||||
|
EPerson ePerson = EPersonBuilder.createEPerson(context)
|
||||||
|
.withNameInMetadata("John", "Doe")
|
||||||
|
.withEmail("Johndoe@example.com")
|
||||||
|
.withGroupMembership(group)
|
||||||
|
.build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
// Search for UUID in a group the person already belongs to. Should return zero results.
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", ePerson.getID().toString())
|
||||||
|
.param("group", group.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||||
|
|
||||||
|
// Search for exact email in a group the person does NOT belong to. Should return the person
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", ePerson.getID().toString())
|
||||||
|
.param("group", group2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.contains(
|
||||||
|
EPersonMatcher.matchEPersonEntry(ePerson)
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfUnauthorized() throws Exception {
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
getClient().perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", eperson.getID().toString())
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isUnauthorized());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfForbidden() throws Exception {
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", eperson.getID().toString())
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isForbidden());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfMissingOrInvalidParameter() throws Exception {
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
String authToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", eperson.getID().toString()))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
// Test invalid group UUID
|
||||||
|
getClient(authToken).perform(get("/api/eperson/epersons/search/isNotMemberOf")
|
||||||
|
.param("query", eperson.getID().toString())
|
||||||
|
.param("group", "not-a-uuid"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteOne() throws Exception {
|
public void deleteOne() throws Exception {
|
||||||
context.turnOffAuthorisationSystem();
|
context.turnOffAuthorisationSystem();
|
||||||
|
@@ -3091,6 +3091,343 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test of /groups/[uuid]/epersons pagination
|
||||||
|
@Test
|
||||||
|
public void epersonMemberPaginationTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
EPerson eperson1 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("test1@example.com")
|
||||||
|
.withNameInMetadata("Test1", "User")
|
||||||
|
.build();
|
||||||
|
EPerson eperson2 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("test2@example.com")
|
||||||
|
.withNameInMetadata("Test2", "User")
|
||||||
|
.build();
|
||||||
|
EPerson eperson3 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("test3@example.com")
|
||||||
|
.withNameInMetadata("Test3", "User")
|
||||||
|
.build();
|
||||||
|
EPerson eperson4 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("test4@example.com")
|
||||||
|
.withNameInMetadata("Test4", "User")
|
||||||
|
.build();
|
||||||
|
EPerson eperson5 = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("test5@example.com")
|
||||||
|
.withNameInMetadata("Test5", "User")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group")
|
||||||
|
.addMember(eperson1)
|
||||||
|
.addMember(eperson2)
|
||||||
|
.addMember(eperson3)
|
||||||
|
.addMember(eperson4)
|
||||||
|
.addMember(eperson5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authTokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/epersons")
|
||||||
|
.param("page", "0")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(0)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/epersons")
|
||||||
|
.param("page", "1")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(1)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/epersons")
|
||||||
|
.param("page", "2")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("eperson")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.epersons").value(Matchers.hasSize(1)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test of /groups/[uuid]/subgroups pagination
|
||||||
|
@Test
|
||||||
|
public void subgroupPaginationTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test subgroup 1")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test subgroup 2")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test subgroup 3")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test subgroup 4")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test subgroup 5")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authTokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/subgroups")
|
||||||
|
.param("page", "0")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(0)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/subgroups")
|
||||||
|
.param("page", "1")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(1)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/" + group.getID() + "/subgroups")
|
||||||
|
.param("page", "2")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.subgroups").value(Matchers.hasSize(1)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test of /groups/search/isNotMemberOf pagination
|
||||||
|
// NOTE: Additional tests of 'isNotMemberOf' search functionality can be found in GroupTest in 'dspace-api'
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfPaginationTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Group group = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test Parent group")
|
||||||
|
.build();
|
||||||
|
// Create two subgroups of main group. These SHOULD NOT be included in pagination
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test group 1")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group)
|
||||||
|
.withName("Test group 2")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create five non-member groups. These SHOULD be included in pagination
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group 3")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group 4")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group 5")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group 6")
|
||||||
|
.build();
|
||||||
|
GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test group 7")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authTokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "test group")
|
||||||
|
.param("page", "0")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(0)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "test group")
|
||||||
|
.param("page", "1")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups").value(Matchers.hasSize(2)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(1)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group.getID().toString())
|
||||||
|
.param("query", "test group")
|
||||||
|
.param("page", "2")
|
||||||
|
.param("size", "2"))
|
||||||
|
.andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups", Matchers.everyItem(
|
||||||
|
hasJsonPath("$.type", is("group")))
|
||||||
|
))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups").value(Matchers.hasSize(1)))
|
||||||
|
.andExpect(jsonPath("$.page.size", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.number", is(2)))
|
||||||
|
.andExpect(jsonPath("$.page.totalPages", is(3)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfByUUID() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
// Create two groups which have no parent group
|
||||||
|
Group group1 = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test Parent group 1")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Group group2 = GroupBuilder.createGroup(context)
|
||||||
|
.withName("Test Parent group 2")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create a subgroup of parent group 1
|
||||||
|
Group group3 = GroupBuilder.createGroup(context)
|
||||||
|
.withParent(group1)
|
||||||
|
.withName("Test subgroup")
|
||||||
|
.build();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String authTokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||||
|
// Search for UUID in a group that the subgroup already belongs to. Should return ZERO results.
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group1.getID().toString())
|
||||||
|
.param("query", group3.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||||
|
|
||||||
|
// Search for UUID in a group that the subgroup does NOT belong to. Should return group via exact match
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group2.getID().toString())
|
||||||
|
.param("query", group3.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$._embedded.groups", Matchers.contains(
|
||||||
|
GroupMatcher.matchGroupEntry(group3.getID(), group3.getName())
|
||||||
|
)))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||||
|
|
||||||
|
// Search for UUID of the group in the "group" param. Should return ZERO results, as "group" param is excluded
|
||||||
|
getClient(authTokenAdmin).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", group1.getID().toString())
|
||||||
|
.param("query", group1.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType(contentType))
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfUnauthorized() throws Exception {
|
||||||
|
// To avoid creating data, just use the Admin & Anon groups for this test
|
||||||
|
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
Group anonGroup = groupService.findByName(context, Group.ANONYMOUS);
|
||||||
|
|
||||||
|
getClient().perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("query", anonGroup.getID().toString())
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isUnauthorized());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfForbidden() throws Exception {
|
||||||
|
// To avoid creating data, just use the Admin & Anon groups for this test
|
||||||
|
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
Group anonGroup = groupService.findByName(context, Group.ANONYMOUS);
|
||||||
|
|
||||||
|
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
getClient(authToken).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("query", anonGroup.getID().toString())
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isForbidden());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchIsNotMemberOfMissingOrInvalidParameter() throws Exception {
|
||||||
|
// To avoid creating data, just use the Admin & Anon groups for this test
|
||||||
|
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||||
|
Group adminGroup = groupService.findByName(context, Group.ADMIN);
|
||||||
|
Group anonGroup = groupService.findByName(context, Group.ANONYMOUS);
|
||||||
|
|
||||||
|
String authToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
getClient(authToken).perform(get("/api/eperson/groups/search/isNotMemberOf"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
getClient(authToken).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("query", anonGroup.getID().toString()))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
getClient(authToken).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("group", adminGroup.getID().toString()))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
|
||||||
|
// Test invalid group UUID
|
||||||
|
getClient(authToken).perform(get("/api/eperson/groups/search/isNotMemberOf")
|
||||||
|
.param("query", anonGroup.getID().toString())
|
||||||
|
.param("group", "not-a-uuid"))
|
||||||
|
.andExpect(status().isBadRequest());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void commAdminAndColAdminCannotExploitItemReadGroupTest() throws Exception {
|
public void commAdminAndColAdminCannotExploitItemReadGroupTest() throws Exception {
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
|
|||||||
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist;
|
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist;
|
||||||
import static org.dspace.builder.OrcidHistoryBuilder.createOrcidHistory;
|
import static org.dspace.builder.OrcidHistoryBuilder.createOrcidHistory;
|
||||||
import static org.dspace.builder.OrcidQueueBuilder.createOrcidQueue;
|
import static org.dspace.builder.OrcidQueueBuilder.createOrcidQueue;
|
||||||
|
import static org.dspace.core.Constants.READ;
|
||||||
import static org.dspace.core.Constants.WRITE;
|
import static org.dspace.core.Constants.WRITE;
|
||||||
import static org.dspace.orcid.OrcidOperation.DELETE;
|
import static org.dspace.orcid.OrcidOperation.DELETE;
|
||||||
import static org.dspace.profile.OrcidEntitySyncPreference.ALL;
|
import static org.dspace.profile.OrcidEntitySyncPreference.ALL;
|
||||||
@@ -3021,10 +3022,43 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
|
|||||||
String token = getAuthToken(eperson.getEmail(), password);
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
getClient(token).perform(get("/api/core/items/" + item.getID()))
|
getClient(token).perform(get("/api/core/items/" + item.getID()))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$", ItemMatcher.matchItemProperties(item)))
|
.andExpect(jsonPath("$", ItemMatcher.matchItemProperties(item)))
|
||||||
.andExpect(jsonPath("$.metadata", matchMetadata("dc.title", "Public item 1")))
|
.andExpect(jsonPath("$.metadata", matchMetadata("dc.title", "Public item 1")))
|
||||||
.andExpect(jsonPath("$.metadata", matchMetadataDoesNotExist("dc.description.provenance")));
|
.andExpect(jsonPath("$.metadata", matchMetadata("dc.description.provenance", "Provenance data")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHiddenMetadataForUserWithReadRights() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, col1)
|
||||||
|
.withTitle("Public item 1")
|
||||||
|
.withProvenanceData("Provenance data")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
|
||||||
|
ResourcePolicyBuilder.createResourcePolicy(context)
|
||||||
|
.withUser(eperson)
|
||||||
|
.withAction(READ)
|
||||||
|
.withDspaceObject(item)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String token = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(token).perform(get("/api/core/items/" + item.getID()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", ItemMatcher.matchItemProperties(item)))
|
||||||
|
.andExpect(jsonPath("$.metadata", matchMetadata("dc.title", "Public item 1")))
|
||||||
|
.andExpect(jsonPath("$.metadata", matchMetadataDoesNotExist("dc.description.provenance")));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.app.rest;
|
package org.dspace.app.rest;
|
||||||
|
|
||||||
import static org.dspace.builder.ItemBuilder.createItem;
|
import static org.dspace.builder.ItemBuilder.createItem;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
@@ -16,6 +17,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
|
import org.dspace.authorize.service.ResourcePolicyService;
|
||||||
import org.dspace.builder.CollectionBuilder;
|
import org.dspace.builder.CollectionBuilder;
|
||||||
import org.dspace.builder.CommunityBuilder;
|
import org.dspace.builder.CommunityBuilder;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
@@ -38,10 +40,22 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
ConfigurationService configurationService;
|
ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ResourcePolicyService policyService;
|
||||||
|
|
||||||
private final static String SITEMAPS_ENDPOINT = "sitemaps";
|
private final static String SITEMAPS_ENDPOINT = "sitemaps";
|
||||||
|
|
||||||
private Item item1;
|
private Item item1;
|
||||||
private Item item2;
|
private Item item2;
|
||||||
|
private Item itemRestricted;
|
||||||
|
private Item itemUndiscoverable;
|
||||||
|
private Item entityPublication;
|
||||||
|
private Item entityPublicationRestricted;
|
||||||
|
private Item entityPublicationUndiscoverable;
|
||||||
|
private Community community;
|
||||||
|
private Community communityRestricted;
|
||||||
|
private Collection collection;
|
||||||
|
private Collection collectionRestricted;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@Override
|
@Override
|
||||||
@@ -52,8 +66,16 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest {
|
|||||||
|
|
||||||
context.turnOffAuthorisationSystem();
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
Community community = CommunityBuilder.createCommunity(context).build();
|
community = CommunityBuilder.createCommunity(context).build();
|
||||||
Collection collection = CollectionBuilder.createCollection(context, community).build();
|
communityRestricted = CommunityBuilder.createCommunity(context).build();
|
||||||
|
policyService.removeAllPolicies(context, communityRestricted);
|
||||||
|
collection = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
collectionRestricted = CollectionBuilder.createCollection(context, community).build();
|
||||||
|
Collection publicationCollection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withEntityType("Publication")
|
||||||
|
.withName("Publication Collection").build();
|
||||||
|
policyService.removeAllPolicies(context, collectionRestricted);
|
||||||
|
|
||||||
this.item1 = createItem(context, collection)
|
this.item1 = createItem(context, collection)
|
||||||
.withTitle("Test 1")
|
.withTitle("Test 1")
|
||||||
.withIssueDate("2010-10-17")
|
.withIssueDate("2010-10-17")
|
||||||
@@ -62,6 +84,30 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest {
|
|||||||
.withTitle("Test 2")
|
.withTitle("Test 2")
|
||||||
.withIssueDate("2015-8-3")
|
.withIssueDate("2015-8-3")
|
||||||
.build();
|
.build();
|
||||||
|
this.itemRestricted = createItem(context, collection)
|
||||||
|
.withTitle("Test 3")
|
||||||
|
.withIssueDate("2015-8-3")
|
||||||
|
.build();
|
||||||
|
policyService.removeAllPolicies(context, itemRestricted);
|
||||||
|
this.itemUndiscoverable = createItem(context, collection)
|
||||||
|
.withTitle("Test 4")
|
||||||
|
.withIssueDate("2015-8-3")
|
||||||
|
.makeUnDiscoverable()
|
||||||
|
.build();
|
||||||
|
this.entityPublication = createItem(context, publicationCollection)
|
||||||
|
.withTitle("Item Publication")
|
||||||
|
.withIssueDate("2015-8-3")
|
||||||
|
.build();
|
||||||
|
this.entityPublicationRestricted = createItem(context, publicationCollection)
|
||||||
|
.withTitle("Item Publication Restricted")
|
||||||
|
.withIssueDate("2015-8-3")
|
||||||
|
.build();
|
||||||
|
policyService.removeAllPolicies(context, entityPublicationRestricted);
|
||||||
|
this.entityPublicationUndiscoverable = createItem(context, publicationCollection)
|
||||||
|
.withTitle("Item Publication")
|
||||||
|
.withIssueDate("2015-8-3")
|
||||||
|
.makeUnDiscoverable()
|
||||||
|
.build();
|
||||||
|
|
||||||
runDSpaceScript("generate-sitemaps");
|
runDSpaceScript("generate-sitemaps");
|
||||||
|
|
||||||
@@ -127,9 +173,39 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest {
|
|||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
String response = result.getResponse().getContentAsString();
|
String response = result.getResponse().getContentAsString();
|
||||||
|
// contains a link to communities: [dspace.ui.url]/communities/<uuid>
|
||||||
|
assertTrue(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/communities/" + community.getID()));
|
||||||
|
// contains a link to collections: [dspace.ui.url]/collections/<uuid>
|
||||||
|
assertTrue(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/collections/" + collection.getID()));
|
||||||
// contains a link to items: [dspace.ui.url]/items/<uuid>
|
// contains a link to items: [dspace.ui.url]/items/<uuid>
|
||||||
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item1.getID()));
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item1.getID()));
|
||||||
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item2.getID()));
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item2.getID()));
|
||||||
|
// contains proper link to entities items
|
||||||
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublication.getID()));
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + entityPublication.getID()));
|
||||||
|
// does not contain links to restricted content
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/communities/" + communityRestricted.getID()));
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/collections/" + collectionRestricted.getID()));
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + itemRestricted.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublicationRestricted.getID()));
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/items/" + entityPublicationRestricted.getID()));
|
||||||
|
// does not contain links to undiscoverable content
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + itemUndiscoverable.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublicationUndiscoverable.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/"
|
||||||
|
+ entityPublicationUndiscoverable.getID()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -160,8 +236,37 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest {
|
|||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
String response = result.getResponse().getContentAsString();
|
String response = result.getResponse().getContentAsString();
|
||||||
|
// contains a link to communities: [dspace.ui.url]/communities/<uuid>
|
||||||
|
assertTrue(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/communities/" + community.getID()));
|
||||||
|
// contains a link to collections: [dspace.ui.url]/collections/<uuid>
|
||||||
|
assertTrue(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/collections/" + collection.getID()));
|
||||||
// contains a link to items: [dspace.ui.url]/items/<uuid>
|
// contains a link to items: [dspace.ui.url]/items/<uuid>
|
||||||
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item1.getID()));
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item1.getID()));
|
||||||
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item2.getID()));
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + item2.getID()));
|
||||||
|
// contains proper link to entities items
|
||||||
|
assertTrue(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublication.getID()));
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + entityPublication.getID()));
|
||||||
|
// does not contain links to restricted content
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/communities/" + communityRestricted.getID()));
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/collections/" + collectionRestricted.getID()));
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + itemRestricted.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublicationRestricted.getID()));
|
||||||
|
assertFalse(response.contains(
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/items/" + entityPublicationRestricted.getID()));
|
||||||
|
// does not contain links to undiscoverable content
|
||||||
|
assertFalse(response
|
||||||
|
.contains(configurationService.getProperty("dspace.ui.url") + "/items/" + itemUndiscoverable.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/entities/publication/"
|
||||||
|
+ entityPublicationUndiscoverable.getID()));
|
||||||
|
assertFalse(response.contains(configurationService.getProperty("dspace.ui.url") + "/items/"
|
||||||
|
+ entityPublicationUndiscoverable.getID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import org.dspace.app.rest.matcher.SubmissionFormFieldMatcher;
|
|||||||
import org.dspace.app.rest.repository.SubmissionFormRestRepository;
|
import org.dspace.app.rest.repository.SubmissionFormRestRepository;
|
||||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
import org.dspace.app.util.DCInputsReaderException;
|
import org.dspace.app.util.DCInputsReaderException;
|
||||||
|
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||||
import org.dspace.builder.EPersonBuilder;
|
import org.dspace.builder.EPersonBuilder;
|
||||||
import org.dspace.content.authority.DCInputAuthority;
|
import org.dspace.content.authority.DCInputAuthority;
|
||||||
import org.dspace.content.authority.service.ChoiceAuthorityService;
|
import org.dspace.content.authority.service.ChoiceAuthorityService;
|
||||||
@@ -666,7 +667,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetLocalesConfiguration() throws DCInputsReaderException {
|
private void resetLocalesConfiguration() throws DCInputsReaderException, SubmissionConfigReaderException {
|
||||||
configurationService.setProperty("default.locale","en");
|
configurationService.setProperty("default.locale","en");
|
||||||
configurationService.setProperty("webui.supported.locales",null);
|
configurationService.setProperty("webui.supported.locales",null);
|
||||||
submissionFormRestRepository.reload();
|
submissionFormRestRepository.reload();
|
||||||
|
@@ -780,7 +780,7 @@ event.dispatcher.default.class = org.dspace.event.BasicDispatcher
|
|||||||
# Add rdf here, if you are using dspace-rdf to export your repository content as RDF.
|
# Add rdf here, if you are using dspace-rdf to export your repository content as RDF.
|
||||||
# Add iiif here, if you are using dspace-iiif.
|
# Add iiif here, if you are using dspace-iiif.
|
||||||
# Add orcidqueue here, if the integration with ORCID is configured and wish to enable the synchronization queue functionality
|
# Add orcidqueue here, if the integration with ORCID is configured and wish to enable the synchronization queue functionality
|
||||||
event.dispatcher.default.consumers = versioning, discovery, eperson, qaeventsdelete
|
event.dispatcher.default.consumers = versioning, discovery, eperson, submissionconfig, qaeventsdelete
|
||||||
|
|
||||||
# The noindex dispatcher will not create search or browse indexes (useful for batch item imports)
|
# The noindex dispatcher will not create search or browse indexes (useful for batch item imports)
|
||||||
event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher
|
event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher
|
||||||
@@ -826,6 +826,10 @@ event.consumer.iiif.filters = Item+Modify:Item+Modify_Metadata:Item+Delete:Item+
|
|||||||
event.consumer.orcidqueue.class = org.dspace.orcid.consumer.OrcidQueueConsumer
|
event.consumer.orcidqueue.class = org.dspace.orcid.consumer.OrcidQueueConsumer
|
||||||
event.consumer.orcidqueue.filters = Item+Install|Modify|Modify_Metadata|Delete|Remove
|
event.consumer.orcidqueue.filters = Item+Install|Modify|Modify_Metadata|Delete|Remove
|
||||||
|
|
||||||
|
# item submission config reload consumer
|
||||||
|
event.consumer.submissionconfig.class = org.dspace.submit.consumer.SubmissionConfigConsumer
|
||||||
|
event.consumer.submissionconfig.filters = Collection+Modify_Metadata
|
||||||
|
|
||||||
# ...set to true to enable testConsumer messages to standard output
|
# ...set to true to enable testConsumer messages to standard output
|
||||||
#testConsumer.verbose = true
|
#testConsumer.verbose = true
|
||||||
|
|
||||||
@@ -1407,19 +1411,6 @@ sitemap.dir = ${dspace.dir}/sitemaps
|
|||||||
# Defaults to "sitemaps", which means they are available at ${dspace.server.url}/sitemaps/
|
# Defaults to "sitemaps", which means they are available at ${dspace.server.url}/sitemaps/
|
||||||
# sitemap.path = sitemaps
|
# sitemap.path = sitemaps
|
||||||
|
|
||||||
#
|
|
||||||
# Comma-separated list of search engine URLs to 'ping' when a new Sitemap has
|
|
||||||
# been created. Include everything except the Sitemap URL itself (which will
|
|
||||||
# be URL-encoded and appended to form the actual URL 'pinged').
|
|
||||||
#
|
|
||||||
sitemap.engineurls = http://www.google.com/webmasters/sitemaps/ping?sitemap=
|
|
||||||
|
|
||||||
# Add this to the above parameter if you have an application ID with Yahoo
|
|
||||||
# (Replace REPLACE_ME with your application ID)
|
|
||||||
# http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=REPLACE_ME&url=
|
|
||||||
#
|
|
||||||
# No known Sitemap 'ping' URL for MSN/Live search
|
|
||||||
|
|
||||||
# Define cron for how frequently the sitemap should refresh.
|
# Define cron for how frequently the sitemap should refresh.
|
||||||
# Defaults to running daily at 1:15am
|
# Defaults to running daily at 1:15am
|
||||||
# Cron syntax is defined at https://www.quartz-scheduler.org/api/2.3.0/org/quartz/CronTrigger.html
|
# Cron syntax is defined at https://www.quartz-scheduler.org/api/2.3.0/org/quartz/CronTrigger.html
|
||||||
|
@@ -27,6 +27,7 @@ arks
|
|||||||
^Array$
|
^Array$
|
||||||
asterias
|
asterias
|
||||||
atomz
|
atomz
|
||||||
|
axios\/\d
|
||||||
BDFetch
|
BDFetch
|
||||||
Betsie
|
Betsie
|
||||||
baidu
|
baidu
|
||||||
@@ -45,6 +46,7 @@ BUbiNG
|
|||||||
bwh3_user_agent
|
bwh3_user_agent
|
||||||
CakePHP
|
CakePHP
|
||||||
celestial
|
celestial
|
||||||
|
centuryb
|
||||||
cfnetwork
|
cfnetwork
|
||||||
checklink
|
checklink
|
||||||
checkprivacy
|
checkprivacy
|
||||||
@@ -89,6 +91,7 @@ Embedly
|
|||||||
EThOS\+\(British\+Library\)
|
EThOS\+\(British\+Library\)
|
||||||
facebookexternalhit\/
|
facebookexternalhit\/
|
||||||
favorg
|
favorg
|
||||||
|
Faveeo\/\d
|
||||||
FDM(\s|\+)\d
|
FDM(\s|\+)\d
|
||||||
Feedbin
|
Feedbin
|
||||||
feedburner
|
feedburner
|
||||||
@@ -113,6 +116,7 @@ GLMSLinkAnalysis
|
|||||||
Goldfire(\s|\+)Server
|
Goldfire(\s|\+)Server
|
||||||
google
|
google
|
||||||
Grammarly
|
Grammarly
|
||||||
|
GroupHigh\/\d
|
||||||
grub
|
grub
|
||||||
gulliver
|
gulliver
|
||||||
gvfs\/
|
gvfs\/
|
||||||
@@ -121,16 +125,19 @@ heritrix
|
|||||||
holmes
|
holmes
|
||||||
htdig
|
htdig
|
||||||
htmlparser
|
htmlparser
|
||||||
|
HeadlessChrome
|
||||||
HttpComponents\/1.1
|
HttpComponents\/1.1
|
||||||
HTTPFetcher
|
HTTPFetcher
|
||||||
http.?client
|
http.?client
|
||||||
httpget
|
httpget
|
||||||
|
httpx
|
||||||
httrack
|
httrack
|
||||||
ia_archiver
|
ia_archiver
|
||||||
ichiro
|
ichiro
|
||||||
iktomi
|
iktomi
|
||||||
ilse
|
ilse
|
||||||
Indy Library
|
Indy Library
|
||||||
|
insomnia
|
||||||
^integrity\/\d
|
^integrity\/\d
|
||||||
internetseer
|
internetseer
|
||||||
intute
|
intute
|
||||||
@@ -140,6 +147,7 @@ iskanie
|
|||||||
jeeves
|
jeeves
|
||||||
Jersey\/\d
|
Jersey\/\d
|
||||||
jobo
|
jobo
|
||||||
|
Koha
|
||||||
kyluka
|
kyluka
|
||||||
larbin
|
larbin
|
||||||
libcurl
|
libcurl
|
||||||
@@ -161,10 +169,12 @@ LongURL.API
|
|||||||
ltx71
|
ltx71
|
||||||
lwp
|
lwp
|
||||||
lycos[_+]
|
lycos[_+]
|
||||||
|
MaCoCu
|
||||||
mail\.ru
|
mail\.ru
|
||||||
MarcEdit
|
MarcEdit
|
||||||
mediapartners-google
|
mediapartners-google
|
||||||
megite
|
megite
|
||||||
|
MetaInspector
|
||||||
MetaURI[\+\s]API\/\d\.\d
|
MetaURI[\+\s]API\/\d\.\d
|
||||||
Microsoft(\s|\+)URL(\s|\+)Control
|
Microsoft(\s|\+)URL(\s|\+)Control
|
||||||
Microsoft Office Existence Discovery
|
Microsoft Office Existence Discovery
|
||||||
@@ -190,6 +200,7 @@ nagios
|
|||||||
^NetAnts\/\d
|
^NetAnts\/\d
|
||||||
netcraft
|
netcraft
|
||||||
netluchs
|
netluchs
|
||||||
|
nettle
|
||||||
newspaper\/\d
|
newspaper\/\d
|
||||||
ng\/2\.
|
ng\/2\.
|
||||||
^Ning\/\d
|
^Ning\/\d
|
||||||
@@ -225,6 +236,7 @@ rambler
|
|||||||
ReactorNetty\/\d
|
ReactorNetty\/\d
|
||||||
Readpaper
|
Readpaper
|
||||||
redalert
|
redalert
|
||||||
|
RestSharp
|
||||||
Riddler
|
Riddler
|
||||||
robozilla
|
robozilla
|
||||||
rss
|
rss
|
||||||
@@ -252,7 +264,7 @@ T\-H\-U\-N\-D\-E\-R\-S\-T\-O\-N\-E
|
|||||||
tailrank
|
tailrank
|
||||||
Teleport(\s|\+)Pro
|
Teleport(\s|\+)Pro
|
||||||
Teoma
|
Teoma
|
||||||
The\+Knowledge\+AI
|
The[\+\s]Knowledge[\+\s]AI
|
||||||
titan
|
titan
|
||||||
^Traackr\.com$
|
^Traackr\.com$
|
||||||
Trello
|
Trello
|
||||||
@@ -302,6 +314,8 @@ yacy
|
|||||||
yahoo
|
yahoo
|
||||||
yandex
|
yandex
|
||||||
Yeti\/\d
|
Yeti\/\d
|
||||||
|
Zabbix
|
||||||
|
ZoteroTranslationServer
|
||||||
zeus
|
zeus
|
||||||
zyborg
|
zyborg
|
||||||
7siters
|
7siters
|
||||||
|
@@ -52,9 +52,11 @@
|
|||||||
<bean id="indexObjectFactoryFactory" class="org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactoryImpl"/>
|
<bean id="indexObjectFactoryFactory" class="org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactoryImpl"/>
|
||||||
|
|
||||||
<bean id="openURLTrackerLoggerServiceFactory" class="org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactoryImpl"/>
|
<bean id="openURLTrackerLoggerServiceFactory" class="org.dspace.statistics.export.factory.OpenURLTrackerLoggerServiceFactoryImpl"/>
|
||||||
|
|
||||||
<bean id="orcidServiceFactory" class="org.dspace.orcid.factory.OrcidServiceFactoryImpl"/>
|
<bean id="orcidServiceFactory" class="org.dspace.orcid.factory.OrcidServiceFactoryImpl"/>
|
||||||
|
|
||||||
<bean id="supervisionOrderServiceFactory" class="org.dspace.supervision.factory.SupervisionOrderServiceFactoryImpl"/>
|
<bean id="supervisionOrderServiceFactory" class="org.dspace.supervision.factory.SupervisionOrderServiceFactoryImpl"/>
|
||||||
|
|
||||||
|
<bean id="submissionServiceFactory" class="org.dspace.submit.factory.SubmissionServiceFactoryImpl"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -152,5 +152,8 @@
|
|||||||
|
|
||||||
<bean class="org.dspace.supervision.SupervisionOrderServiceImpl"/>
|
<bean class="org.dspace.supervision.SupervisionOrderServiceImpl"/>
|
||||||
|
|
||||||
|
<!-- Submission Config Service -->
|
||||||
|
<bean class="org.dspace.submit.service.SubmissionConfigServiceImpl"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|
||||||
|
@@ -87,9 +87,20 @@
|
|||||||
</analyzer>
|
</analyzer>
|
||||||
</fieldType>
|
</fieldType>
|
||||||
|
|
||||||
|
<fieldType name="long"
|
||||||
|
class="solr.LongPointField"
|
||||||
|
omitNorms="true"
|
||||||
|
positionIncrementGap="0"
|
||||||
|
docValues="true"/>
|
||||||
|
|
||||||
</types>
|
</types>
|
||||||
|
|
||||||
<fields>
|
<fields>
|
||||||
|
<field name="_version_"
|
||||||
|
type="long"
|
||||||
|
indexed="true"
|
||||||
|
stored="true"
|
||||||
|
multiValued="false"/>
|
||||||
<field name="id" type="string" multiValued="false" indexed="true" stored="true" required="true"/>
|
<field name="id" type="string" multiValued="false" indexed="true" stored="true" required="true"/>
|
||||||
<field name="field" type="string" multiValued="false" indexed="true" stored="true" required="true" />
|
<field name="field" type="string" multiValued="false" indexed="true" stored="true" required="true" />
|
||||||
<field name="email" type="string" multiValued="true" indexed="true" stored="true" required="false"/>
|
<field name="email" type="string" multiValued="true" indexed="true" stored="true" required="false"/>
|
||||||
|
Reference in New Issue
Block a user