Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
5e1c099
UFAL/Removed duplicities of the bitstreams in the cmdi (#766)
milanmajchrak Sep 20, 2024
1e2b8ef
Ufal/Preview issues (#764)
milanmajchrak Sep 20, 2024
4f579e1
UFAL/Encoded the UTF-8 characters from the redirect URL to UTF (#758)
milanmajchrak Sep 20, 2024
140f0b7
Merge pull request #9790 from DSpace/backport-9775-to-dspace-7_x (#769)
milanmajchrak Sep 24, 2024
dd24d2b
test for bitstream with null value of sizebytes
Paurikova2 Oct 10, 2024
9386c0e
Update README.md
vidiecan Oct 15, 2024
0659305
UFAL/Shibboleth - load more net-id headers e.g. persistent-id (#772)
milanmajchrak Oct 16, 2024
999164c
Propagate the verification token to the DB after the email is success…
milanmajchrak Oct 16, 2024
6c6de87
UFAL/Enhanced type-bind feature (#762)
milanmajchrak Oct 17, 2024
8d115da
create preview content for tar files (#759)
Paurikova2 Oct 17, 2024
659d14e
Internal/fix failing Clarin integration test (#796)
milanmajchrak Oct 31, 2024
68fb203
Rest api for handle resolution with metadata
Paurikova2 Nov 4, 2024
8aed694
Add default licenses - from ZCU update (#801)
milanmajchrak Nov 12, 2024
a9078bb
UFAL/share submission by email (#780)
milanmajchrak Nov 12, 2024
2ff2286
Import default licenses only if the license tables are empty. (#808)
milanmajchrak Nov 12, 2024
bc75418
Oai elg crosswalk (#798)
Paurikova2 Nov 15, 2024
dad2ea2
removed handle from item submission (#812)
Paurikova2 Nov 15, 2024
32f61b3
UFAL/Shibboleth - netid-header should use getArrayProperty everywhere…
milanmajchrak Nov 19, 2024
582906c
UFAL/Autocomplete enhancement (#768)
milanmajchrak Nov 19, 2024
c25374e
UFAL/Changed position of rows in submission-forms.xml following v5 (#…
jr-rk Nov 19, 2024
37cf904
Show db connection statistics in the log file or the `dbstatistics` e…
milanmajchrak Nov 21, 2024
e29101b
Translation of submission-forms to _cs (#816)
jr-rk Nov 26, 2024
dadd1fc
Updated cfg to pretify the author suggestions (#819)
milanmajchrak Nov 27, 2024
0a0466e
crosswalk-embargo (#821)
Paurikova2 Nov 27, 2024
9911fcc
For now the complex input field is without autocomplete for the size …
milanmajchrak Nov 28, 2024
da05904
Send the custom type bind `field` to the FE configuration (#822)
milanmajchrak Nov 28, 2024
3aec368
fix date converting to string (#825)
Paurikova2 Nov 28, 2024
005c939
cherry-pick clarin v7 into dtq dev (#820)
kosarko Nov 29, 2024
9758648
Test release without db logs (#827)
milanmajchrak Nov 29, 2024
3486d2d
UFAL/Matomo statistics with dimension (#813)
jr-rk Nov 29, 2024
3ec13b2
The `dspace.name.short` is not working properly in the email, use `ds…
milanmajchrak Dec 5, 2024
56b4862
Assinging to JAVA_OPTS_HANDLE must be without $
milanmajchrak Dec 6, 2024
dc57ffd
Transaction bug - close context in finally block (#845) (#852)
milanmajchrak Jan 16, 2025
0b20909
metadata-added-provenance (#730)
Paurikova2 Jan 23, 2025
ca40fa9
Facet result for suggestion (#854)
milanmajchrak Jan 24, 2025
b260927
Healthcheck process (#853)
milanmajchrak Jan 24, 2025
018af11
Changed matomo url to some valid URL (#856)
milanmajchrak Jan 24, 2025
eacd6d3
Oai indexing after res policy change (#855)
milanmajchrak Jan 24, 2025
4e83fdd
Run build action every 4 hours to be sure tests are still passing.
milanmajchrak Jan 24, 2025
7670b7b
The dc.type should not be repeatable (#861)
milanmajchrak Jan 30, 2025
aca89cd
UFAL/Health report send to more email adresses
Kasinhou Feb 3, 2025
9b012dd
UFAL/Fixed missing `*` character in the required input field
milanmajchrak Feb 3, 2025
97fa905
Res policy for submitter (#862)
Paurikova2 Feb 4, 2025
1df4afe
Merge branch 'dtq-dev' into lindat-release-temp-02
milanmajchrak Feb 4, 2025
208eac3
Do not merge flyway script with default licenses.
milanmajchrak Feb 4, 2025
d1ac572
Removed unuseful comment
milanmajchrak Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ProvenanceService;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
Expand Down Expand Up @@ -111,6 +112,8 @@ public class BulkAccessControl extends DSpaceRunnable<BulkAccessControlScriptCon

protected String eperson = null;

protected ProvenanceService provenanceService = ContentServiceFactory.getInstance().getProvenanceService();

@Override
@SuppressWarnings("unchecked")
public void setup() throws ParseException {
Expand Down Expand Up @@ -465,6 +468,7 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl)
itemAccessConditions.get(accessCondition.getName())));

itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false);
provenanceService.setItemPolicies(context, item, accessControl);
}

/**
Expand Down Expand Up @@ -580,6 +584,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont

itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream);
mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream);
provenanceService.setBitstreamPolicies(context, bitstream, item, accessControl);
}

/**
Expand Down
221 changes: 221 additions & 0 deletions dspace-api/src/main/java/org/dspace/app/healthreport/HealthReport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/**
* 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.healthreport;

import static org.apache.commons.io.IOUtils.toInputStream;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import javax.mail.MessagingException;

import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.health.Check;
import org.dspace.health.Report;
import org.dspace.health.ReportInfo;
import org.dspace.scripts.DSpaceRunnable;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;

/**
* This class is used to generate a health report of the DSpace instance.
* @author Matus Kasak (dspace at dataquest.sk)
* @author Milan Majchrak (dspace at dataquest.sk)
*/
public class HealthReport extends DSpaceRunnable<HealthReportScriptConfiguration> {
ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
private static final Logger log = LogManager.getLogger(HealthReport.class);
private EPersonService ePersonService;

/**
* Checks to be performed.
*/
private static final LinkedHashMap<String, Check> checks = Report.checks();

/**
* `-i`: Info, show help information.
*/
private boolean info = false;

/**
* `-e`: Email, send report to specified email address.
*/
private String[] emails;

/**
* `-c`: Check, perform only specific check by index (0-`getNumberOfChecks()`).
*/
private int specificCheck = -1;

/**
* `-f`: For, specify the last N days to consider.
* Default value is set in dspace.cfg.
*/
private int forLastNDays = configurationService.getIntProperty("healthcheck.last_n_days");

/**
* `-o`: Output, specify a file to save the report.
*/
private String fileName;

@Override
public HealthReportScriptConfiguration getScriptConfiguration() {
return new DSpace().getServiceManager()
.getServiceByName("health-report", HealthReportScriptConfiguration.class);
}

@Override
public void setup() throws ParseException {
ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
// `-i`: Info, show help information.
if (commandLine.hasOption('i')) {
info = true;
return;
}

// `-e`: Email, send report to specified email address.
if (commandLine.hasOption('e')) {
emails = commandLine.getOptionValues('e');
handler.logInfo("\nReport sent to this email address: " + String.join(", ", emails));
}

// `-c`: Check, perform only specific check by index (0-`getNumberOfChecks()`).
if (commandLine.hasOption('c')) {
String checkOption = commandLine.getOptionValue('c');
try {
specificCheck = Integer.parseInt(checkOption);
if (specificCheck < 0 || specificCheck >= getNumberOfChecks()) {
specificCheck = -1;
}
} catch (NumberFormatException e) {
log.info("Invalid value for check. It has to be a number from the displayed range.");
return;
}
}

// `-f`: For, specify the last N days to consider.
if (commandLine.hasOption('f')) {
String daysOption = commandLine.getOptionValue('f');
try {
forLastNDays = Integer.parseInt(daysOption);
} catch (NumberFormatException e) {
log.info("Invalid value for last N days. Argument f has to be a number.");
return;
}
}

// `-o`: Output, specify a file to save the report.
if (commandLine.hasOption('o')) {
fileName = commandLine.getOptionValue('o');
}
}

@Override
public void internalRun() throws Exception {
if (info) {
printHelp();
return;
}

ReportInfo ri = new ReportInfo(this.forLastNDays);

StringBuilder sbReport = new StringBuilder();
sbReport.append("\n\nHEALTH REPORT:\n");

int position = -1;
for (Map.Entry<String, Check> check_entry : Report.checks().entrySet()) {
++position;
if (specificCheck != -1 && specificCheck != position) {
continue;
}

String name = check_entry.getKey();
Check check = check_entry.getValue();

log.info("#{}. Processing [{}] at [{}]", position, name, new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));

sbReport.append("\n######################\n\n").append(name).append(":\n");
check.report(ri);
sbReport.append(check.getReport());
}

// save output to file
if (fileName != null) {
Context context = new Context();
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));

InputStream inputStream = toInputStream(sbReport.toString(), StandardCharsets.UTF_8);
handler.writeFilestream(context, fileName, inputStream, "export");

context.restoreAuthSystemState();
context.complete();
}

// send email to email address from argument
if (emails != null && emails.length > 0) {
try {
Email e = Email.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "healthcheck"));
for (String recipient : emails) {
e.addRecipient(recipient);
}
e.addArgument(sbReport.toString());
e.send();
} catch (IOException | MessagingException e) {
log.error("Error sending email:", e);
}
}

handler.logInfo(sbReport.toString());
}

@Override
public void printHelp() {
handler.logInfo("\n\nINFORMATION\nThis process creates a health report of your DSpace.\n" +
"You can choose from these available options:\n" +
" -i, --info Show help information\n" +
" -e, --email Send report to specified email address\n" +
" -c, --check Perform only specific check by index (0-" + (getNumberOfChecks() - 1) + ")\n" +
" -f, --for Specify the last N days to consider\n" +
" -o, --output Specify a file to save the report\n\n" +
"If you want to execute only one check using -c, use check index:\n" + checksNamesToString() + "\n"
);
}

/**
* Convert checks names to string.
*/
private String checksNamesToString() {
StringBuilder names = new StringBuilder();
int pos = 0;
for (String name : checks.keySet()) {
names.append(String.format(" %d. %s\n", pos++, name));
}
return names.toString();
}

/**
* Get the number of checks. This is used for the `-c` option.
*/
public static int getNumberOfChecks() {
return checks.size();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.healthreport;

import org.apache.commons.cli.Options;
import org.dspace.scripts.configuration.ScriptConfiguration;

/**
* This class represents a HealthReport that is used in the CLI.
* @author Matus Kasak (dspace at dataquest.sk)
*/
public class HealthReportScriptConfiguration<T extends HealthReport> extends ScriptConfiguration<T> {

private Class<T> dspaceRunnableclass;

@Override
public Class<T> getDspaceRunnableClass() {
return dspaceRunnableclass;
}

@Override
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
this.dspaceRunnableclass = dspaceRunnableClass;
}

@Override
public Options getOptions() {
if (options == null) {
Options options = new Options();
options.addOption("i", "info", false,
"Show help information.");
options.addOption("e", "email", true,
"Send report to this email address.");
options.getOption("e").setType(String.class);
options.addOption("c", "check", true,
String.format("Perform only specific check (use index from 0 to %d, " +
"otherwise perform default checks).", HealthReport.getNumberOfChecks() - 1));
options.getOption("c").setType(String.class);
options.addOption("f", "for", true,
"Report for last N days. Used only in general information for now.");
options.getOption("f").setType(String.class);
options.addOption("o", "output", true,
"Save report to the file.");

super.options = options;
}
return options;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ProvenanceService;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
Expand Down Expand Up @@ -51,6 +52,12 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
@Autowired
private GroupService groupService;

@Autowired
ProvenanceService provenanceService;

@Autowired
ResourcePolicyService resourcePolicyService;

protected ResourcePolicyServiceImpl() {
}

Expand Down Expand Up @@ -233,12 +240,17 @@ public void removePolicies(Context c, DSpaceObject o, String type) throws SQLExc
}

@Override
public void removePolicies(Context c, DSpaceObject o, String type, int action)
throws SQLException, AuthorizeException {
public void removePolicies(Context c, DSpaceObject o, String type, int action)
throws SQLException, AuthorizeException {
// Get all read policies of the dso before removing them
List<ResourcePolicy> resPolicies = resourcePolicyService.find(c, o, type);

resourcePolicyDAO.deleteByDsoAndTypeAndAction(c, o, type, action);
c.turnOffAuthorisationSystem();
contentServiceFactory.getDSpaceObjectService(o).updateLastModified(c, o);
c.restoreAuthSystemState();

provenanceService.removeReadPolicies(c, o, resPolicies);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.dspace.content.service.RelationshipService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ProvenanceService;
import org.dspace.handle.service.HandleService;
import org.dspace.identifier.service.IdentifierService;
import org.dspace.utils.DSpace;
Expand Down Expand Up @@ -67,6 +68,8 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
protected MetadataAuthorityService metadataAuthorityService;
@Autowired(required = true)
protected RelationshipService relationshipService;
@Autowired(required = true)
protected ProvenanceService provenanceService;

public DSpaceObjectServiceImpl() {

Expand Down Expand Up @@ -377,6 +380,7 @@ public void clearMetadata(Context context, T dso, String schema, String element,
}
}
dso.setMetadataModified();
provenanceService.removeMetadata(context, dso, schema, element, qualifier);
}

@Override
Expand Down
Loading