Skip to content

Commit

Permalink
Merge branch 'develop' into 7059-openaire
Browse files Browse the repository at this point in the history
  • Loading branch information
sekmiller committed Jul 21, 2020
2 parents 63f8008 + 941d17d commit f3f7a38
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 38 deletions.
2 changes: 1 addition & 1 deletion doc/sphinx-guides/Makefile
Expand Up @@ -2,7 +2,7 @@
#

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXOPTS = -W
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
Expand Down
@@ -0,0 +1,8 @@
{
"id":"orcid-public",
"factoryAlias":"oauth2",
"title":"ORCID",
"subtitle":"",
"factoryData":"type: orcid | userEndpoint: https://pub.orcid.org/v2.1/{ORCID}/person | clientId: FIXME | clientSecret: FIXME",
"enabled":true
}
4 changes: 3 additions & 1 deletion doc/sphinx-guides/source/developers/deployment.rst
Expand Up @@ -82,7 +82,9 @@ Download and Run the "Create Instance" Script

Once you have done the configuration above, you are ready to try running the "ec2-create-instance.sh" script to spin up Dataverse in AWS.

Download :download:`ec2-create-instance.sh<https://raw.githubusercontent.com/GlobalDataverseCommunityConsortium/dataverse-ansible/master/ec2/ec2-create-instance.sh>` and put it somewhere reasonable. For the purpose of these instructions we'll assume it's in the "Downloads" directory in your home directory.
Download `ec2-create-instance.sh`_ and put it somewhere reasonable. For the purpose of these instructions we'll assume it's in the "Downloads" directory in your home directory.

.. _ec2-create-instance.sh: https://raw.githubusercontent.com/GlobalDataverseCommunityConsortium/dataverse-ansible/master/ec2/ec2-create-instance.sh

To run it with default values you just need the script, but you may also want a current copy of the ansible `group vars <https://raw.githubusercontent.com/GlobalDataverseCommunityConsortium/dataverse-ansible/master/defaults/main.yml>`_ file.

Expand Down
7 changes: 4 additions & 3 deletions doc/sphinx-guides/source/installation/oauth2.rst
Expand Up @@ -26,11 +26,11 @@ Identity Provider Side
Obtain Client ID and Client Secret
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Before OAuth providers will release information about their users (first name, last name, etc.) to your Dataverse installation, you must request a "Client ID" and "Client Secret" from them. In the case of GitHub and Google, this is as simple as clicking a few buttons and there is no cost associated with using their authentication service. ORCID and Microsoft, on the other hand, do not have an automated system for requesting these credentials, and it is not free to use these authentication services.
Before OAuth providers will release information about their users (first name, last name, etc.) to your Dataverse installation, you must request a "Client ID" and "Client Secret" from them. In many cases you can use providers' automated system to request these credentials, but if not, contact the provider for assistance.

URLs to help you request a Client ID and Client Secret from the providers supported by Dataverse are provided below. For all of these providers, it's a good idea to request the Client ID and Client secret using a generic account, perhaps the one that's associated with the ``:SystemEmail`` you've configured for Dataverse, rather than your own personal Microsoft Azure AD, ORCID, GitHub, or Google account:

- ORCID: https://orcid.org/content/register-client-application-production-trusted-party
- ORCID: https://orcid.org/content/register-client-application-0
- Microsoft: https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code
- GitHub: https://github.com/settings/applications/new via https://developer.github.com/v3/oauth/
- Google: https://console.developers.google.com/projectselector/apis/credentials via https://developers.google.com/identity/protocols/OAuth2WebServer (pick "OAuth client ID")
Expand All @@ -51,7 +51,8 @@ As explained under "Auth Modes" in the :doc:`config` section, available authenti

We will ``POST`` a JSON file containing the Client ID and Client Secret to this ``authenticationProviders`` API endpoint to add another authentication provider. As a starting point, you'll want to download the JSON template file matching the provider you're setting up:

