diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d63f45982c1..39a6f41429fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,7 +49,7 @@ jobs: # https://github.com/actions/setup-java - name: Install JDK ${{ matrix.java }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: 'temurin' @@ -65,14 +65,14 @@ jobs: # (This artifact is downloadable at the bottom of any job's summary page) - name: Upload Results of ${{ matrix.type }} to Artifact if: ${{ failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.type }} results path: ${{ matrix.resultsdir }} # Upload code coverage report to artifact, so that it can be shared with the 'codecov' job (see below) - name: Upload code coverage report to Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.type }} coverage report path: 'dspace/target/site/jacoco-aggregate/jacoco.xml' @@ -91,7 +91,7 @@ jobs: # Download artifacts from previous 'tests' job - name: Download coverage artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 # Now attempt upload to Codecov using its action. # NOTE: We use a retry action to retry the Codecov upload if it fails the first time. @@ -101,10 +101,11 @@ jobs: - name: Upload coverage to Codecov.io uses: Wandalen/wretry.action@v1.3.0 with: - action: codecov/codecov-action@v3 + action: codecov/codecov-action@v4 # Ensure codecov-action throws an error when it fails to upload with: | fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} # Try re-running action 5 times max attempt_limit: 5 # Run again in 30 seconds diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml index 2a5abfceb1d8..3a563c6fa39c 100644 --- a/.github/workflows/codescan.yml +++ b/.github/workflows/codescan.yml @@ -39,7 +39,7 @@ jobs: # https://github.com/actions/setup-java - name: Install JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: 'temurin' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9f1e407cff4b..a9ff8760e763 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -43,7 +43,7 @@ jobs: needs: dspace-dependencies uses: ./.github/workflows/reusable-docker-build.yml with: - build_id: dspace + build_id: dspace-prod image_name: dspace/dspace dockerfile_path: ./Dockerfile secrets: @@ -120,7 +120,7 @@ jobs: if: github.repository == 'dspace/dspace' uses: ./.github/workflows/reusable-docker-build.yml with: - build_id: dspace-postgres-pgcrypto + build_id: dspace-postgres-pgcrypto-prod image_name: dspace/dspace-postgres-pgcrypto # Must build out of subdirectory to have access to install script for pgcrypto. # NOTE: this context will build the image based on the Dockerfile in the specified directory diff --git a/.github/workflows/issue_opened.yml b/.github/workflows/issue_opened.yml index b4436dca3aad..0a35a6a95044 100644 --- a/.github/workflows/issue_opened.yml +++ b/.github/workflows/issue_opened.yml @@ -16,7 +16,7 @@ jobs: # Only add to project board if issue is flagged as "needs triage" or has no labels # NOTE: By default we flag new issues as "needs triage" in our issue template if: (contains(github.event.issue.labels.*.name, 'needs triage') || join(github.event.issue.labels.*.name) == '') - uses: actions/add-to-project@v0.5.0 + uses: actions/add-to-project@v1.0.0 # Note, the authentication token below is an ORG level Secret. # It must be created/recreated manually via a personal access token with admin:org, project, public_repo permissions # See: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml index f16e81c9fd25..bbac52af2438 100644 --- a/.github/workflows/pull_request_opened.yml +++ b/.github/workflows/pull_request_opened.yml @@ -21,4 +21,4 @@ jobs: # Assign the PR to whomever created it. This is useful for visualizing assignments on project boards # See https://github.com/toshimaru/auto-author-assign - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v2.0.1 + uses: toshimaru/auto-author-assign@v2.1.0 diff --git a/.github/workflows/reusable-docker-build.yml b/.github/workflows/reusable-docker-build.yml index aa8327f4d11b..0c7538a8f113 100644 --- a/.github/workflows/reusable-docker-build.yml +++ b/.github/workflows/reusable-docker-build.yml @@ -68,9 +68,9 @@ env: # See "Redeploy" steps below for more details. REDEPLOY_SANDBOX_URL: ${{ secrets.REDEPLOY_SANDBOX_URL }} REDEPLOY_DEMO_URL: ${{ secrets.REDEPLOY_DEMO_URL }} - # Current DSpace maintenance branch (and architecture) which is deployed to demo.dspace.org / sandbox.dspace.org - # (NOTE: No deployment branch specified for sandbox.dspace.org as it uses the default_branch) + # Current DSpace branches (and architecture) which are deployed to demo.dspace.org & sandbox.dspace.org respectively DEPLOY_DEMO_BRANCH: 'dspace-7_x' + DEPLOY_SANDBOX_BRANCH: 'dspace-8.0-testathon' DEPLOY_ARCH: 'linux/amd64' jobs: @@ -93,6 +93,14 @@ jobs: runs-on: ${{ matrix.os }} steps: + # This step converts the slashes in the "arch" matrix values above into dashes & saves to env.ARCH_NAME + # E.g. "linux/amd64" becomes "linux-amd64" + # This is necessary because all upload artifacts CANNOT have special chars (like slashes) + - name: Prepare + run: | + platform=${{ matrix.arch }} + echo "ARCH_NAME=${platform//\//-}" >> $GITHUB_ENV + # https://github.com/actions/checkout - name: Checkout codebase uses: actions/checkout@v4 @@ -152,9 +160,9 @@ jobs: # Upload digest to an artifact, so that it can be used in manifest below - name: Upload Docker build digest to artifact if: ${{ ! matrix.isPr }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: digests-${{ inputs.build_id }} + name: digests-${{ inputs.build_id }}-${{ env.ARCH_NAME }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 @@ -166,13 +174,13 @@ jobs: !matrix.isPR && env.REDEPLOY_SANDBOX_URL != '' && matrix.arch == env.DEPLOY_ARCH && - github.ref_name == github.event.repository.default_branch + github.ref_name == env.DEPLOY_SANDBOX_BRANCH run: | curl -X POST $REDEPLOY_SANDBOX_URL # If this build is NOT a PR and passed in a REDEPLOY_DEMO_URL secret, # Then redeploy https://demo.dspace.org if this build is for our deployment architecture and demo branch. - - name: Redeploy demo.dspace.org (based on maintenace branch) + - name: Redeploy demo.dspace.org (based on maintenance branch) if: | !matrix.isPR && env.REDEPLOY_DEMO_URL != '' && @@ -192,10 +200,12 @@ jobs: - docker-build steps: - name: Download Docker build digests - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: digests-${{ inputs.build_id }} path: /tmp/digests + # Download digests for both AMD64 and ARM64 into same directory + pattern: digests-${{ inputs.build_id }}-* + merge-multiple: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index e9544d3274fa..5c094dee2a2e 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -458,7 +458,12 @@ commons-validator - com.sun.mail + jakarta.mail + jakarta.mail-api + provided + + + org.eclipse.angus jakarta.mail diff --git a/dspace-api/src/main/java/org/dspace/app/ldn/model/Citation.java b/dspace-api/src/main/java/org/dspace/app/ldn/model/Citation.java index c6629f5e7b91..7abe5c8ef44a 100644 --- a/dspace-api/src/main/java/org/dspace/app/ldn/model/Citation.java +++ b/dspace-api/src/main/java/org/dspace/app/ldn/model/Citation.java @@ -18,7 +18,7 @@ public class Citation extends Base { @JsonProperty("ietf:cite-as") private String ietfCiteAs; - @JsonProperty("url") + @JsonProperty("ietf:item") private Url url; /** diff --git a/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java b/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java index f901c9ca569e..aac42ce1acf9 100644 --- a/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java +++ b/dspace-api/src/main/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncCli.java @@ -105,35 +105,17 @@ private void performStatusUpdate(Context context) throws SearchServiceException, solrQuery.addFilterQuery(dateRangeFilter); solrQuery.addField(SearchUtils.RESOURCE_ID_FIELD); solrQuery.addField(SearchUtils.RESOURCE_UNIQUE_ID); + solrQuery.setRows(0); QueryResponse response = solrSearchCore.getSolr().query(solrQuery, solrSearchCore.REQUEST_METHOD); - - if (response != null) { - logInfoAndOut(response.getResults().size() + " items found to process"); - - for (SolrDocument doc : response.getResults()) { - String uuid = (String) doc.getFirstValue(SearchUtils.RESOURCE_ID_FIELD); - String uniqueId = (String) doc.getFirstValue(SearchUtils.RESOURCE_UNIQUE_ID); - logDebugAndOut("Processing item with UUID: " + uuid); - - Optional indexableObject = Optional.empty(); - try { - indexableObject = indexObjectServiceFactory - .getIndexableObjectFactory(uniqueId).findIndexableObject(context, uuid); - } catch (SQLException e) { - log.warn("An exception occurred when attempting to retrieve item with UUID \"" + uuid + - "\" from the database, removing related solr document", e); - } - - try { - if (indexableObject.isPresent()) { - logDebugAndOut("Item exists in DB, updating solr document"); - updateItem(context, indexableObject.get()); - } else { - logDebugAndOut("Item doesn't exist in DB, removing solr document"); - removeItem(context, uniqueId); - } - } catch (SQLException | IOException e) { - log.error(e.getMessage(), e); + if (response != null && response.getResults() != null) { + long nrOfPreDBResults = response.getResults().getNumFound(); + if (nrOfPreDBResults > 0) { + logInfoAndOut(nrOfPreDBResults + " items found to process"); + int batchSize = configurationService.getIntProperty("script.solr-database-resync.batch-size", 100); + for (int start = 0; start < nrOfPreDBResults; start += batchSize) { + solrQuery.setStart(start); + solrQuery.setRows(batchSize); + performStatusUpdateOnNextBatch(context, solrQuery); } } } @@ -141,6 +123,38 @@ private void performStatusUpdate(Context context) throws SearchServiceException, indexingService.commit(); } + private void performStatusUpdateOnNextBatch(Context context, SolrQuery solrQuery) + throws SolrServerException, IOException { + QueryResponse response = solrSearchCore.getSolr().query(solrQuery, solrSearchCore.REQUEST_METHOD); + + for (SolrDocument doc : response.getResults()) { + String uuid = (String) doc.getFirstValue(SearchUtils.RESOURCE_ID_FIELD); + String uniqueId = (String) doc.getFirstValue(SearchUtils.RESOURCE_UNIQUE_ID); + logDebugAndOut("Processing item with UUID: " + uuid); + + Optional indexableObject = Optional.empty(); + try { + indexableObject = indexObjectServiceFactory + .getIndexableObjectFactory(uniqueId).findIndexableObject(context, uuid); + } catch (SQLException e) { + log.warn("An exception occurred when attempting to retrieve item with UUID \"" + uuid + + "\" from the database, removing related solr document", e); + } + + try { + if (indexableObject.isPresent()) { + logDebugAndOut("Item exists in DB, updating solr document"); + updateItem(context, indexableObject.get()); + } else { + logDebugAndOut("Item doesn't exist in DB, removing solr document"); + removeItem(context, uniqueId); + } + } catch (SQLException | IOException e) { + log.error(e.getMessage(), e); + } + } + } + private void updateItem(Context context, IndexableObject indexableObject) throws SolrServerException, IOException { Map fieldModifier = new HashMap<>(1); fieldModifier.put("remove", STATUS_FIELD_PREDB); diff --git a/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java index 2119959073f0..ba4bce0de7d3 100644 --- a/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/DSpaceObjectServiceImpl.java @@ -629,6 +629,7 @@ public void update(Context context, T dso) throws SQLException, AuthorizeExcepti // E.g. for an Author relationship, // the place should be updated using the same principle as dc.contributor.author. StringUtils.startsWith(metadataValue.getAuthority(), Constants.VIRTUAL_AUTHORITY_PREFIX) + && metadataValue instanceof RelationshipMetadataValue && ((RelationshipMetadataValue) metadataValue).isUseForPlace() ) { int mvPlace = getMetadataValuePlace(fieldToLastPlace, metadataValue); diff --git a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java index 2f34129f2e69..9b28203827e0 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java @@ -8,6 +8,7 @@ package org.dspace.content; import java.sql.SQLException; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.UUID; @@ -51,12 +52,7 @@ public Entity findByItemId(Context context, UUID itemId, Integer limit, Integer @Override public EntityType getType(Context context, Entity entity) throws SQLException { Item item = entity.getItem(); - List list = itemService.getMetadata(item, "dspace", "entity", "type", Item.ANY, false); - if (!list.isEmpty()) { - return entityTypeService.findByEntityType(context, list.get(0).getValue()); - } else { - return null; - } + return itemService.getEntityType(context, item); } @Override @@ -103,7 +99,12 @@ public List getAllRelationshipTypes(Context context, Entity en @Override public List getAllRelationshipTypes(Context context, Entity entity, Integer limit, Integer offset) throws SQLException { - return relationshipTypeService.findByEntityType(context, this.getType(context, entity), limit, offset); + EntityType entityType = this.getType(context, entity); + if (entityType != null) { + return relationshipTypeService.findByEntityType(context, entityType, limit, offset); + } else { + return Collections.emptyList(); + } } @Override @@ -115,7 +116,12 @@ public List getLeftRelationshipTypes(Context context, Entity e @Override public List getLeftRelationshipTypes(Context context, Entity entity, boolean isLeft, Integer limit, Integer offset) throws SQLException { - return relationshipTypeService.findByEntityType(context, this.getType(context, entity), isLeft, limit, offset); + EntityType entityType = this.getType(context, entity); + if (entityType != null) { + return relationshipTypeService.findByEntityType(context, entityType, isLeft, limit, offset); + } else { + return Collections.emptyList(); + } } @Override @@ -128,7 +134,12 @@ public List getRightRelationshipTypes(Context context, Entity public List getRightRelationshipTypes(Context context, Entity entity, boolean isLeft, Integer limit, Integer offset) throws SQLException { - return relationshipTypeService.findByEntityType(context, this.getType(context, entity), isLeft, limit, offset); + EntityType entityType = this.getType(context, entity); + if (entityType != null) { + return relationshipTypeService.findByEntityType(context, entityType, isLeft, limit, offset); + } else { + return Collections.emptyList(); + } } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java index b6e7372af184..b78f6b9f7de8 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java @@ -96,11 +96,18 @@ public WorkspaceItem find(Context context, int id) throws SQLException { @Override public WorkspaceItem create(Context context, Collection collection, boolean template) throws AuthorizeException, SQLException { - return create(context, collection, null, template); + return create(context, collection, null, template, false); } @Override - public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template) + public WorkspaceItem create(Context context, Collection collection, boolean template, boolean isNewVersion) + throws AuthorizeException, SQLException { + return create(context, collection, null, template, isNewVersion); + } + + @Override + public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template, + boolean isNewVersion) throws AuthorizeException, SQLException { // Check the user has permission to ADD to the collection authorizeService.authorizeAction(context, collection, Constants.ADD); @@ -174,8 +181,10 @@ public WorkspaceItem create(Context context, Collection collection, UUID uuid, b // If configured, register identifiers (eg handle, DOI) now. This is typically used with the Show Identifiers // submission step which previews minted handles and DOIs during the submission process. Default: false + // Additional check needed: if we are creating a new version of an existing item we skip the identifier + // generation here, as this will be performed when the new version is created in VersioningServiceImpl if (DSpaceServicesFactory.getInstance().getConfigurationService() - .getBooleanProperty("identifiers.submission.register", false)) { + .getBooleanProperty("identifiers.submission.register", false) && !isNewVersion) { try { // Get map of filters to use for identifier types, while the item is in progress Map, Filter> filters = FilterUtils.getIdentifierFilters(true); diff --git a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java index 9e7d870076aa..9a8ae4606487 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/PackageUtils.java @@ -503,7 +503,7 @@ public static DSpaceObject createDSpaceObject(Context context, DSpaceObject pare wsi = workspaceItemService.create(context, (Collection)parent, params.useCollectionTemplate()); } else { wsi = workspaceItemService.create(context, (Collection)parent, - uuid, params.useCollectionTemplate()); + uuid, params.useCollectionTemplate(), false); } // Please note that we are returning an Item which is *NOT* yet in the Archive, diff --git a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java index c8df68e43498..8559bcc61402 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java @@ -56,6 +56,23 @@ public interface WorkspaceItemService extends InProgressSubmissionServicetrue, the workspace item starts as a copy + * of the collection's template item + * @param isNewVersion whether we are creating a new workspace item version of an existing item + * @return the newly created workspace item + * @throws SQLException if database error + * @throws AuthorizeException if authorization error + */ + public WorkspaceItem create(Context context, Collection collection, boolean template, boolean isNewVersion) + throws AuthorizeException, SQLException; + /** * Create a new workspace item, with a new ID. An Item is also created. The * submitter is the current user in the context. @@ -65,11 +82,13 @@ public WorkspaceItem create(Context context, Collection collection, boolean temp * @param uuid the preferred uuid of the new item (used if restoring an item and retaining old uuid) * @param template if true, the workspace item starts as a copy * of the collection's template item + * @param isNewVersion whether we are creating a new workspace item version of an existing item * @return the newly created workspace item * @throws SQLException if database error * @throws AuthorizeException if authorization error */ - public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template) + public WorkspaceItem create(Context context, Collection collection, UUID uuid, boolean template, + boolean isNewVersion) throws AuthorizeException, SQLException; public WorkspaceItem create(Context c, WorkflowItem wfi) throws SQLException, AuthorizeException; diff --git a/dspace-api/src/main/java/org/dspace/submit/consumer/SubmissionConfigConsumer.java b/dspace-api/src/main/java/org/dspace/submit/consumer/SubmissionConfigConsumer.java index a593fe8ae066..0cf4ae92c2ca 100644 --- a/dspace-api/src/main/java/org/dspace/submit/consumer/SubmissionConfigConsumer.java +++ b/dspace-api/src/main/java/org/dspace/submit/consumer/SubmissionConfigConsumer.java @@ -8,15 +8,10 @@ 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; /** @@ -28,11 +23,9 @@ public class SubmissionConfigConsumer implements Consumer { /** * log4j logger */ - private static Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionConfigConsumer.class); + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionConfigConsumer.class); - IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager() - .getServiceByName(IndexingService.class.getName(), - IndexingService.class); + private boolean reloadNeeded = false; @Override public void initialize() throws Exception { @@ -42,37 +35,27 @@ public void initialize() throws Exception { @Override public void consume(Context ctx, Event event) throws Exception { int st = event.getSubjectType(); - int et = event.getEventType(); + if (st == Constants.COLLECTION) { + // NOTE: IndexEventConsumer ("discovery") should be declared before this consumer + // We don't reindex the collection because it will normally be reindexed by IndexEventConsumer + // before the submission configurations are reloaded - 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; - } + log.debug("SubmissionConfigConsumer occurred: " + event); + // submission configurations should be reloaded + reloadNeeded = true; } } @Override public void end(Context ctx) throws Exception { - // No-op + if (reloadNeeded) { + // reload submission configurations + SubmissionServiceFactory.getInstance().getSubmissionConfigService().reload(); + + // Reset the boolean used + reloadNeeded = false; + } } @Override diff --git a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java index d4590ae24ea2..fa89b3441408 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java +++ b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java @@ -52,7 +52,9 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen @Override public Item createNewItemAndAddItInWorkspace(Context context, Item nativeItem) { try { - WorkspaceItem workspaceItem = workspaceItemService.create(context, nativeItem.getOwningCollection(), false); + WorkspaceItem workspaceItem = workspaceItemService.create(context, nativeItem.getOwningCollection(), + false, + true); Item itemNew = workspaceItem.getItem(); itemService.update(context, itemNew); return itemNew; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java index cd18b3a0bd19..d954cc3b26ca 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowServiceImpl.java @@ -1177,7 +1177,7 @@ protected WorkspaceItem returnToWorkspace(Context c, XmlWorkflowItem wfi) public String getEPersonName(EPerson ePerson) { String submitter = ePerson.getFullName(); - submitter = submitter + "(" + ePerson.getEmail() + ")"; + submitter = submitter + " (" + ePerson.getEmail() + ")"; return submitter; } diff --git a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java index 7d808ab8715c..2cddbb511f91 100644 --- a/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java +++ b/dspace-api/src/test/java/org/dspace/app/packager/PackagerIT.java @@ -159,7 +159,7 @@ public void packagerUUIDAlreadyExistWithoutForceTest() throws Exception { performExportScript(article.getHandle(), tempFile); UUID id = article.getID(); itemService.delete(context, article); - WorkspaceItem workspaceItem = workspaceItemService.create(context, col1, id, false); + WorkspaceItem workspaceItem = workspaceItemService.create(context, col1, id, false, false); installItemService.installItem(context, workspaceItem, "123456789/0100"); performImportNoForceScript(tempFile); Iterator items = itemService.findByCollection(context, col1); diff --git a/dspace-api/src/test/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncIT.java b/dspace-api/src/test/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncIT.java index 4fa881257e0f..d1fa0db9089b 100644 --- a/dspace-api/src/test/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncIT.java +++ b/dspace-api/src/test/java/org/dspace/app/solrdatabaseresync/SolrDatabaseResyncIT.java @@ -35,6 +35,9 @@ import org.junit.Before; import org.junit.Test; +/** + * IT for {@link org.dspace.app.solrdatabaseresync.SolrDatabaseResyncIT} + */ public class SolrDatabaseResyncIT extends AbstractIntegrationTestWithDatabase { private final ConfigurationService configurationService = @@ -48,11 +51,21 @@ public class SolrDatabaseResyncIT extends AbstractIntegrationTestWithDatabase { private Collection col; private Item item1; private Item item2; + private Item item3; + private Item item4; + private Item item5; + private Item item6; + private Item item7; + private Item item8; + private Item item9; + private Item item10; + private Item item11; @Before public void setUp() throws Exception { super.setUp(); configurationService.setProperty("solr-database-resync.time-until-reindex", 1); + configurationService.setProperty("script.solr-database-resync.batch-size", 5); ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager(); searchService = serviceManager.getServiceByName(null, MockSolrSearchCore.class); @@ -75,6 +88,16 @@ public void setUp() throws Exception { .withSubject("TestingForMore") .build(); + item3 = ItemBuilder.createItem(context, col).withTitle("Public item 3").build(); + item4 = ItemBuilder.createItem(context, col).withTitle("Public item 4").build(); + item5 = ItemBuilder.createItem(context, col).withTitle("Public item 5").build(); + item6 = ItemBuilder.createItem(context, col).withTitle("Public item 6").build(); + item7 = ItemBuilder.createItem(context, col).withTitle("Public item 7").build(); + item8 = ItemBuilder.createItem(context, col).withTitle("Public item 8").build(); + item9 = ItemBuilder.createItem(context, col).withTitle("Public item 9").build(); + item10 = ItemBuilder.createItem(context, col).withTitle("Public item 10").build(); + item11 = ItemBuilder.createItem(context, col).withTitle("Public item 11").build(); + context.setDispatcher("noindex"); } @@ -83,12 +106,30 @@ public void solrPreDBStatusExistingItemTest() throws Exception { // Items were created, they should contain a predb status in solr assertHasPreDBStatus(item1); assertHasPreDBStatus(item2); + assertHasPreDBStatus(item3); + assertHasPreDBStatus(item4); + assertHasPreDBStatus(item5); + assertHasPreDBStatus(item6); + assertHasPreDBStatus(item7); + assertHasPreDBStatus(item8); + assertHasPreDBStatus(item9); + assertHasPreDBStatus(item10); + assertHasPreDBStatus(item11); performSolrDatabaseResyncScript(); // Database status script was performed, their predb status should be removed assertHasNoPreDBStatus(item1); assertHasNoPreDBStatus(item2); + assertHasNoPreDBStatus(item3); + assertHasNoPreDBStatus(item4); + assertHasNoPreDBStatus(item5); + assertHasNoPreDBStatus(item6); + assertHasNoPreDBStatus(item7); + assertHasNoPreDBStatus(item8); + assertHasNoPreDBStatus(item9); + assertHasNoPreDBStatus(item10); + assertHasNoPreDBStatus(item11); context.restoreAuthSystemState(); } @@ -98,22 +139,50 @@ public void solrPreDBStatusRemovedItemTest() throws Exception { // Items were created, they should contain a predb status in solr assertHasPreDBStatus(item1); assertHasPreDBStatus(item2); + assertHasPreDBStatus(item3); + assertHasPreDBStatus(item4); + assertHasPreDBStatus(item5); + assertHasPreDBStatus(item6); + assertHasPreDBStatus(item7); + assertHasPreDBStatus(item8); + assertHasPreDBStatus(item9); + assertHasPreDBStatus(item10); + assertHasPreDBStatus(item11); collectionService.delete(context, col); // Items were deleted, they should still contain a predb status in solr for now assertHasPreDBStatus(item1); assertHasPreDBStatus(item2); + assertHasPreDBStatus(item3); + assertHasPreDBStatus(item4); + assertHasPreDBStatus(item5); + assertHasPreDBStatus(item6); + assertHasPreDBStatus(item7); + assertHasPreDBStatus(item8); + assertHasPreDBStatus(item9); + assertHasPreDBStatus(item10); + assertHasPreDBStatus(item11); performSolrDatabaseResyncScript(); // Database status script was performed, their solr document should have been removed assertNoSolrDocument(item1); assertNoSolrDocument(item2); + assertNoSolrDocument(item3); + assertNoSolrDocument(item4); + assertNoSolrDocument(item5); + assertNoSolrDocument(item6); + assertNoSolrDocument(item7); + assertNoSolrDocument(item8); + assertNoSolrDocument(item9); + assertNoSolrDocument(item10); + assertNoSolrDocument(item11); context.restoreAuthSystemState(); } + public void assertHasNoPreDBStatus(Item item) throws Exception { assertNotEquals(STATUS_FIELD_PREDB, getStatus(item)); } diff --git a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java index 305ebff69710..11fbbb9f9119 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java @@ -145,6 +145,7 @@ public void testGetAllRelationshipTypes() throws Exception { // Declare objects utilized for this test Item item = mock(Item.class); Entity entity = mock(Entity.class); + EntityType entityType = mock(EntityType.class); RelationshipType relationshipType = mock(RelationshipType.class); relationshipType.setLeftType(leftType); relationshipType.setLeftType(rightType); @@ -156,7 +157,8 @@ public void testGetAllRelationshipTypes() throws Exception { // Mock the state of objects utilized in getAllRelationshipTypes() // to meet the success criteria of the invocation when(entity.getItem()).thenReturn(item); - when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), -1, -1)) + when(entityService.getType(context, entity)).thenReturn(entityType); + when(relationshipTypeService.findByEntityType(context, entityType, -1, -1)) .thenReturn(relationshipTypeList); // The relation(s) reported from our mocked Entity should match our relationshipList @@ -181,10 +183,9 @@ public void testGetLeftRelationshipTypes() throws Exception { // Mock the state of objects utilized in getLeftRelationshipTypes() // to meet the success criteria of the invocation - when(itemService.getMetadata(item, "dspace", "entity", "type", Item.ANY, false)).thenReturn(metsList); when(entity.getItem()).thenReturn(item); when(entityService.getType(context, entity)).thenReturn(entityType); - when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), true, -1, -1)) + when(relationshipTypeService.findByEntityType(context, entityType, true, -1, -1)) .thenReturn(relationshipTypeList); // The left relationshipType(s) reported from our mocked Entity should match our relationshipList @@ -209,10 +210,9 @@ public void testGetRightRelationshipTypes() throws Exception { // Mock the state of objects utilized in getRightRelationshipTypes() // to meet the success criteria of the invocation - when(itemService.getMetadata(item, "dspace", "entity", "type", Item.ANY, false)).thenReturn(metsList); when(entity.getItem()).thenReturn(item); when(entityService.getType(context, entity)).thenReturn(entityType); - when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), false, -1, -1)) + when(relationshipTypeService.findByEntityType(context, entityType, false, -1, -1)) .thenReturn(relationshipTypeList); // The right relationshipType(s) reported from our mocked Entity should match our relationshipList diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java deleted file mode 100644 index f8af92fa5868..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DSpaceCsrfTokenRequestHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.util.function.Supplier; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.web.csrf.CsrfToken; -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; -import org.springframework.security.web.csrf.CsrfTokenRequestHandler; -import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; -import org.springframework.util.StringUtils; - -/** - * A custom Spring Security CsrfTokenRequestAttributeHandler which uses the Spring Security BREACH protection - * (provided by XorCsrfTokenRequestAttributeHandler) *only* when the CSRF token is sent as a "_csrf" request parameter. - * In all other scenarios, the CsrfTokenRequestAttributeHandler is used instead. - *

