Skip to content

Commit

Permalink
Merge branch 'develop' into fdias-2519-change-doi-status-to-registere…
Browse files Browse the repository at this point in the history
…d-on-deaccession
  • Loading branch information
diasf authored Sep 5, 2024
2 parents dfc1b18 + abaddea commit 2736730
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3078,7 +3078,8 @@ uningest.table.unf=UNF of ingested file
uningest.table.actions=Action
uningest.table.uningest.button=Uningest
uningest.dialog.title=Confirm uningest
uningest.dialog.text=Do you really want to uningest the file named "{0}"?
uningest.dialog.text=Do you really want to uningest the selected files?
uningest.error=Could not uningest the following files

add.dataset.button=Add dataset
add.dataset.dialog.header=Select dataverse
Expand Down
21 changes: 11 additions & 10 deletions dataverse-persistence/src/main/resources/Bundle_pl.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2334,8 +2334,8 @@ mydataFragment.errorMessage.NoUserSelected=Przykro mi! U\u017Cytkownik nie zosta
mydataFragment.errorMessage.UnknownType.Prefix=Przykro mi! Typ '
mydataFragment.errorMessage.UnknownType.Suffix=' jest nieznany.

file.provenance=Pochodzenie
file.editProvenanceDialog=Pochodzenie
file.provenance=Proweniencja
file.editProvenanceDialog=Proweniencja
file.editProvenanceDialog.tip=Proweniencja to zapis \u017Ar\u00F3d\u0142a Twojego pliku danych i wszelkich transformacji, jakie przeszed\u0142. Prze\u015Blij plik JSON z narz\u0119dzia do przechwytywania proweniencji w celu wygenerowania grafu proweniencji swoich danych. Wi\u0119cej informacji mo\u017Cna znale\u017A\u0107 w <a href="{0}/{1}/user/index.html" title="Dataverse User Guide" target="_blank">Podr\u0119czniku u\u017Cytkownika</a>.
file.editProvenanceDialog.upload.invalidFile=Nie mo\u017Cna przes\u0142a\u0107 pliku. Spr\u00F3buj ponownie u\u017Cywaj\u0105c pliku w formacie JSON.
file.editProvenanceDialog.uploadSuccess=Przesy\u0142anie uko\u0144czone
Expand All @@ -2344,7 +2344,7 @@ file.editProvenanceDialog.noEntitiesError=Przes\u0142any plik z rejestrem prowen
file.editProvenanceDialog.invalidSchemaError=Przes\u0142any plik z rejestrem proweniencji nie jest zgodny ze standardem PROV W3C.
file.editProvenanceDialog.bundleFile=Plik z rejestrem proweniencji
file.editProvenanceDialog.bundleFile.instructions=Plik musi by\u0107 w formacie JSON i spe\u0142nia\u0107 wymogi <a href="https://www.w3.org/Submission/2013/SUBM-prov-json-20130424/" target="_blank">standardu W3C</a>.
file.editProvenanceDialog.bundleFile.alreadyPublished=Ten plik z rejestrem pochodzenia zosta\u0142 opublikowany i nie mo\u017Cna go zast\u0105pi\u0107 ani usun\u0105\u0107.
file.editProvenanceDialog.bundleFile.alreadyPublished=Ten plik z rejestrem proweniencji zosta\u0142 opublikowany i nie mo\u017Cna go zast\u0105pi\u0107 ani usun\u0105\u0107.
file.editProvenanceDialog.bundleEntity=Jednostka (entity) pliku danych
file.editProvenanceDialog.bundleEntity.placeholder=Po\u0142\u0105cz jednostk\u0119 (entity)\u2026
file.editProvenanceDialog.bundleEntity.requiredValidation=Warto\u015B\u0107 jest wymagana
Expand All @@ -2354,10 +2354,10 @@ file.editProvenanceDialog.bundleEntity.typeHeader=Typ
file.editProvenanceDialog.bundleEntity.entityHeader=Jednostka (entity)
file.editProvenanceDialog.selectToAddBtn=Wybierz plik
file.editProvenanceDialog.description.tip=Mo\u017Cesz r\u00F3wnie\u017C doda\u0107 dokumentacj\u0119 historii Twojego pliku danych, zawieraj\u0105c\u0105 informacje o tym, jak powsta\u0142, jak si\u0119 zmienia\u0142 i kto nad nim pracowa\u0142.
file.editProvenanceDialog.description=Opis pochodzenia
file.editProvenanceDialog.description.placeholder=Dodaj opis pochodzenia
file.confirmProvenanceDialog=Pochodzenie
file.confirmProvenanceDialog.tip1=Po opublikowaniu tego pliku danych, Twojego pliku z rejestrem pochodzenia nie b\u0119dzie mo\u017Cna edytowa\u0107, ani zast\u0105pi\u0107.
file.editProvenanceDialog.description=Opis proweniencji
file.editProvenanceDialog.description.placeholder=Dodaj opis proweniencji
file.confirmProvenanceDialog=Proweniencja
file.confirmProvenanceDialog.tip1=Po opublikowaniu tego pliku danych, Twojego pliku z rejestrem proweniencji nie b\u0119dzie mo\u017Cna edytowa\u0107, ani zast\u0105pi\u0107.
file.confirmProvenanceDialog.tip2=Wybierz "Anuluj" by powr\u00F3ci\u0107 do poprzedniej strony, gdzie mo\u017Cesz obejrze\u0107 podgl\u0105d swojego pliku z rejestrem proweniencji, by potwierdzi\u0107 jego poprawno\u015B\u0107.
file.metadataTab.provenance.header=Proweniencja pliku
file.metadataTab.provenance.body=Informacja o proweniencji pliku, kt\u00F3ra pojawi si\u0119 w p\u00F3\u017Aniejszej wersji\u2026
Expand All @@ -2370,8 +2370,8 @@ file.provConfirm.empty=Nie dokonano \u017Cadnych zmian.
file.provAlert.published.json=Zmiany w Twoim pliku z rejestrem proweniencji zosta\u0142y zapisane w zbiorze danych.
file.provAlert.unpublished.json=Zmiany w Twoim pliku z rejestrem proweniencji zostan\u0105 zapisane w tej wersji zbioru danych po naci\u015Bni\u0119ciu przycisku "Zapisz zmiany".
file.provAlert.freeform=Zmiany w opisie proweniencji zostan\u0105 zapisane w tej wersji zbioru danych po naci\u015Bni\u0119ciu przycisku "Zapisz zmiany".
file.provAlert.filePage.published.json=Zmiany w Twoim pliku z rejestrem pochodzenia zosta\u0142y zapisane w zbiorze danych.
file.provAlert.filePage.unpublished.json=Zmiany w Twoim pliku z rejestrem pochodzenia zosta\u0142y zapisane w tej wersji zbioru danych.
file.provAlert.filePage.published.json=Zmiany w Twoim pliku z rejestrem proweniencji zosta\u0142y zapisane w zbiorze danych.
file.provAlert.filePage.unpublished.json=Zmiany w Twoim pliku z rejestrem proweniencji zosta\u0142y zapisane w tej wersji zbioru danych.
file.provAlert.filePage.freeform=Zmiany w opisie proweniencji zosta\u0142y zapisane w tej wersji zbioru danych.

