diff --git a/.gitignore b/.gitignore index 2fcb46b9932c..b1722b445723 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ rebel.xml ## Ignore jenv configuration .java-version + +## Ignore mergetool backup files +*.orig diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/FilterMedia.java b/dspace-api/src/main/java/org/dspace/ctask/general/FilterMedia.java new file mode 100644 index 000000000000..a411bfbbd137 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/FilterMedia.java @@ -0,0 +1,105 @@ +package org.dspace.ctask.general; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.ArrayUtils; +import org.dspace.app.mediafilter.FormatFilter; +import org.dspace.app.mediafilter.factory.MediaFilterServiceFactory; +import org.dspace.app.mediafilter.service.MediaFilterService; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Constants; +import org.dspace.core.SelfNamedPlugin; +import org.dspace.core.factory.CoreServiceFactory; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; +import org.dspace.services.factory.DSpaceServicesFactory; + +/** + * Curation taks to apply media filters. Useful to execute this curation task as + * part of a submission workflow. + * + * @author agomez + */ +public class FilterMedia extends AbstractCurationTask { + + // Key (in dspace.cfg) which lists all enabled filters by name + private static final String MEDIA_FILTER_PLUGINS_KEY = "filter.plugins"; + + // Prefix (in dspace.cfg) for all filter properties + private static final String FILTER_PREFIX = "filter"; + + // Suffix (in dspace.cfg) for input formats supported by each filter + private static final String INPUT_FORMATS_SUFFIX = "inputFormats"; + + // The MediaFilterService + private MediaFilterService mediaFilterService = MediaFilterServiceFactory.getInstance().getMediaFilterService(); + + protected String result = null; + + // Static initializer + { + // Configure all enabled filters in the MediaFilterService + // Adapted from org.dspace.app.mediafilter.MediaFilterScript + String[] filterNames = DSpaceServicesFactory.getInstance().getConfigurationService().getArrayProperty(MEDIA_FILTER_PLUGINS_KEY); + + List filterList = new ArrayList<>(); + Map> filterFormats = new HashMap<>(); + + for (int i = 0; i < filterNames.length; i++) { + FormatFilter filter = (FormatFilter) CoreServiceFactory.getInstance().getPluginService().getNamedPlugin(FormatFilter.class, filterNames[i]); + filterList.add(filter); + String filterClassName = filter.getClass().getName(); + String pluginName = null; + if (SelfNamedPlugin.class.isAssignableFrom(filter.getClass())) { + pluginName = ((SelfNamedPlugin) filter).getPluginInstanceName(); + } + String[] formats = DSpaceServicesFactory.getInstance().getConfigurationService().getArrayProperty( + FILTER_PREFIX + "." + filterClassName + (pluginName != null ? "." + pluginName : "") + "." + INPUT_FORMATS_SUFFIX); + if (ArrayUtils.isNotEmpty(formats)) { + filterFormats.put(filterClassName + (pluginName != null ? MediaFilterService.FILTER_PLUGIN_SEPARATOR + pluginName : ""), + Arrays.asList(formats)); + } + } + mediaFilterService.setFilterFormats(filterFormats); + mediaFilterService.setFilterClasses(filterList); + } + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + if (dso instanceof Item) { + try { + if (mediaFilterService.filterItem(Curator.curationContext(), (Item) dso)) { + result = "Media filters succesfully applied on Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } else { + result = "No media filters applied on Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } catch (Exception e) { + result = "Failed to filter media on Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_FAIL; + } + } else { + result = "Skipping element that cannot be media filtered: " + dso.getID() + "[" + Constants.typeText[dso.getType()] + "]"; + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/FixJcis.java b/dspace-api/src/main/java/org/dspace/ctask/general/FixJcis.java new file mode 100644 index 000000000000..b6cafb0b9420 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/FixJcis.java @@ -0,0 +1,114 @@ +package org.dspace.ctask.general; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.MetadataFieldName; +import org.dspace.content.MetadataValue; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.CommunityService; +import org.dspace.content.service.ItemService; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; + +/** + * Curation task to fix the JCIS name + * + * @author agomez + */ +public class FixJcis extends AbstractCurationTask { + + private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService(); + + protected String result = null; + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + + List fields = new ArrayList(); + + fields.add(new MetadataFieldName("bs.edition.name")); + fields.add(new MetadataFieldName("dc.relation.ispartof")); + fields.add(new MetadataFieldName("bs.conference.name")); + fields.add(new MetadataFieldName("bs.proceedings.name")); + fields.add(new MetadataFieldName("dc.description")); + fields.add(new MetadataFieldName("dc.description.abstract")); + + try { + + for (MetadataFieldName field : fields) { + if (dso instanceof Item) { + ItemService service = itemService; + List values= service.getMetadata((Item) dso, field.schema, field.element, field.qualifier, Item.ANY); + if (!values.isEmpty()) { + service.removeMetadataValues(Curator.curationContext(), (Item) dso, values); + values.forEach(v -> { + try { + service.addMetadata(Curator.curationContext(), (Item) dso, field.schema, field.element, field.qualifier, null, + v.getValue().replaceAll("Jornadas de Ingeniería de Ciencia e Ingeniería de Servicios", + "Jornadas de Ciencia e Ingeniería de Servicios")); + } catch (SQLException e) { + report("An error occurred: " + e.getMessage()); + } + }); + } + } else if (dso instanceof Community) { + CommunityService service = communityService; + List values= service.getMetadata((Community) dso, field.schema, field.element, field.qualifier, Item.ANY); + if (!values.isEmpty()) { + service.removeMetadataValues(Curator.curationContext(), (Community) dso, values); + values.forEach(v -> { + try { + service.addMetadata(Curator.curationContext(), (Community) dso, field.schema, field.element, field.qualifier, null, + v.getValue().replaceAll("Jornadas de Ingeniería de Ciencia e Ingeniería de Servicios", + "Jornadas de Ciencia e Ingeniería de Servicios")); + } catch (SQLException e) { + report("An error occurred: " + e.getMessage()); + } + }); + } + } else if (dso instanceof Collection) { + CollectionService service = collectionService; + List values= service.getMetadata((Collection) dso, field.schema, field.element, field.qualifier, Item.ANY); + if (!values.isEmpty()) { + service.removeMetadataValues(Curator.curationContext(), (Collection) dso, values); + values.forEach(v -> { + try { + service.addMetadata(Curator.curationContext(), (Collection) dso, field.schema, field.element, field.qualifier, null, + v.getValue().replaceAll("Jornadas de Ingeniería de Ciencia e Ingeniería de Servicios", + "Jornadas de Ciencia e Ingeniería de Servicios")); + } catch (SQLException e) { + report("An error occurred: " + e.getMessage()); + } + }); + } + } else { + result = "Unsupported DSpaceObject type: " + dso.getClass().getName(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } + } catch (Exception e) { + result = "Failed rename attribute in DSpaceObject " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_FAIL; + } + result = "JCIS name succesfully fixed in DSpaceObject " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } +} diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MakeAdminOnly.java b/dspace-api/src/main/java/org/dspace/ctask/general/MakeAdminOnly.java new file mode 100644 index 000000000000..1c5a6a3191e3 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MakeAdminOnly.java @@ -0,0 +1,72 @@ +package org.dspace.ctask.general; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.factory.AuthorizeServiceFactory; +import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; + +/** + * Curation taks to make all {@link DSpaceObject}s private + * + * @author agomez + */ +public class MakeAdminOnly extends AbstractCurationTask { + + private ResourcePolicyService resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService(); + + protected String result = null; + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + if (dso instanceof Item) { + if (!((Item) dso).isArchived()) { + result = "Skipping not archived Item: " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } + try { + Context context = Curator.curationContext(); + resourcePolicyService.removePolicies(context, dso, Constants.READ); + if (dso instanceof Item) { + Item item = (Item) dso; + List bundles = new ArrayList(); + bundles.addAll(item.getBundles("ORIGINAL")); + bundles.addAll(item.getBundles("TEXT")); + bundles.addAll(item.getBundles("THUMBNAIL")); + for (Bundle bundle : bundles) { + resourcePolicyService.removePolicies(context, bundle, Constants.READ); + for (Bitstream bitstream: bundle.getBitstreams()) { + resourcePolicyService.removePolicies(context, bitstream, Constants.READ); + } + } + } + result = "DSpaceObject has been successfully made private only for Administrators: " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } catch (SQLException | AuthorizeException e) { + result = "Unable to change authorization policy for " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MakePublic.java b/dspace-api/src/main/java/org/dspace/ctask/general/MakePublic.java new file mode 100644 index 000000000000..084141da09a1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MakePublic.java @@ -0,0 +1,85 @@ +package org.dspace.ctask.general; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.authorize.factory.AuthorizeServiceFactory; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; +import org.dspace.eperson.Group; +import org.dspace.eperson.factory.EPersonServiceFactory; +import org.dspace.eperson.service.GroupService; + +/** + * Curation taks to make all {@link DSpaceObject}s public + * + * @author agomez + */ +public class MakePublic extends AbstractCurationTask { + + private ResourcePolicyService resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService(); + private AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService(); + private GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); + + protected String result = null; + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + if (dso instanceof Item) { + if (!((Item) dso).isArchived()) { + result = "Skipping not archived Item: " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } + try { + Context context = Curator.curationContext(); + Group anonymous = groupService.findByName(context, Group.ANONYMOUS); + resourcePolicyService.removePolicies(context, dso, Constants.READ); + if (dso instanceof Item) { + Item item = (Item) dso; + authorizeService.createResourcePolicy(context, dso, anonymous, null, Constants.READ, ResourcePolicy.TYPE_INHERITED); + List bundles = new ArrayList(); + bundles.addAll(item.getBundles("ORIGINAL")); + bundles.addAll(item.getBundles("TEXT")); + bundles.addAll(item.getBundles("THUMBNAIL")); + for (Bundle bundle : bundles) { + resourcePolicyService.removePolicies(context, bundle, Constants.READ); + authorizeService.createResourcePolicy(context, bundle, anonymous, null, Constants.READ, ResourcePolicy.TYPE_INHERITED); + for (Bitstream bitstream: bundle.getBitstreams()) { + resourcePolicyService.removePolicies(context, bitstream, Constants.READ); + authorizeService.createResourcePolicy(context, bitstream, anonymous, null, Constants.READ, null); + } + } + } else { + authorizeService.createResourcePolicy(context, dso, anonymous, null, Constants.READ, null); + } + result = "DSpaceObject has been successfully made public: " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } catch (SQLException | AuthorizeException e) { + result = "Unable to change authorization policy for " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/RegisterExternalHandle.java b/dspace-api/src/main/java/org/dspace/ctask/general/RegisterExternalHandle.java new file mode 100644 index 000000000000..a45bb2d13d0c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/RegisterExternalHandle.java @@ -0,0 +1,183 @@ +package org.dspace.ctask.general; + +import java.io.File; +import java.io.IOException; +import java.security.PrivateKey; +import java.text.MessageFormat; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.MetadataValue; +import org.dspace.content.Site; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.SiteService; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; + +import net.handle.hdllib.AbstractMessage; +import net.handle.hdllib.AbstractRequest; +import net.handle.hdllib.AbstractResponse; +import net.handle.hdllib.AdminRecord; +import net.handle.hdllib.CreateHandleRequest; +import net.handle.hdllib.DeleteHandleRequest; +import net.handle.hdllib.Encoder; +import net.handle.hdllib.HandleResolver; +import net.handle.hdllib.HandleValue; +import net.handle.hdllib.PublicKeyAuthenticationInfo; +import net.handle.hdllib.Util; + +/** + * Curation taks to register in an external Handle server + * the identifier stored in a specific DC property. + * + * Used by the Sistedes Digital Library, which uses "semantic" + * handles as a legacy decision + * + * @author agomez + */ +public class RegisterExternalHandle extends AbstractCurationTask { + + private static final Logger logger = LogManager.getLogger(RegisterExternalHandle.class); + + private static final String CONF_PREFIX = "prefix"; + private static final String CONF_KEY = "key"; + private static final String CONF_PASSWORD = "password"; + private static final String CONF_PROPERTY = "property"; + private static final String CONF_FORCE = "force"; + + private CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService(); + private SiteService siteService = ContentServiceFactory.getInstance().getSiteService(); + + protected String result = null; + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + + String prefix = taskProperty(CONF_PREFIX, configurationService.getProperty("handle.prefix")); + File keyFile = new File(taskProperty(CONF_KEY, "admpriv.bin")); + String password = taskProperty(CONF_PASSWORD, ""); + String property = taskProperty(CONF_PROPERTY, "dc.identifier.uri"); + boolean force = taskBooleanProperty(CONF_FORCE, false); + + if (StringUtils.isEmpty(dso.getHandle())) { + result = "DSpaceObject " + dso.getID() + " does not have a permanent Handle yet, skipping...: "; + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + + if (!keyFile.exists()) { + result = "Key file " + keyFile.getAbsolutePath() + " to authenticate in prefix " + prefix + " does not exist"; + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + + PublicKeyAuthenticationInfo auth; + try { + auth = getAuth(prefix, keyFile, password); + } catch (Exception e) { + result = "Unable to load authentication key on prefix " + prefix + ". Maybe wrong password?"; + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + + List metadataList; + if (dso instanceof Item) { + metadataList = itemService.getMetadataByMetadataString((Item) dso, property); + } else if (dso instanceof Community) { + metadataList = communityService.getMetadataByMetadataString((Community) dso, property); + } else if (dso instanceof Collection) { + metadataList = collectionService.getMetadataByMetadataString((Collection) dso, property); + } else if (dso instanceof Site) { + metadataList = siteService.getMetadataByMetadataString((Site) dso, property); + } else { + result = "Unsupported DSpaceObject type: " + dso.getClass().getName(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + + if (metadataList.isEmpty()) { + result = "No metadata property " + property + " found for " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + + try { + for (MetadataValue sistedesIdMetadata : metadataList) { + if (!sistedesIdMetadata.getValue().startsWith(prefix + "/")) { + report("Handle " + sistedesIdMetadata.getValue() + " does not reside in prefix " + prefix + ". Skiping." ); + continue; + } + registerHandleMapping(dso, prefix, sistedesIdMetadata.getValue(), auth, force); + } + result = "Sistedes Handles succesfully registered for " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } catch (Exception e) { + result = "Failed to register external Handle for " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_FAIL; + } + } + + private void registerHandleMapping(DSpaceObject object, String externalPrefix, String externalHandle, PublicKeyAuthenticationInfo auth, boolean force) + throws Exception { + String targetUrl = handleService.getCanonicalForm(object.getHandle()); + logger.debug(MessageFormat.format("Creating handle ''{0}'' -> ''{1}''", externalHandle, object.getHandle())); + HandleResolver resolver = new HandleResolver(); + int timestamp = (int) (System.currentTimeMillis() / 1000); + + HandleValue urlVal = new HandleValue(1, Util.encodeString("URL"), Util.encodeString(targetUrl), HandleValue.TTL_TYPE_RELATIVE, 86400, timestamp, null, + true, true, true, false); + + if (force) { + AbstractRequest request = new DeleteHandleRequest(Util.encodeString(externalHandle), auth); + request.authoritative = true; + if (resolver.processRequest(request).responseCode != AbstractMessage.RC_SUCCESS) { + logger.error(MessageFormat.format("Unable to delete existing Handle for {0}", object.getHandle())); + } + } + + AdminRecord adminRecord = new AdminRecord(Util.encodeString("0.NA/" + externalPrefix), 300, true, true, true, true, true, true, true, true, true, true, + true, true); + HandleValue[] values = { urlVal, new HandleValue(100, Util.encodeString("HS_ADMIN"), Encoder.encodeAdminRecord(adminRecord), + HandleValue.TTL_TYPE_RELATIVE, 86400, timestamp, null, true, true, true, false) }; + AbstractRequest request = new CreateHandleRequest(Util.encodeString(externalHandle), values, auth); + + AbstractResponse response = resolver.processRequest(request); + if (response.responseCode == AbstractMessage.RC_SUCCESS) { + logger.info(MessageFormat.format("Created handle ''{0}'' -> ''{1}''", externalHandle, object.getHandle())); + } else { + throw new Exception("Unable to create external handle " + externalHandle + " for " + object.getHandle()); + } + } + + private static PublicKeyAuthenticationInfo getAuth(String prefix, File keyFile, String password) throws Exception { + byte key[] = IOUtils.toByteArray(keyFile.toURI()); + PrivateKey privkey = null; + if (Util.requiresSecretKey(key) && StringUtils.isBlank(password)) { + throw new Exception(MessageFormat.format("Private key in ''{0}'' requires a password", keyFile)); + } + key = Util.decrypt(key, password.getBytes()); + privkey = Util.getPrivateKeyFromBytes(key, 0); + return new PublicKeyAuthenticationInfo(Util.encodeString("0.NA/" + prefix), 300, privkey); + } +} diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/RenameMetadataAttribute.java b/dspace-api/src/main/java/org/dspace/ctask/general/RenameMetadataAttribute.java new file mode 100644 index 000000000000..62552ed13656 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/RenameMetadataAttribute.java @@ -0,0 +1,92 @@ +package org.dspace.ctask.general; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.MetadataFieldName; +import org.dspace.content.MetadataValue; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; + +/** + * Curation task to move the value of one metadata field to another + * + * @author agomez + */ +public class RenameMetadataAttribute extends AbstractCurationTask { + + private static final String CONF_SOURCE = "source"; + private static final String CONF_TARGET = "target"; + private static final String CONF_LANGUAGE = "language"; + + protected String result = null; + + protected String taskProperty(String name, String defaultValue) { + return super.taskProperty(name) != null ? super.taskProperty(name) : defaultValue; + } + + @Override + public int perform(DSpaceObject dso) throws IOException { + + String source = taskProperty(CONF_SOURCE); + String target = taskProperty(CONF_TARGET); + String language = taskProperty(CONF_LANGUAGE, Item.ANY); + + if (StringUtils.isEmpty(source)) { + result = "No source metadata attribute specified!"; + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + + if (StringUtils.isEmpty(target)) { + result = "No target metadata attribute specified!"; + setResult(result); + report(result); + return Curator.CURATE_ERROR; + } + + if (dso instanceof Item) { + MetadataFieldName sourceField = new MetadataFieldName(source); + MetadataFieldName targetField = new MetadataFieldName(target); + try { + Item item = (Item) dso; + List values = itemService.getMetadata(item, sourceField.schema, sourceField.element, sourceField.qualifier, language); + if (!values.isEmpty()) { + values.forEach(v -> { + try { + itemService.addMetadata(Curator.curationContext(), item, targetField.schema, targetField.element, targetField.qualifier, v.getLanguage(), v.getValue()); + } catch (SQLException e) { + report("An error occurred: " + e.getMessage()); + } + }); + itemService.clearMetadata(Curator.curationContext(), item, sourceField.schema, sourceField.element, sourceField.qualifier, language); + result = "Attribute succesfully renamed in Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SUCCESS; + } else { + result = "Source attribute not found in Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } catch (Exception e) { + result = "Failed rename attribute in Item " + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_FAIL; + } + + } else { + result = "Skipping non-Item element" + dso.getID(); + setResult(result); + report(result); + return Curator.CURATE_SKIP; + } + } +} diff --git a/dspace/config/default.license b/dspace/config/default.license index 390e9786688d..93cddeaac0dc 100644 --- a/dspace/config/default.license +++ b/dspace/config/default.license @@ -1,18 +1,11 @@ -NOTE: PLACE YOUR OWN LICENSE HERE -This sample license is provided for informational purposes only. - -NON-EXCLUSIVE DISTRIBUTION LICENSE - -By signing and submitting this license, you (the author(s) or copyright owner) grants to DSpace University (DSU) the non-exclusive right to reproduce, translate (as defined below), and/or distribute your submission (including the abstract) worldwide in print and electronic format and in any medium, including but not limited to audio or video. - -You agree that DSU may, without changing the content, translate the submission to any medium or format for the purpose of preservation. - -You also agree that DSU may keep more than one copy of this submission for purposes of security, back-up and preservation. - -You represent that the submission is your original work, and that you have the right to grant the rights contained in this license. You also represent that your submission does not, to the best of your knowledge, infringe upon anyone's copyright. - -If the submission contains material for which you do not hold copyright, you represent that you have obtained the unrestricted permission of the copyright owner to grant DSU the rights required by this license, and that such third-party owned material is clearly identified and acknowledged within the text or content of the submission. - -IF THE SUBMISSION IS BASED UPON WORK THAT HAS BEEN SPONSORED OR SUPPORTED BY AN AGENCY OR ORGANIZATION OTHER THAN DSU, YOU REPRESENT THAT YOU HAVE FULFILLED ANY RIGHT OF REVIEW OR OTHER OBLIGATIONS REQUIRED BY SUCH CONTRACT OR AGREEMENT. - -DSU will clearly identify your name(s) as the author(s) or owner(s) of the submission, and will not make any alteration, other than as allowed by this license, to your submission. +