- * NOTE: The DSpace UI always sends the CSRF Token as a request header. It does NOT send it as a "_csrf" request - * paramter. So, this BREACH protection would ONLY be triggered for custom clients (not the DSpace UI). - * Therefore, if using this custom class becomes problematic, we could revert to using the default - * CsrfTokenRequestAttributeHandler without any negative impact on the DSpace UI. - *

- * This code is copied from the example "SpaCsrfTokenRequestHandler" (for single page applications) from the Spring - * Security docs at - * https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration-javascript-spa-configuration - */ -public final class DSpaceCsrfTokenRequestHandler extends CsrfTokenRequestAttributeHandler { - private final CsrfTokenRequestHandler delegate = new XorCsrfTokenRequestAttributeHandler(); - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, Supplier csrfToken) { - /* - * Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of - * the CsrfToken when it is rendered in the response body. - * NOTE: This should never occur from the DSpace UI, so it is only applicable for custom clients. - */ - this.delegate.handle(request, response, csrfToken); - } - - @Override - public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) { - /* - * If the request contains a request header, use CsrfTokenRequestAttributeHandler - * to resolve the CsrfToken. This applies to the DSpace UI which always includes - * the raw CsrfToken in an HTTP Header. - */ - if (StringUtils.hasText(request.getHeader(csrfToken.getHeaderName()))) { - return super.resolveCsrfTokenValue(request, csrfToken); - } - /* - * In all other cases (e.g. if the request contains a request parameter), use - * XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies - * when a server-side rendered form includes the _csrf request parameter as a - * hidden input. - * NOTE: This should never occur from the DSpace UI, so it is only applicable for custom clients. - */ - return this.delegate.resolveCsrfTokenValue(request, csrfToken); - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java index 6fb8f285d1a4..af7116a2bea5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; /** @@ -112,7 +113,12 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .csrf((csrf) -> csrf .csrfTokenRepository(this.csrfTokenRepository()) .sessionAuthenticationStrategy(this.dSpaceCsrfAuthenticationStrategy()) - .csrfTokenRequestHandler(new DSpaceCsrfTokenRequestHandler())) + // Disable SpringSecurity BREACH protection, as this is not working well with Cookie-based storage. + // When enabled, BREACH protection causes the CSRF token to grow in size until UI errors occur. + // See https://github.com/DSpace/DSpace/issues/9450 + // NOTE: DSpace doesn't need BREACH protection as it's only necessary when sending the token via a + // request attribute (e.g. "_csrf") which the DSpace UI never does. + .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())) .exceptionHandling((exceptionHandling) -> exceptionHandling // Return 401 on authorization failures with a correct WWWW-Authenticate header .authenticationEntryPoint(new DSpace401AuthenticationEntryPoint(restAuthenticationService)) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java index 653850331a61..5c6d394ffda0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/NotifyServiceRestRepositoryIT.java @@ -1266,6 +1266,8 @@ public void NotifyServiceInboundPatternConstraintReplaceOperationBadRequestTest( .andExpect(status().isBadRequest()); } + // Temporarily disable. See: https://github.com/DSpace/DSpace/issues/9457 + @Ignore @Test public void NotifyServiceInboundPatternConstraintRemoveOperationTest() throws Exception { @@ -1330,6 +1332,8 @@ public void NotifyServiceInboundPatternConstraintRemoveOperationTest() throws Ex ))); } + // Temporarily disable. See: https://github.com/DSpace/DSpace/issues/9457 + @Ignore @Test public void NotifyServiceInboundPatternConstraintRemoveOperationBadRequestTest() throws Exception { diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_endorsement.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_endorsement.json index 828757c4c1b9..e266565d2c8b 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_endorsement.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_endorsement.json @@ -12,7 +12,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": ["sorg:AboutPage"], - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_release.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_release.json index becd3a02c5cf..6669628d9251 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_release.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_release.json @@ -13,7 +13,7 @@ "id_handle": "http://localhost:4000/handle/123456789/1119", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "https://another-research-organisation.org/repository/datasets/item/201203421/data_archive.zip", "mediaType": "application/zip", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_review.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_review.json index 8f422c9039fe..c5203bee9433 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_review.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_announce_review.json @@ -12,7 +12,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement.json index d977f2e6b7db..39f6411a5593 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement.json @@ -13,7 +13,7 @@ "id": "https://overlay-journal.com/articles/00001/", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_badrequest.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_badrequest.json index e6e373f1c7cd..2371fc54c3a1 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_badrequest.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_badrequest.json @@ -13,7 +13,7 @@ "id": "https://overlay-journal.com/articles/00001/", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": ["sorg:AboutPage"], - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_object.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_object.json index 8252d7f70102..7af079acba2e 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_object.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_endorsement_object.json @@ -12,7 +12,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": ["sorg:AboutPage"], - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review.json index d1d5ba5601f6..9a20adcda5d6 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review.json @@ -13,7 +13,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "url.pdf", "mediaType": "applicationpdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review2.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review2.json index d60e32f04f2b..973ea946f6f4 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review2.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_offer_review2.json @@ -13,7 +13,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "url.pdf", "mediaType": "applicationpdf", "type": [ diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_origin_inbox_unregistered.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_origin_inbox_unregistered.json index 30c5cc559034..fdeb340fd2f4 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_origin_inbox_unregistered.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/ldn_origin_inbox_unregistered.json @@ -12,7 +12,7 @@ "id": "<>", "ietf:cite-as": "https://doi.org/10.5555/12345680", "type": ["sorg:AboutPage"], - "url": { + "ietf:item": { "id": "https://research-organisation.org/repository/preprint/201203/421/content.pdf", "mediaType": "application/pdf", "type": [ diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index e146d6676dea..e268d62d4b60 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -102,7 +102,12 @@ provided - com.sun.mail + jakarta.mail + jakarta.mail-api + provided + + + org.eclipse.angus jakarta.mail diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 1e799449898d..c5a2c02956d0 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -45,6 +45,20 @@ org.glassfish.jersey.core jersey-common + + + org.apache.geronimo.specs + geronimo-activation_1.1_spec + + + org.apache.geronimo.specs + geronimo-javamail_1.4_spec + + + org.apache.geronimo.specs + geronimo-stax-api_1.0_spec + diff --git a/dspace/config/ldn/request-endorsement b/dspace/config/ldn/request-endorsement index e885bf88efab..443a7029159f 100644 --- a/dspace/config/ldn/request-endorsement +++ b/dspace/config/ldn/request-endorsement @@ -26,7 +26,7 @@ "id": "${params[5]}", "ietf:cite-as": "${params[6]}", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "${params[7]}", "mediaType": "${params[8]}", "type": [ diff --git a/dspace/config/ldn/request-ingest b/dspace/config/ldn/request-ingest index 82bd9a85d90c..701f3929c826 100644 --- a/dspace/config/ldn/request-ingest +++ b/dspace/config/ldn/request-ingest @@ -26,7 +26,7 @@ "id": "${params[5]}", "ietf:cite-as": "${params[6]}", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "${params[7]}", "mediaType": "${params[8]}", "type": [ diff --git a/dspace/config/ldn/request-review b/dspace/config/ldn/request-review index 24c1ac831968..01f177b6cc18 100644 --- a/dspace/config/ldn/request-review +++ b/dspace/config/ldn/request-review @@ -26,7 +26,7 @@ "id": "${params[5]}", "ietf:cite-as": "${params[6]}", "type": "sorg:AboutPage", - "url": { + "ietf:item": { "id": "${params[7]}", "mediaType": "${params[8]}", "type": [ diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index ed6aacdbd74a..659b7796dd97 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -163,7 +163,7 @@ dropdown Select the type of content of the item. - + You must choose at least one type. @@ -366,7 +366,7 @@ Select the type(s) of content of the item. To select more than one value in the list, you may have to hold down the "CTRL" or "Shift" key. - + You must choose at least one type. @@ -1041,7 +1041,7 @@ Select the type(s) of content of the item. To select more than one value in the list, you may have to hold down the "CTRL" or "Shift" key. - + You must choose at least one type. diff --git a/dspace/src/main/docker/dspace-shibboleth/httpd-shibd-foreground.sh b/dspace/src/main/docker/dspace-shibboleth/httpd-shibd-foreground.sh old mode 100644 new mode 100755 diff --git a/pom.xml b/pom.xml index 3fd890f6c305..f57bd812f96d 100644 --- a/pom.xml +++ b/pom.xml @@ -34,8 +34,8 @@ 2.16.0 2.16.0 2.1.1 - 4.0.0 - 4.0.1 + 4.0.2 + 4.0.5 1.1.1 9.4.54.v20240208 @@ -374,7 +374,7 @@ false - + https://docs.spring.io/spring-framework/docs/current/javadoc-api/ https://docs.spring.io/spring-security/site/docs/current/api/ @@ -1494,7 +1494,7 @@ org.apache.commons commons-compress - 1.23.0 + 1.26.0 org.apache.commons @@ -1522,9 +1522,22 @@ 2.12.5 - com.sun.mail + jakarta.activation + jakarta.activation-api + 2.1.3 + + + + jakarta.mail + jakarta.mail-api + 2.1.3 + provided + + + + org.eclipse.angus jakarta.mail - 2.0.1 + 2.0.3 jakarta.servlet