api.prov.provJsonSaved=Zapisano rejestr proweniencji PROV-JSON dla pliku danych:
Expand Down Expand Up @@ -3029,7 +3029,8 @@ uningest.table.unf=UNF zanalizowanego pliku
uningest.table.actions=Akcje
uningest.table.uningest.button=Cofnij analiz\u0119
uningest.dialog.title=Potwierd\u017A cofni\u0119cie analizy
uningest.dialog.text=Czy na pewno chcesz cofn\u0105\u0107 analiz\u0119 pliku o nazwie "{0}"?
uningest.dialog.text=Czy na pewno chcesz cofn\u0105\u0107 analiz\u0119 dla zaznaczonych plik\u00F3w?
uningest.error=Nie uda\u0142o si\u0119 cofn\u0105\u0107 analiz\u0119 dla nast\u0119puj\u0105cych plik\u00F3w

add.dataset.button=Dodaj zbi\u00F3r danych
add.dataset.dialog.header=Wybierz kolekcj\u0119
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package edu.harvard.iq.dataverse;

import edu.harvard.iq.dataverse.util.SystemConfig;

import javax.inject.Inject;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.SessionCookieConfig;
import java.util.logging.Logger;

@WebListener
public class DataverseSessionConfigListener implements ServletContextListener {
private final SystemConfig systemConfig;
private static final Logger logger = Logger.getLogger(DataverseSessionConfigListener.class.getCanonicalName());

@Inject
public DataverseSessionConfigListener(SystemConfig systemConfig) {
this.systemConfig = systemConfig;
}

@Override
public void contextInitialized(ServletContextEvent sce) {
logger.info("Initializing session cookie configuration");
SessionCookieConfig sessionCookieConfig = sce.getServletContext().getSessionCookieConfig();
String cookieName = systemConfig.getCookieName();
if (cookieName != null && !cookieName.isEmpty()) {
logger.info("Setting session cookie name to " + cookieName);
sessionCookieConfig.setName(cookieName);
}
String cookieDomain = systemConfig.getCookieDomain();
if (cookieDomain != null && !cookieName.isEmpty()) {
logger.info("Setting session cookie domain to " + cookieDomain);
sessionCookieConfig.setDomain(cookieDomain);
}
Boolean cookieSecure = systemConfig.getCookieSecure();
if (cookieSecure != null && !cookieName.isEmpty()) {
logger.info("Setting session cookie secure to " + cookieSecure);
sessionCookieConfig.setSecure(cookieSecure);
}
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
// nothing to do here
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
Expand All @@ -31,6 +32,7 @@
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
* @author xyang
Expand Down Expand Up @@ -184,7 +186,12 @@ public String login() {
}

logger.log(Level.FINE, "Sending user to = {0}", redirectPage);
return redirectPage + (!redirectPage.contains("?") ? "?" : "&") + "faces-redirect=true";

if(validateIsRedirectUrlAnExternalResource(redirectPage)) {
return redirectToExternalResource();
} else {
return redirectPage + (!redirectPage.contains("?") ? "?" : "&") + "faces-redirect=true";
}
} catch (AuthenticationFailedException ex) {
numFailedLoginAttempts++;
op1 = random.nextInt(10);
Expand Down Expand Up @@ -212,6 +219,15 @@ public String login() {
}
}

boolean validateIsRedirectUrlAnExternalResource(String urlToValidate) {
boolean result = Pattern.compile("^(https?)://[^\\s/$.?#].[^\\s]*$",
Pattern.CASE_INSENSITIVE).matcher(urlToValidate).matches();
if(!result) {
logger.severe("Invalid redirect URL: " + urlToValidate + ". Redirect URL must start with http:// or https://");
}
return result;
}

public void resetFilledCredentials(AjaxBehaviorEvent event) {
if (selectedCredentialsProvider() == null) {
return;
Expand Down Expand Up @@ -278,6 +294,28 @@ private String redirectToRoot() {
return "dataverse.xhtml?alias=" + dataverseDao.findRootDataverse().getAlias();
}

private String redirectToExternalResource() {
try {
logger.info("Trying to redirect to external page: " + redirectPage);
if(systemConfig.getAllowedExternalRedirectionUrl() == null || systemConfig.getAllowedExternalRedirectionUrl().isEmpty()) {
logger.severe("External redirection not allowed.");
} else if(redirectPage.startsWith(systemConfig.getAllowedExternalRedirectionUrl())) {
FacesContext.getCurrentInstance().getExternalContext().redirect(redirectPage);
} else {
logger.severe("Chosen redirect page " + redirectPage + " is not allowed. " +
"Allowed pages: " + systemConfig.getAllowedExternalRedirectionUrl());
}
} catch (IOException e) {
logger.severe("Unable to redirect to external page "+ e.getMessage());
}
// Internal Redirection: Uses navigation handling in JSF, where returning
// a string tells JSF which page to navigate to next.
// External Redirection: Directly interacts with the HTTP response to send a redirect.
// No string return is necessary because the redirection is handled immediately
// by the ExternalContext.redirect() method.
return "";
}

// -------------------- SETTERS --------------------

public void setSelectedSamlIdpId(Long selectedSamlIdpId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.harvard.iq.dataverse;

import edu.harvard.iq.dataverse.common.BundleUtil;
import edu.harvard.iq.dataverse.ingest.UningestInfoService;
import edu.harvard.iq.dataverse.ingest.UningestService;
import edu.harvard.iq.dataverse.persistence.datafile.DataFile;
Expand All @@ -11,7 +12,11 @@
import edu.harvard.iq.dataverse.util.SystemConfig;
import org.apache.commons.lang.StringUtils;
import org.omnifaces.cdi.ViewScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
Expand All @@ -23,6 +28,7 @@
@Named("UningestPage")
public class UningestPage implements Serializable {

private static final Logger log = LoggerFactory.getLogger(UningestPage.class);
private UningestService uningestService;
private DatasetRepository datasetRepository;
private DataverseSession dataverseSession;
Expand All @@ -33,7 +39,7 @@ public class UningestPage implements Serializable {
private UningestInfoService uningestInfoService;

private List<UningestableItem> uningestableFiles = new ArrayList<>();
private UningestableItem toUningest;
private List<UningestableItem> selectedFiles = new ArrayList<>();

private Long datasetId;
private Dataset dataset;
Expand All @@ -51,9 +57,9 @@ public Dataset getDataset() {
public List<UningestableItem> getUningestableFiles() {
return uningestableFiles;
}
public UningestableItem getToUningest() {
return toUningest;

public List<UningestableItem> getSelectedFiles() {
return selectedFiles;
}

// -------------------- CONSTRUCTORS --------------------
Expand Down Expand Up @@ -96,17 +102,33 @@ public String init() {
return permissionsWrapper.notFound();
}
uningestableFiles.addAll(prepareItemList());
selectedFiles.clear();
return StringUtils.EMPTY;
}

public void uningest() {
if (toUningest == null || !dataverseSession.getUser().isAuthenticated()) {
if (selectedFiles.isEmpty() || !dataverseSession.getUser().isAuthenticated()) {
return;
}

AuthenticatedUser user = (AuthenticatedUser) dataverseSession.getUser();
uningestService.uningest(toUningest.getDataFile(), user);
List<String> uningestFailedFileNames = new ArrayList<>();
selectedFiles.forEach(toUningest -> {
try {
uningestService.uningest(toUningest.getDataFile(), user);
} catch (Exception e) {
log.error("Could not uningest data file: {}", toUningest.getDataFile().getId(), e);
uningestFailedFileNames.add(toUningest.getFileName());
}
});
uningestableFiles = prepareItemList();
toUningest = null;
selectedFiles.clear();

if (!uningestFailedFileNames.isEmpty()) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
BundleUtil.getStringFromBundle("uningest.error"),
uningestFailedFileNames.stream().collect(Collectors.joining(", ", "[", "]. "))));
}
}

public String cancel() {
Expand All @@ -127,8 +149,8 @@ public void setDatasetId(Long datasetId) {
this.datasetId = datasetId;
}

public void setToUningest(UningestableItem toUningest) {
this.toUningest = toUningest;
public void setSelectedFiles(List<UningestableItem> selectedFiles) {
this.selectedFiles = selectedFiles;
}

// -------------------- INNER CLASSES --------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ public enum Key {
* Location and name of Footer customization file
*/
FooterCustomizationFile,
/**
* Additional links to be shown in the footer.
*/
FooterAdditionalUrl,
/**
* Location and name of CSS customization file (it will be used as an inline style)
*/
Expand Down Expand Up @@ -737,7 +741,13 @@ public enum Key {
* Additional (localized) text to show at the top
* of the "Add dataset" modal window.
*/
SelectDataverseInfo
SelectDataverseInfo,

CookieDomain,
CookieName,
CookieSecure,

AllowedExternalRedirectionUrlAfterLogin
;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public class SettingsWrapper implements java.io.Serializable {
SystemConfig systemConfig;

private final LazyLoaded<Map<String, String>> configuredLocales = new LazyLoaded<>(this::languagesLoader);
private final LazyLoaded<Map<String, String>> configuredAboutUrls = new LazyLoaded<>(this::aboutUrlsLoader);
private final LazyLoaded<Map<String, String>> configuredAboutUrls = new LazyLoaded<>(() -> urlsLoader(SettingsServiceBean.Key.NavbarAboutUrl));
private final LazyLoaded<Map<String, String>> configuredFooterUrls = new LazyLoaded<>(() -> urlsLoader(SettingsServiceBean.Key.FooterAdditionalUrl));

// -------------------- GETTERS --------------------

Expand Down Expand Up @@ -122,6 +123,10 @@ public Map<String, String> getConfiguredAboutUrls() {
return configuredAboutUrls.get();
}

public Map<String, String> getConfiguredFooterUrls() {
return configuredFooterUrls.get();
}

public boolean isDataCiteInstallation() {
String protocol = getEnumSettingValue(SettingsServiceBean.Key.DoiProvider);
return "DataCite".equals(protocol);
Expand All @@ -134,9 +139,9 @@ private Map<String, String> languagesLoader() {
.collect(toMap(getKey("locale"), getKey("title"), throwingMerger(), LinkedHashMap::new));
}

private Map<String, String> aboutUrlsLoader() {
private Map<String, String> urlsLoader(SettingsServiceBean.Key key) {
String lang = FacesContext.getCurrentInstance().getViewRoot().getLocale().getLanguage();
return settingService.getValueForKeyAsListOfMaps(SettingsServiceBean.Key.NavbarAboutUrl).stream()
return settingService.getValueForKeyAsListOfMaps(key).stream()
.collect(toMap(getKey("url"), getKey("title." + lang), throwingMerger(), LinkedHashMap::new));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,23 @@ public String getSelectDataverseInfo(Locale locale) {
return getLocalizedProperty(SettingsServiceBean.Key.SelectDataverseInfo, locale);
}


public String getAllowedExternalRedirectionUrl() {
return settingsService.getValueForKey(SettingsServiceBean.Key.AllowedExternalRedirectionUrlAfterLogin);
}

public String getCookieName() {
return settingsService.getValueForKey(Key.CookieName);
}

public String getCookieDomain() {
return settingsService.getValueForKey(Key.CookieDomain);
}

public Boolean getCookieSecure() {
return Boolean.parseBoolean(settingsService.getValueForKey(Key.CookieSecure));
}

public long getTabularIngestSizeLimit() {
// This method will return the blanket ingestable size limit, if
// set on the system. I.e., the universal limit that applies to all
Expand Down
Loading

0 comments on commit 2736730

Please sign in to comment.