Al realizar este envío, Usted acepta y acuerda estar obligado por los términos y condiciones de la + Licencia Internacional Pública +de Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 de Creative Commons ("Licencia Pública"). +En la medida en que esta Licencia Pública pueda ser interpretada como un contrato, a Usted se le otorgan +los Derechos Licenciados en consideración a su aceptación de estos términos y condiciones, y el Licenciante +le concede a Usted tales derechos en consideración a los beneficios que el Licenciante recibe por poner +a disposición el Material Licenciado bajo estos términos y condiciones.

+ +

Usted puede consultar los terminos de la licencia completos que está aceptando en Licencia Internacional Pública +de Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 de Creative Commons.

\ No newline at end of file diff --git a/dspace/config/entities/sistedes-relationship.xml b/dspace/config/entities/sistedes-relationship.xml new file mode 100644 index 000000000000..87c236b692d2 --- /dev/null +++ b/dspace/config/entities/sistedes-relationship.xml @@ -0,0 +1,58 @@ + + + + + + + Artículo + Autor + isAuthorOfPaper + isPaperOfAuthor + + 0 + + + 0 + + true + + + Resumen + Autor + isAuthorOfAbstract + isAbstractOfAuthor + + 0 + + + 0 + + true + + + Seminario + Autor + isAuthorOfSeminar + isSeminarOfAuthor + + 0 + + + 0 + + true + + + Boletín + Autor + isAuthorOfBulletin + isBulletinOfAuthor + + 0 + + + 0 + + true + + diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index b5278d2f3d87..4f1e8c6ced4a 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -63,7 +63,7 @@ - + --> - + + + + + + @@ -254,6 +259,34 @@ duplicates + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.steptwo + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.steptwo + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.CClicense + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + @@ -419,6 +452,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/modules/curate.cfg b/dspace/config/modules/curate.cfg index 1d7b87960df1..7eacac7600cc 100644 --- a/dspace/config/modules/curate.cfg +++ b/dspace/config/modules/curate.cfg @@ -17,6 +17,15 @@ plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.MetadataV plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.RegisterDOI = registerdoi #plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.CitationPage = citationpage # add new tasks here (or in additional config files) +# BEGIN: Sistedes +plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.RegisterExternalHandle = registerexternalhandle +plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.FilterMedia = filtermedia +plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.RenameMetadataAttribute = renamemetadataattribute +plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.MakeAdminOnly = makeadmin +plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.MakePublic = makepublic +# This should be no longer needed: +#plugin.named.org.dspace.curate.CurationTask = org.dspace.ctask.general.FixJcis = fixjcis +# END: Sistedes ## task queue implementation plugin.single.org.dspace.curate.TaskQueue = org.dspace.curate.FileTaskQueue diff --git a/dspace/config/modules/registerexternalhandle.cfg b/dspace/config/modules/registerexternalhandle.cfg new file mode 100644 index 000000000000..a16672f2664e --- /dev/null +++ b/dspace/config/modules/registerexternalhandle.cfg @@ -0,0 +1,25 @@ +#---------------------------------------------------------------# +#---------- Register External Handles Configurations -----------# +#---------------------------------------------------------------# +# Configuration properties used to register Handles in # +# an external server. Implemented for the Sistedes Digital # +# Library. # +#---------------------------------------------------------------# + +# Prefix of the external Handle server, if different of the Site's prefix (i.e., 'handle.prefix' property) +# registerexternalhandle.prefix = 12345678 + +# Path of the adminpriv.bin key file +# registerexternalhandle.key = admpriv.bin + +# Password to decrypt the key file +# Leave empty or unset for unencyprted key files +# registerexternalhandle.password = keypassword + +# FQN of the property that contains the Handle to be created in the external service +# Defaults to 'dc.identifier.uri' +# registerexternalhandle.property = dc.identifier.uri + +# Delete existing Handles before creating a new one +# Defaults to false +# registerexternalhandle.force = false diff --git a/dspace/config/registries/sistedes-types.xml b/dspace/config/registries/sistedes-types.xml new file mode 100644 index 000000000000..b690d25f012b --- /dev/null +++ b/dspace/config/registries/sistedes-types.xml @@ -0,0 +1,212 @@ + + + + Sistedes Types Registry + Abel Gómez + + + + bs + https://biblioteca.sistedes.es/Conference + + + + + dc + identifier + sistedes + Manually assigned identifier in the context of Sistedes. It must be a handle in the 11705 prefix. + + + + dc + contributor + signature + Signature of the author, as specified in the publication. It may differ from 'dc.author.name' due to 'name variants'. + + + + dc + contributor + email + Author e-mail, as specified in the publication (if any). + + + + dc + contributor + affiliation + Author affiliation, as specified in the publication. + + + + dc + contributor + bio + Author biography, as specified in the publication (if any). It may be used in publications such as seminars, or keynotes, where the biography of the author at a given moment is relevant. + + + + + person + web + + Personal web page. + + + + + bs + conference + name + Name of the conference in which the publication was presented. + + + + bs + conference + acronym + Acronym of the conference in which the publication was presented. + + + + bs + edition + name + Full name of the edition in which the publication was presented. + + + + bs + edition + date + Full date of the edition in which the publication was presented. + + + + bs + edition + location + City where the edition in which the publication was presented was held. + + + + bs + proceedings + editor + Editor of the proceedings in which the publication was published. + + + + bs + proceedings + name + Full name of the proceedings in which the publication was published. + + + + + relation + isAuthorOfPaper + (Sistedes specific) Contains all uuids of the "latest" AUTHORS that the current PAPER links to via a relationship. In other words, this stores all relationships pointing from the current PAPER to any AUTHOR where the AUTHOR is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isAuthorOfPaper + latestForDiscovery + (Sistedes specific) Contains all uuids of AUTHORS which link to the current PAPER via a "latest" relationship. In other words, this stores all relationships pointing to the current PAPER from an AUTHOR, implying that the PAPER is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isPaperOfAuthor + (Sistedes specific) Contains all uuids of the "latest" PAPERS that the current AUTHOR links to via a relationship. In other words, this stores all relationships pointing from the current AUTHOR to any PAPER where the PAPER is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isPaperOfAuthor + latestForDiscovery + (Sistedes specific) Contains all uuids of PAPERS which link to the current AUTHOR via a "latest" relationship. In other words, this stores all relationships pointing to the current AUTHOR from a PAPER, implying that the AUTHOR is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isAuthorOfAbstract + (Sistedes specific) Contains all uuids of the "latest" AUTHORS that the current ABSTRACT links to via a relationship. In other words, this stores all relationships pointing from the current ABSTRACT to any AUTHOR where the AUTHOR is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isAuthorOfAbstract + latestForDiscovery + (Sistedes specific) Contains all uuids of AUTHORS which link to the current ABSTRACT via a "latest" relationship. In other words, this stores all relationships pointing to the current ABSTRACT from an AUTHOR, implying that the ABSTRACT is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + + relation + isAbstractOfAuthor + (Sistedes specific) Contains all uuids of the "latest" ABSTRACTS that the current AUTHOR links to via a relationship. In other words, this stores all relationships pointing from the current AUTHOR to any ABSTRACT where the ABSTRACT is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isAbstractOfAuthor + latestForDiscovery + (Sistedes specific) Contains all uuids of ABSTRACTS which link to the current AUTHOR via a "latest" relationship. In other words, this stores all relationships pointing to the current AUTHOR from a ABSTRACT, implying that the AUTHOR is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isAuthorOfSeminar + (Sistedes specific) Contains all uuids of the "latest" AUTHORS that the current SEMINAR links to via a relationship. In other words, this stores all relationships pointing from the current SEMINAR to any AUTHOR where the AUTHOR is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isAuthorOfSeminar + latestForDiscovery + (Sistedes specific) Contains all uuids of AUTHORS which link to the current SEMINAR via a "latest" relationship. In other words, this stores all relationships pointing to the current SEMINAR from an AUTHOR, implying that the SEMINAR is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isSeminarOfAuthor + (Sistedes specific) Contains all uuids of the "latest" SEMINARS that the current AUTHOR links to via a relationship. In other words, this stores all relationships pointing from the current AUTHOR to any SEMINAR where the SEMINAR is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isSeminarOfAuthor + latestForDiscovery + (Sistedes specific) Contains all uuids of SEMINARS which link to the current AUTHOR via a "latest" relationship. In other words, this stores all relationships pointing to the current AUTHOR from a SEMINAR, implying that the AUTHOR is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isAuthorOfBulletin + (Sistedes specific) Contains all uuids of the "latest" AUTHORS that the current BULLETIN links to via a relationship. In other words, this stores all relationships pointing from the current BULLETIN to any AUTHOR where the AUTHOR is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isAuthorOfBulletin + latestForDiscovery + (Sistedes specific) Contains all uuids of AUTHORS which link to the current BULLETIN via a "latest" relationship. In other words, this stores all relationships pointing to the current BULLETIN from an AUTHOR, implying that the BULLETIN is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + + + relation + isBulletinOfAuthor + (Sistedes specific) Contains all uuids of the "latest" BULLETINS that the current AUTHOR links to via a relationship. In other words, this stores all relationships pointing from the current AUTHOR to any BULLETIN where the BULLETIN is marked as "latest". Internally used by DSpace. Do not manually add, remove or edit values. + + + + relation + isBulletinOfAuthor + latestForDiscovery + (Sistedes specific) Contains all uuids of BULLETINS which link to the current AUTHOR via a "latest" relationship. In other words, this stores all relationships pointing to the current AUTHOR from a BULLETIN, implying that the AUTHOR is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. + + diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 92917818132e..4de6c814ddad 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -136,6 +136,19 @@ + + + + + + + + + + + + + @@ -206,6 +219,12 @@ + + + + + + @@ -388,6 +407,12 @@ + + + + + + @@ -527,6 +552,12 @@ + + + + + + @@ -673,6 +704,12 @@ + + + + + + @@ -1429,6 +1466,669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND entityType_keyword:Autor + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND latestVersion:true AND entityType_keyword:Autor + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND latestVersion:true AND entityType_keyword:Artículo + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND entityType_keyword:Artículo + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND latestVersion:true AND entityType_keyword:Resumen + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND entityType_keyword:Resumen + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND latestVersion:true AND entityType_keyword:Seminario + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND entityType_keyword:Seminario + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND latestVersion:true AND entityType_keyword:Boletín + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:Item AND entityType_keyword:Boletín + -withdrawn:true AND -discoverable:false + + + + + + + + + + + + + + + + + + + @@ -2508,6 +3208,53 @@ + + + + + + relation.isAuthorOfPaper.latestForDiscovery + + + + + + + + + + + relation.isAuthorOfAbstract.latestForDiscovery + + + + + + + + + + + + relation.isAuthorOfSeminar.latestForDiscovery + + + + + + + + + + + relation.isAuthorOfBulletin.latestForDiscovery + + + + + + + @@ -2576,7 +3323,7 @@ dspace.entity.type - + @@ -2782,6 +3529,53 @@ + + + + + + relation.isPaperOfAuthor.latestForDiscovery + + + + + + + + + + relation.isAbstractOfAuthor.latestForDiscovery + + + + + + + + + + relation.isSeminarOfAuthor.latestForDiscovery + + + + + + + + + + relation.isBulletinOfAuthor.latestForDiscovery + + + + + + + diff --git a/dspace/config/spring/api/virtual-metadata.xml b/dspace/config/spring/api/virtual-metadata.xml index dee96eca7c0c..524c97195f56 100644 --- a/dspace/config/spring/api/virtual-metadata.xml +++ b/dspace/config/spring/api/virtual-metadata.xml @@ -21,6 +21,12 @@ + + + + + + @@ -31,6 +37,12 @@ + + + + + + @@ -254,4 +266,78 @@ + + + + + + + + + person.familyName + person.givenName + organization.legalName + + + + , + + + + + + + + + + + + person.familyName + person.givenName + organization.legalName + + + + , + + + + + + + + + + + + person.familyName + person.givenName + organization.legalName + + + + , + + + + + + + + + + + + person.familyName + person.givenName + organization.legalName + + + + , + + + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index a93195c91f77..b2dc30530155 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1348,6 +1348,363 @@ + +
+ + + person + givenName + + onebox + Introduzca el nombre del autor + + + + + person + familyName + + onebox + Introduzca los apellidos del autor + + + + + person + affiliation + name + true + + onebox + Introduzca la afiliación de este autor + + + + + person + email + + onebox + Introduzca el e-mail del autor + + + + + person + identifier + orcid + + onebox + Introduzca el ORCID del autor + + + +
+ +
+ + + isAuthorOfSeminar + author + true + + Seleccione un autor de los autores registrados en la Biblioteca. + Debe seleccionar un autor de los autores registrados en la Biblioteca. No puede especificar su nombre como texto en esta casilla directamente. + workflow + + + + + + dc + contributor + signature + true + + onebox + Introduzca el nombre del autor en la forma "Apellidos, Nombre" + Los seminarios han de tener al menos un autor, escrito en la forma "Apellidos, Nombre" + .*,.* + + + dc + contributor + affiliation + true + + onebox + Introduzca la afiliación de este autor + Los autores han de tener una afiliación + + + dc + contributor + email + true + + onebox + Introduzca el e-mail del autor + Los autores han de tener un e-mail + + + + + dc + contributor + bio + false + + textarea + Introduzca una breve nota bibliográfica sobre el autor. + + + +
+
+ + + dc + title + + false + + onebox + + Introduzca el título del seminario. + Los seminarios deben tener un título. + + + dc + identifier + sistedes + false + + onebox + + Indique un handle público en la forma 11705/SEM/SEMXXX (donde XXX es el número de seminario) como identificador en la Biblioteca Digital de Sistedes. + 11705/SEM/SEM[0-9]{3} + Se require un handle como identificador público en Sistedes. + workflow + readonly + + + + + dc + description + abstract + false + + textarea + Introduzca un resumen del seminario. + + + + + + dc + subject + + true + + onebox + + Especifique las palabras clave. + + + + dc + date + issued + false + + date + Indique la fecha de celebración del seminario. + Indique una fecha válida. + + + + + dc + publisher + + false + + dropdown + Indique quién publica el seminario. + Los seminarios deben incluir Sistedes como publicador. + + + dc + relation + ispartof + false + + + dropdown + Indique a qué serie de eventos de Sistedes pertenece el seminario. + Los seminarios deben formar parte de los Seminarios Sistedes. + + +
+
+ + + dc + title + + false + + onebox + + Introduzca el título del boletín. + Los boletines deben tener un título. + + + + dc + identifier + sistedes + false + + onebox + + Indique un handle público en la forma 11705/BOLETIN/YYYY/XXX (donde YYYY es el año y XXX es el número de boletín) como identificador en la Biblioteca Digital de Sistedes. + 11705/BOLETIN/20[0-9]{2}/[0-9]{3} + Se require un handle como identificador público en Sistedes. + workflow + readonly + + + + + dc + description + abstract + false + + textarea + Introduzca un resumen del seminario. + + + + + + dc + subject + + true + + onebox + + Especifique las palabras clave. + + + + dc + date + issued + false + + date + Indique la fecha de publicación del boletín. + Indique una fecha y hora válidas. + + + + + dc + publisher + + false + + dropdown + Indique quién publica el boletín. + Los boletines deben incluir Sistedes como publicador. + + + dc + relation + ispartof + false + + + dropdown + Indique a qué colección de documentos de Sistedes pertenece el boletín. + Los boletines deben formar parte de los Boletines de Sistedes. + + +
+
+ + + dc + rights + license + false + + dropdown + Indique la licencia. + Es necesario especificar una licencia + + + dc + rights + uri + false + + dropdown + Indique una URI para la licencia + Es necesario especificar la URI de la licencia + + +
+ + @@ -1985,7 +2342,38 @@ FundingOrganization - + + + + Sistedes + Sistedes + + + + + Seminarios Sistedes + Seminarios Sistedes + + + + + Boletines Sistedes + Boletines Sistedes + + + + + Atribución-NoComercial-SinDerivadas 4.0 Internacional (CC BY-NC-ND 4.0) + CC BY-NC-ND 4.0 + + + + + https://creativecommons.org/licenses/by-nc-nd/4.0/ + https://creativecommons.org/licenses/by-nc-nd/4.0/ + + + diff --git a/dspace/config/workflow-curation.xml b/dspace/config/workflow-curation.xml index 89cfd5309f2a..04608c770daa 100644 --- a/dspace/config/workflow-curation.xml +++ b/dspace/config/workflow-curation.xml @@ -9,7 +9,12 @@ + + + + @@ -62,7 +67,7 @@ - + @@ -74,6 +79,18 @@ + + + + + $siteadmin + $siteadmin + $siteadmin + + + + + diff --git a/dspace/modules/server-boot/pom.xml b/dspace/modules/server-boot/pom.xml index 019d019088c6..4f3a987e95d5 100644 --- a/dspace/modules/server-boot/pom.xml +++ b/dspace/modules/server-boot/pom.xml @@ -100,7 +100,12 @@ lucene-analyzers-icu test - + + + org.antlr + antlr4-runtime + 4.13.0 + diff --git a/utility-scripts/download-dbip-city-lite.sh b/utility-scripts/download-dbip-city-lite.sh new file mode 100755 index 000000000000..2dd1d30693ff --- /dev/null +++ b/utility-scripts/download-dbip-city-lite.sh @@ -0,0 +1,10 @@ +#! /bin/bash + +year=`date +'%Y'` +month=`date +'%m'` +target="/opt/dbip-city-lite" +outgz="$target/dbip-city-lite.mmdb.gz" + +mkdir -p $target +wget -O $outgz "https://download.db-ip.com/free/dbip-city-lite-$year-$month.mmdb.gz" +gunzip $outgz \ No newline at end of file diff --git a/utility-scripts/dspace-clear.sh b/utility-scripts/dspace-clear.sh new file mode 100755 index 000000000000..89fb3d90eff4 --- /dev/null +++ b/utility-scripts/dspace-clear.sh @@ -0,0 +1,14 @@ +#! /bin/bash + +server="/opt/dspace.server" + +systemctl stop tomcat9.service +sudo -u postgres psql --username=postgres dspace -c "DROP EXTENSION pgcrypto CASCADE;" +yes | $server/bin/dspace database clean +sudo -u postgres psql --username=postgres dspace -c "CREATE EXTENSION pgcrypto;" +rm -rf $server/assetstore/* +/opt/dspace-fix-permissions.sh +"$server/bin/dspace" initialize-entities -f "$server/config/entities/sistedes-relationship.xml" +/opt/dspace-create-admin.sh +systemctl start tomcat9.service + diff --git a/utility-scripts/dspace-convert-to-dev.sh b/utility-scripts/dspace-convert-to-dev.sh new file mode 100755 index 000000000000..f14c08cd699e --- /dev/null +++ b/utility-scripts/dspace-convert-to-dev.sh @@ -0,0 +1,53 @@ +#! /bin/bash + +prodsite=biblioteca.sistedes.es +devsite=bdsistedes.dsic.upv.es +cookies=/tmp/bdcookies.tmp +headers=/tmp/bdheaders.tmp +user=USER_EMAIL +password=USER_PASSWORD + +sed -i "s/$prodsite/$devsite/g" /opt/dspace.ui/config/config.prod.yml +sed -i "s/$prodsite/$devsite/g" /opt/dspace.server/config/local.cfg + +function get_header() { + cat /tmp/bdheaders.tmp | grep $1 | cut -d ':' -f2 | xargs +} + +curl --silent \ + --output /dev/null \ + --cookie-jar $cookies \ + --dump-header $headers \ + 'http://localhost:8080/dspace.server/api/' + +token=$(get_header DSPACE-XSRF-TOKEN) + +curl --silent \ + --output /dev/null \ + --cookie $cookies \ + --cookie-jar $cookies \ + --dump-header $headers \ + 'http://localhost:8080/dspace.server/api/authn/login' \ + -H "X-XSRF-TOKEN: $token" \ + --data-urlencode "user=$user" \ + --data-urlencode "password=$password" + +token=$(get_header DSPACE-XSRF-TOKEN) +auth=$(get_header Authorization) + +curl --silent \ + --output /dev/null \ + --cookie $cookies \ + --cookie-jar $cookies \ + --dump-header $headers \ + -X PUT \ + 'http://localhost:8080/dspace.server/api/system/systemwidealerts/1' \ + -H "Content-Type: application/json" \ + -H "X-XSRF-TOKEN: $token" \ + -H "Authorization: $auth" \ + --data '{ "message": "Este es un sitio de desarrollo y pruebas", "countdownTo": null, "allowSessions": "all", "active": true }' + +rm -rf $cookies $headers + +systemctl restart tomcat9.service +pm2 restart all diff --git a/utility-scripts/dspace-create-admin.sh b/utility-scripts/dspace-create-admin.sh new file mode 100755 index 000000000000..14837560d600 --- /dev/null +++ b/utility-scripts/dspace-create-admin.sh @@ -0,0 +1,22 @@ +#!/usr/bin/expect -f + +set server /opt/dspace.server +set email HERE_THE_EMAIL +set password HERE_THE_PASSWORD + +set timeout -1 +spawn $server/bin/dspace create-administrator +match_max 100000 +expect "E-mail address: " +send -- "$email\r" +expect "First name: " +send -- "Biblioteca Digital\r" +expect "Last name: " +send -- "Sistedes\r" +expect "Is the above data correct? (y or n): " +send -- "y\r" +expect "Password: " +send -- "$password\r" +expect "Again to confirm: " +send -- "$password\r" +expect eof diff --git a/utility-scripts/dspace-fix-permissions.sh b/utility-scripts/dspace-fix-permissions.sh new file mode 100755 index 000000000000..e80ad0d96eef --- /dev/null +++ b/utility-scripts/dspace-fix-permissions.sh @@ -0,0 +1,16 @@ +# Fix solr permissions +chown -R solr:solr /var/solr/data/configsets + +# Fix server permissions +# Tomcat must be configured first using `systemctl edit tomcat9.service` as: +# +# [Service] +# ReadWritePaths=/opt/dspace-server +# Environment='UMASK=002' +server=/opt/dspace.server + +chmod g+x -R $server/bin +find $server -type d -exec chmod g+s {} \; +find $server -type f -exec chmod g-s {} \; +chmod ug+w -R $server +chown dspace:tomcat -R $server diff --git a/utility-scripts/dspace-redeploy-ui.sh b/utility-scripts/dspace-redeploy-ui.sh new file mode 100755 index 000000000000..3626665fcac9 --- /dev/null +++ b/utility-scripts/dspace-redeploy-ui.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +sourceui=/root/git/dspace.ui +ui=/opt/dspace.ui + +pushd $sourceui +yarn merge-i18n -s src/themes/sistedes/assets/i18n +yarn build:prod +popd + +mkdir -p $ui/dist +rm -rf $ui/dist/* +cp -r $sourceui/dist $ui + +pushd $ui +pm2 stop dspace.ui +pm2 start dspace.ui.json +pm2 save +popd