- :download:`orcid.json <../_static/installation/files/root/auth-providers/orcid.json>`
- :download:`orcid-public.json <../_static/installation/files/root/auth-providers/orcid-public.json>`
- :download:`orcid-member.json <../_static/installation/files/root/auth-providers/orcid-member.json>`
- :download:`github.json <../_static/installation/files/root/auth-providers/github.json>`
- :download:`google.json <../_static/installation/files/root/auth-providers/google.json>`
- :download:`microsoft.json <../_static/installation/files/root/auth-providers/microsoft.json>`
Expand Down
159 changes: 154 additions & 5 deletions src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Expand Up @@ -309,6 +309,14 @@ public enum DisplayMode {
private Boolean hasRsyncScript = false;

private Boolean hasTabular = false;

/**
* If the dataset version has at least one tabular file. The "hasTabular"
* boolean is for the dataset level ("has ever had a tabular file") but
* sometimes you want to know about the current version ("no tabular files
* currently"). Like all files, tabular files can be deleted.
*/
private boolean versionHasTabular = false;

private boolean showIngestSuccess;

Expand Down Expand Up @@ -2037,7 +2045,18 @@ private String init(boolean initFull) {

displayLockInfo(dataset);

for (FileMetadata fmd : workingVersion.getFileMetadatas()) {
if (fmd.getDataFile().isTabularData()) {
versionHasTabular = true;
break;
}
}
for(DataFile f : dataset.getFiles()) {
// TODO: Consider uncommenting this optimization.
// if (versionHasTabular) {
// hasTabular = true;
// break;
// }
if(f.isTabularData()) {
hasTabular = true;
break;
Expand Down Expand Up @@ -2257,8 +2276,11 @@ private DefaultTreeNode createFileTreeNode(FileMetadata fileMetadata, TreeNode p
public boolean isHasTabular() {
return hasTabular;
}



public boolean isVersionHasTabular() {
return versionHasTabular;
}

public boolean isReadOnly() {
return readOnly;
}
Expand Down Expand Up @@ -2886,8 +2908,43 @@ public List<FileMetadata> getSelectedNonDownloadableFiles() {
public void setSelectedNonDownloadableFiles(List<FileMetadata> selectedNonDownloadableFiles) {
this.selectedNonDownloadableFiles = selectedNonDownloadableFiles;
}



private List<FileMetadata> selectedNonDownloadallableFiles;

public List<FileMetadata> getSelectedNonDownloadallableFiles() {
return selectedNonDownloadallableFiles;
}

public void setSelectedNonDownloadallableFiles(List<FileMetadata> selectedNonDownloadallableFiles) {
this.selectedNonDownloadallableFiles = selectedNonDownloadallableFiles;
}

public String getSizeOfDataset() {
boolean original = false;
return DatasetUtil.getDownloadSize(workingVersion, original);
}

public String getSizeOfDatasetOrig() {
boolean original = true;
return DatasetUtil.getDownloadSize(workingVersion, original);
}

public void validateAllFilesForDownloadArchival() {
boolean guestbookRequired = isDownloadPopupRequired();
boolean downloadOriginal = false;
validateFilesForDownloadAll(guestbookRequired, downloadOriginal);
}

/**
* Can result in "requested optional service" error. For non-tabular files
* it's safer to use validateAllFilesForDownloadArchival.
*/
public void validateAllFilesForDownloadOriginal() {
boolean guestbookRequired = isDownloadPopupRequired();
boolean downloadOriginal = true;
validateFilesForDownloadAll(guestbookRequired, downloadOriginal);
}

public void validateFilesForDownload(boolean guestbookRequired, boolean downloadOriginal){
setSelectedDownloadableFiles(new ArrayList<>());
setSelectedNonDownloadableFiles(new ArrayList<>());
Expand Down Expand Up @@ -2951,7 +3008,77 @@ public void validateFilesForDownload(boolean guestbookRequired, boolean download
}

}


/**
* This method borrows heavily from validateFilesForDownload but does not
* use the selectedFiles field.
*/
public void validateFilesForDownloadAll(boolean guestbookRequired, boolean downloadOriginal) {
setSelectedNonDownloadallableFiles(new ArrayList<>());
List<FileMetadata> downloadableFiles = new ArrayList<>();
for (FileMetadata fmd : workingVersion.getFileMetadatas()) {
if (this.fileDownloadHelper.canDownloadFile(fmd)) {
downloadableFiles.add(fmd);
} else {
getSelectedNonDownloadallableFiles().add(fmd);
}
}

// If some of the files were restricted and we had to drop them off the
// list, and NONE of the files are left on the downloadable list
// - we show them a "you're out of luck" popup:
if (downloadableFiles.isEmpty() && !getSelectedNonDownloadallableFiles().isEmpty()) {
//RequestContext requestContext = RequestContext.getCurrentInstance();
PrimeFaces.current().executeScript("PF('downloadInvalid').show()");
return;
}

// Note that the GuestbookResponse object may still have information from
// the last download action performed by the user. For example, it may
// still have the non-null Datafile in it, if the user has just downloaded
// a single file; or it may still have the format set to "original" -
// even if that's not what they are trying to do now.
// So make sure to reset these values:
guestbookResponse.setDataFile(null);
// Inline getSelectedDownloadableFilesIdsString() that doesn't use selectedDownloadableFiles
String downloadIdString = "";
for (FileMetadata fmd : downloadableFiles) {
if (!StringUtil.isEmpty(downloadIdString)) {
downloadIdString += ",";
}
downloadIdString += fmd.getDataFile().getId();
}
guestbookResponse.setSelectedFileIds(downloadIdString);
if (downloadOriginal) {
guestbookResponse.setFileFormat("original");
} else {
guestbookResponse.setFileFormat("");
}
guestbookResponse.setDownloadtype("Download");

// If we have a bunch of files that we can download, AND there were no files
// that we had to take off the list, because of permissions - we can
// either send the user directly to the download API (if no guestbook/terms
// popup is required), or send them to the download popup:
if (!downloadableFiles.isEmpty() && getSelectedNonDownloadallableFiles().isEmpty()) {
if (guestbookRequired) {
openDownloadPopupForDownloadAll();
} else {
startMultipleFileDownload();
}
return;
}

// ... and if some files were restricted, but some are downloadable,
// we are showing them this "you are somewhat in luck" popup; that will
// then direct them to the download, or popup, as needed:
if (!downloadableFiles.isEmpty() && !getSelectedNonDownloadallableFiles().isEmpty()) {
//RequestContext requestContext = RequestContext.getCurrentInstance();
PrimeFaces.current().executeScript("PF('downloadAllMixed').show()");
}

}

private boolean selectAllFiles;

public boolean isSelectAllFiles() {
Expand Down Expand Up @@ -4073,6 +4200,28 @@ public void openDownloadPopupForMultipleFileDownload() {
//RequestContext requestContext = RequestContext.getCurrentInstance();
PrimeFaces.current().executeScript("PF('downloadPopup').show();handleResizeDialog('downloadPopup');");
}

/**
* This method borrows heavily from
* openDownloadPopupForMultipleFileDownload. It does not use the
* selectedFiles field.
*/
public void openDownloadPopupForDownloadAll() {
// This is commented out because "download all" doesn't use selectedFiles.
// if (this.selectedFiles.isEmpty()) {
// //RequestContext requestContext = RequestContext.getCurrentInstance();
// PrimeFaces.current().executeScript("PF('selectFilesForDownload').show()");
// return;
// }

// There's a chance that this is not really a batch download - i.e.,
// there may only be one file on the downloadable list. But the fileDownloadService
// method below will check for that, and will redirect to the single download, if
// that's the case. -- L.A.
this.guestbookResponse.setDownloadtype("Download");
//RequestContext requestContext = RequestContext.getCurrentInstance();
PrimeFaces.current().executeScript("PF('downloadPopup').show();handleResizeDialog('downloadPopup');");
}

public void initGuestbookMultipleResponse(String selectedFileIds){
initGuestbookResponse(null, "download", selectedFileIds);
Expand Down
Expand Up @@ -55,7 +55,13 @@ public class OrcidOAuth2AP extends AbstractOAuth2AuthenticationProvider {
public static final String PROVIDER_ID_SANDBOX = "orcid-sandbox";

public OrcidOAuth2AP(String clientId, String clientSecret, String userEndpoint) {
scope = Arrays.asList("/read-limited");

if(userEndpoint != null && userEndpoint.startsWith("https://pub")) {
this.scope = Arrays.asList("/authenticate");
} else {
this.scope = Arrays.asList("/read-limited");
}

this.clientId = clientId;
this.clientSecret = clientSecret;
this.baseUserEndpoint = userEndpoint;
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/dataset/DatasetUtil.java
Expand Up @@ -34,6 +34,7 @@
import static edu.harvard.iq.dataverse.dataaccess.DataAccess.getStorageIO;
import static edu.harvard.iq.dataverse.dataaccess.DataAccess.getStorageIO;
import static edu.harvard.iq.dataverse.dataaccess.DataAccess.getStorageIO;
import edu.harvard.iq.dataverse.datasetutility.FileSizeChecker;

public class DatasetUtil {

Expand Down Expand Up @@ -440,4 +441,24 @@ public static List<DatasetField> getDatasetSummaryFields(DatasetVersion datasetV
return datasetFields;
}

/**
* Given a dataset version, return it's size in human readable units such as
* 42.9 MB.There is a GetDatasetStorageSizeCommand but it's overly complex
* for the use case.
*
* @param original Use the original file size rather than the archival file
* size for tabular files.
*/
public static String getDownloadSize(DatasetVersion dsv, boolean original) {
long bytes = 0l;
for (FileMetadata fileMetadata : dsv.getFileMetadatas()) {
DataFile dataFile = fileMetadata.getDataFile();
if (original && dataFile.isTabularData()) {
bytes += dataFile.getOriginalFileSize();
} else {
bytes += dataFile.getFilesize();
}
}
return FileSizeChecker.bytesToHumanReadable(bytes);
}
}
Expand Up @@ -204,7 +204,6 @@ public boolean onSuccess(CommandContext ctxt, Object r) {
retVal = false;
}

ctxt.solrIndex().indexPermissionsForOneDvObject(dataset);
exportMetadata(dataset, ctxt.settings());
ctxt.datasets().updateLastExportTimeStamp(dataset.getId());
return retVal;
Expand Down
Expand Up @@ -405,8 +405,6 @@ public IndexResponse indexPermissionsOnSelfAndChildren(DvObject definitionPoint)
}
}
} else if (definitionPoint.isInstanceofDataset()) {
// index the dataset itself
indexPermissionsForOneDvObject(definitionPoint);
dvObjectsToReindexPermissionsFor.add(definitionPoint);
// index files
Dataset dataset = (Dataset) definitionPoint;
Expand All @@ -425,22 +423,15 @@ public IndexResponse indexPermissionsOnSelfAndChildren(DvObject definitionPoint)
*/
String response = reindexFilesInBatches(filesToReindexAsBatch);

List<String> updatePermissionTimeSuccessStatus = new ArrayList<>();
for (DvObject dvObject : dvObjectsToReindexPermissionsFor) {
/**
* @todo do something with this response
*/
IndexResponse indexResponse = indexPermissionsForOneDvObject(dvObject);
DvObject managedDefinitionPoint = dvObjectService.updatePermissionIndexTime(definitionPoint);
boolean updatePermissionTimeSuccessful = false;
if (managedDefinitionPoint != null) {
updatePermissionTimeSuccessful = true;
}
updatePermissionTimeSuccessStatus.add(dvObject + ":" + updatePermissionTimeSuccessful);
}

return new IndexResponse("Number of dvObject permissions indexed for " + definitionPoint
+ " (updatePermissionTimeSuccessful:" + updatePermissionTimeSuccessStatus
+ "): " + dvObjectsToReindexPermissionsFor.size()
+ ": " + dvObjectsToReindexPermissionsFor.size()
);
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/propertyFiles/Bundle.properties
Expand Up @@ -1219,6 +1219,7 @@ dataset.accessBtn=Access Dataset
dataset.accessBtn.header.download=Download Options
dataset.accessBtn.header.explore=Explore Options
dataset.accessBtn.header.compute=Compute Options
dataset.accessBtn.download.size=ZIP ({0})
dataset.linkBtn=Link Dataset
dataset.contactBtn=Contact Owner
dataset.shareBtn=Share
Expand Down

0 comments on commit f3f7a38

Please sign in to comment.