diff --git a/doc/release-notes/12141-storage-driver-endpoints.md b/doc/release-notes/12141-storage-driver-endpoints.md new file mode 100644 index 00000000000..614d3c2f3b1 --- /dev/null +++ b/doc/release-notes/12141-storage-driver-endpoints.md @@ -0,0 +1,6 @@ +### Breaking Changes + +All the endpoints related to Storage Drivers have been moved out of the Admin API. + +- The endpoints GET, PUT AND DELETE for `/api/admin/dataverse/{alias}/storageDriver` has been moved to `/api/dataverses/{alias}/storageDriver`. +- The endpoint `/api/admin/dataverse/storageDrivers` has been moved and renamed to `/api/dataverses/{alias}/allowedStorageDrivers`. Regarding the change of the name, this endpoint will in the future only display the storageDrivers that are allowed on the specified collection, as of now, it will display the entire list of available Drivers on the installation. diff --git a/doc/sphinx-guides/source/admin/dataverses-datasets.rst b/doc/sphinx-guides/source/admin/dataverses-datasets.rst index c916b79aaa8..48481b414bf 100644 --- a/doc/sphinx-guides/source/admin/dataverses-datasets.rst +++ b/doc/sphinx-guides/source/admin/dataverses-datasets.rst @@ -52,17 +52,17 @@ Configure a Dataverse Collection to Store All New Files in a Specific File Store To direct new files (uploaded when datasets are created or edited) for all datasets in a given Dataverse collection, the store can be specified via the API as shown below, or by editing the 'General Information' for a Dataverse collection on the Dataverse collection page. Only accessible to superusers. :: - curl -H "X-Dataverse-key: $API_TOKEN" -X PUT -d $storageDriverLabel http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver + curl -H "X-Dataverse-key: $API_TOKEN" -X PUT -d $storageDriverLabel http://$SERVER/api/dataverses/$dataverse-alias/storageDriver (Note that for ``dataverse.files.store1.label=MyLabel``, you should pass ``MyLabel``.) A store assigned directly to a collection can be seen using:: - curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver + curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/dataverses/$dataverse-alias/storageDriver This may be null. To get the effective storageDriver for a collection, which may be inherited from a parent collection or be the installation default, you can use:: - curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver?getEffective=true + curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/dataverses/$dataverse-alias/storageDriver?getEffective=true This will never be null. @@ -70,11 +70,11 @@ This will never be null. To delete a store assigned directly to a collection (so that the colllection's effective store is inherted from it's parent or is the global default), use:: - curl -H "X-Dataverse-key: $API_TOKEN" -X DELETE http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver + curl -H "X-Dataverse-key: $API_TOKEN" -X DELETE http://$SERVER/api/dataverses/$dataverse-alias/storageDriver -The available drivers can be listed with:: +The available drivers within a collection can be listed with:: - curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/admin/dataverse/storageDrivers + curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/dataverses/$dataverse-alias/allowedStorageDrivers (Individual datasets can be configured to use specific file stores as well. See the "Datasets" section below.) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java index 18f28569d7d..289b893e75f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Admin.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Admin.java @@ -74,7 +74,6 @@ import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; -import java.util.Map.Entry; import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; @@ -2256,94 +2255,6 @@ public Response addRoleAssignementsToChildren(@Context ContainerRequestContext c "InheritParentRoleAssignments does not list any roles on this instance"); } - @GET - @AuthRequired - @Path("/dataverse/{alias}/storageDriver") - public Response getStorageDriver(@Context ContainerRequestContext crc, @PathParam("alias") String alias, - @QueryParam("getEffective") Boolean getEffective) throws WrappedResponse { - Dataverse dataverse = dataverseSvc.findByAlias(alias); - if (dataverse == null) { - return error(Response.Status.NOT_FOUND, "Could not find dataverse based on alias supplied: " + alias + "."); - } - try { - AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); - if (!user.isSuperuser()) { - return error(Response.Status.FORBIDDEN, "Superusers only."); - } - } catch (WrappedResponse wr) { - return wr.getResponse(); - } - - if (getEffective != null && getEffective) { - return ok(JsonPrinter.jsonStorageDriver(dataverse.getEffectiveStorageDriverId())); - } else { - return ok(JsonPrinter.jsonStorageDriver(dataverse.getStorageDriverId())); - } - } - - @PUT - @AuthRequired - @Path("/dataverse/{alias}/storageDriver") - public Response setStorageDriver(@Context ContainerRequestContext crc, @PathParam("alias") String alias, String label) throws WrappedResponse { - Dataverse dataverse = dataverseSvc.findByAlias(alias); - if (dataverse == null) { - return error(Response.Status.NOT_FOUND, "Could not find dataverse based on alias supplied: " + alias + "."); - } - try { - AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); - if (!user.isSuperuser()) { - return error(Response.Status.FORBIDDEN, "Superusers only."); - } - } catch (WrappedResponse wr) { - return wr.getResponse(); - } - for (Entry store: DataAccess.getStorageDriverLabels().entrySet()) { - if(store.getKey().equals(label)) { - dataverse.setStorageDriverId(store.getValue()); - return ok("Storage set to: " + store.getKey() + "/" + store.getValue()); - } - } - return error(Response.Status.BAD_REQUEST, - "No Storage Driver found for : " + label); - } - - @DELETE - @AuthRequired - @Path("/dataverse/{alias}/storageDriver") - public Response resetStorageDriver(@Context ContainerRequestContext crc, @PathParam("alias") String alias) throws WrappedResponse { - Dataverse dataverse = dataverseSvc.findByAlias(alias); - if (dataverse == null) { - return error(Response.Status.NOT_FOUND, "Could not find dataverse based on alias supplied: " + alias + "."); - } - try { - AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); - if (!user.isSuperuser()) { - return error(Response.Status.FORBIDDEN, "Superusers only."); - } - } catch (WrappedResponse wr) { - return wr.getResponse(); - } - dataverse.setStorageDriverId(""); - return ok("Storage reset to default: " + DataAccess.DEFAULT_STORAGE_DRIVER_IDENTIFIER); - } - - @GET - @AuthRequired - @Path("/dataverse/storageDrivers") - public Response listStorageDrivers(@Context ContainerRequestContext crc) throws WrappedResponse { - try { - AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); - if (!user.isSuperuser()) { - return error(Response.Status.FORBIDDEN, "Superusers only."); - } - } catch (WrappedResponse wr) { - return wr.getResponse(); - } - JsonObjectBuilder bld = jsonObjectBuilder(); - DataAccess.getStorageDriverLabels().entrySet().forEach(s -> bld.add(s.getKey(), s.getValue())); - return ok(bld); - } - @GET @AuthRequired @Path("/dataverse/{alias}/curationLabelSet") @@ -2820,4 +2731,5 @@ public Response rateLimitStats(@Context ContainerRequestContext crc, String csvData = cacheFactory.getStats(CacheFactoryBean.RATE_LIMIT_CACHE, deltaMinutesFilter != null ? String.valueOf(deltaMinutesFilter) : null); return Response.ok(csvData).header("Content-Disposition", "attachment; filename=\"data.csv\"").build(); } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java index caf778be675..e071d3bf8cb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java @@ -3,12 +3,10 @@ import com.google.common.collect.Lists; import com.google.api.client.util.ArrayMap; import edu.harvard.iq.dataverse.*; -import static edu.harvard.iq.dataverse.api.AbstractApiBean.error; import edu.harvard.iq.dataverse.api.auth.AuthRequired; import edu.harvard.iq.dataverse.api.datadeposit.SwordServiceBean; import edu.harvard.iq.dataverse.api.dto.*; import edu.harvard.iq.dataverse.authorization.DataverseRole; - import edu.harvard.iq.dataverse.api.imports.ImportException; import edu.harvard.iq.dataverse.api.imports.ImportServiceBean; import edu.harvard.iq.dataverse.authorization.Permission; @@ -16,7 +14,6 @@ import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroup; import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupProvider; import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean; -import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.authorization.users.User; import edu.harvard.iq.dataverse.dataset.DatasetType; @@ -24,7 +21,6 @@ import edu.harvard.iq.dataverse.dataverse.featured.DataverseFeaturedItem; import edu.harvard.iq.dataverse.dataverse.featured.DataverseFeaturedItemServiceBean; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; -import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.impl.*; import edu.harvard.iq.dataverse.pidproviders.PidProvider; import edu.harvard.iq.dataverse.pidproviders.PidUtil; @@ -73,6 +69,7 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.StreamingOutput; + import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; @@ -89,7 +86,6 @@ public class Dataverses extends AbstractApiBean { private static final Logger logger = Logger.getLogger(Dataverses.class.getCanonicalName()); - private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss"); @EJB ExplicitGroupServiceBean explicitGroupSvc; @@ -1330,97 +1326,6 @@ public Response listAssignments(@Context ContainerRequestContext crc, @PathParam ), getRequestUser(crc)); } - /** - * This code for setting a dataverse logo via API was started when initially - * investigating https://github.com/IQSS/dataverse/issues/3559 but it isn't - * finished so it's commented out. See also * "No functionality should be - * GUI-only. Make all functionality reachable via the API" at - * https://github.com/IQSS/dataverse/issues/3440 - */ -// File tempDir; -// -// TODO: Code duplicate in ThemeWidgetFragment. Maybe extract, make static and put some place else? -// Important: at least use JvmSettings.DOCROOT_DIRECTORY and not the hardcoded location! -// private void createTempDir(Dataverse editDv) { -// try { -// File tempRoot = java.nio.file.Files.createDirectories(Paths.get("../docroot/logos/temp")).toFile(); -// tempDir = java.nio.file.Files.createTempDirectory(tempRoot.toPath(), editDv.getId().toString()).toFile(); -// } catch (IOException e) { -// throw new RuntimeException("Error creating temp directory", e); // improve error handling -// } -// } -// -// private DataverseTheme initDataverseTheme(Dataverse editDv) { -// DataverseTheme dvt = new DataverseTheme(); -// dvt.setLinkColor(DEFAULT_LINK_COLOR); -// dvt.setLogoBackgroundColor(DEFAULT_LOGO_BACKGROUND_COLOR); -// dvt.setBackgroundColor(DEFAULT_BACKGROUND_COLOR); -// dvt.setTextColor(DEFAULT_TEXT_COLOR); -// dvt.setDataverse(editDv); -// return dvt; -// } -// -// @PUT -// @Path("{identifier}/logo") -// @Consumes(MediaType.MULTIPART_FORM_DATA) -// public Response setDataverseLogo(@PathParam("identifier") String dvIdtf, -// @FormDataParam("file") InputStream fileInputStream, -// @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, -// @QueryParam("key") String apiKey) { -// boolean disabled = true; -// if (disabled) { -// return error(Status.FORBIDDEN, "Setting the dataverse logo via API needs more work."); -// } -// try { -// final DataverseRequest req = createDataverseRequest(findUserOrDie()); -// final Dataverse editDv = findDataverseOrDie(dvIdtf); -// -// logger.finer("entering fileUpload"); -// if (tempDir == null) { -// createTempDir(editDv); -// logger.finer("created tempDir"); -// } -// File uploadedFile; -// try { -// String fileName = contentDispositionHeader.getFileName(); -// -// uploadedFile = new File(tempDir, fileName); -// if (!uploadedFile.exists()) { -// uploadedFile.createNewFile(); -// } -// logger.finer("created file"); -// File file = null; -// file = FileUtil.inputStreamToFile(fileInputStream); -// if (file.length() > systemConfig.getUploadLogoSizeLimit()) { -// return error(Response.Status.BAD_REQUEST, "File is larger than maximum size: " + systemConfig.getUploadLogoSizeLimit() + "."); -// } -// java.nio.file.Files.copy(fileInputStream, uploadedFile.toPath(), StandardCopyOption.REPLACE_EXISTING); -// logger.finer("copied inputstream to file"); -// editDv.setDataverseTheme(initDataverseTheme(editDv)); -// editDv.getDataverseTheme().setLogo(fileName); -// -// } catch (IOException e) { -// logger.finer("caught IOException"); -// logger.throwing("ThemeWidgetFragment", "handleImageFileUpload", e); -// throw new RuntimeException("Error uploading logo file", e); // improve error handling -// } -// // If needed, set the default values for the logo -// if (editDv.getDataverseTheme().getLogoFormat() == null) { -// editDv.getDataverseTheme().setLogoFormat(DataverseTheme.ImageFormat.SQUARE); -// } -// logger.finer("end handelImageFileUpload"); -// UpdateDataverseThemeCommand cmd = new UpdateDataverseThemeCommand(editDv, uploadedFile, req); -// Dataverse saved = execCommand(cmd); -// -// /** -// * @todo delete the temp file: -// * docroot/logos/temp/1148114212463761832421/cc0.png -// */ -// return ok("logo uploaded: " + saved.getDataverseTheme().getLogo()); -// } catch (WrappedResponse ex) { -// return error(Status.BAD_REQUEST, "problem uploading logo: " + ex); -// } -// } @POST @AuthRequired @Path("{identifier}/assignments") @@ -2140,4 +2045,91 @@ public Response getRoleAssignmentHistory(@Context ContainerRequestContext crc, return getRoleAssignmentHistoryResponse(dataverse, authenticatedUser, false, headers); }, getRequestUser(crc)); } + + @GET + @AuthRequired + @Path("{identifier}/storageDriver") + public Response getStorageDriver(@Context ContainerRequestContext crc, @PathParam("identifier") String id, + @QueryParam("getEffective") Boolean getEffective) throws WrappedResponse { + + Dataverse dataverse = findDataverseOrDie(id); + + if (dataverse == null) { + return error(Response.Status.NOT_FOUND, "Could not find dataverse based on the identifier supplied: " + id + "."); + } + + return response(req -> { + String storageDriver = execCommand(new GetDataverseStorageDriverCommand(req, findDataverseOrDie(id), getEffective)); + return ok(JsonPrinter.jsonStorageDriver(storageDriver)); + }, getRequestUser(crc)); + } + + @PUT + @AuthRequired + @Path("{identifier}/storageDriver") + public Response setStorageDriver(@Context ContainerRequestContext crc, + @PathParam("identifier") String id, String label) throws WrappedResponse { + + Dataverse dataverse = findDataverseOrDie(id); + + if (dataverse == null) { + return error(Response.Status.NOT_FOUND, "Could not find dataverse based on the identifier supplied: " + id + "."); + } + + try { + AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); + DataverseRequest request = createDataverseRequest(user); + SetDataverseStorageDriverCommand setDriverCommand = new SetDataverseStorageDriverCommand(request, dataverse, label); + return ok(execCommand(setDriverCommand)); + + } catch (WrappedResponse wr) { + return handleWrappedResponse(wr); + } + } + + @DELETE + @AuthRequired + @Path("{identifier}/storageDriver") + public Response resetStorageDriver(@Context ContainerRequestContext crc, @PathParam("identifier") String id) throws WrappedResponse { + + Dataverse dataverse = findDataverseOrDie(id); + if (dataverse == null) { + return error(Response.Status.NOT_FOUND, "Could not find dataverse based on the identifier supplied: " + id + "."); + } + + try { + AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); + DataverseRequest request = createDataverseRequest(user); + DeleteDataverseStorageDriverCommand deleteDriverCommand = new DeleteDataverseStorageDriverCommand(request, dataverse); + return ok(execCommand(deleteDriverCommand)); + } catch (WrappedResponse wr) { + return handleWrappedResponse(wr); + } + } + + @GET + @AuthRequired + @Path("{identifier}/allowedStorageDrivers") + public Response listStorageDrivers(@Context ContainerRequestContext crc, @PathParam("identifier") String id) throws WrappedResponse { + + Dataverse dv = findDataverseOrDie(id); + + + /* + * TODO: This endpoint ad GetDataverseAllowedStorageDriverCommand needs to be completed, + * currently it mocks things that will be required to model the behavior requested by Jim Myers, + * which is to return the list of storage drivers that the dataverse can use. + * Currently it will return the full list of drivers available. + */ + try { + AuthenticatedUser user = getRequestAuthenticatedUserOrDie(crc); + DataverseRequest request = createDataverseRequest(user); + GetDataverseAllowedStorageDriverCommand getAllowedStorageDriversCommand = new GetDataverseAllowedStorageDriverCommand(request, dv); + return ok(execCommand(getAllowedStorageDriversCommand)); + } catch (WrappedResponse wr) { + return handleWrappedResponse(wr); + } + } + } + \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Info.java b/src/main/java/edu/harvard/iq/dataverse/api/Info.java index 1aab185e6fb..1a60d3eb1ca 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Info.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Info.java @@ -1,13 +1,11 @@ package edu.harvard.iq.dataverse.api; import java.util.logging.Logger; - import edu.harvard.iq.dataverse.customization.CustomizationConstants; import jakarta.ws.rs.*; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.WebTarget; - import edu.harvard.iq.dataverse.export.ExportService; import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; @@ -165,4 +163,5 @@ private Response getSettingResponseByKey(SettingsServiceBean.Key key) { return notFound("Setting " + key + " not found"); } } + } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseStorageDriverCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseStorageDriverCommand.java new file mode 100644 index 00000000000..39f368cb877 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseStorageDriverCommand.java @@ -0,0 +1,27 @@ +package edu.harvard.iq.dataverse.engine.command.impl; + +import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.engine.command.AbstractCommand; +import edu.harvard.iq.dataverse.engine.command.CommandContext; +import edu.harvard.iq.dataverse.engine.command.DataverseRequest; +import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; +import edu.harvard.iq.dataverse.authorization.Permission; + +@RequiredPermissions(Permission.EditDataverse) +public class DeleteDataverseStorageDriverCommand extends AbstractCommand { + + private Dataverse dv; + + public DeleteDataverseStorageDriverCommand(DataverseRequest aRequest, Dataverse dv) { + super(aRequest, dv); + this.dv = dv; + } + + @Override + public String execute(CommandContext ctxt) { + dv.setStorageDriverId(""); + return "Storage reset to default: " + DataAccess.DEFAULT_STORAGE_DRIVER_IDENTIFIER; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseAllowedStorageDriverCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseAllowedStorageDriverCommand.java new file mode 100644 index 00000000000..f1f55d7e602 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseAllowedStorageDriverCommand.java @@ -0,0 +1,29 @@ +package edu.harvard.iq.dataverse.engine.command.impl; + + +import static edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder.jsonObjectBuilder; +import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.engine.command.AbstractCommand; +import edu.harvard.iq.dataverse.engine.command.CommandContext; +import edu.harvard.iq.dataverse.engine.command.DataverseRequest; +import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; +import jakarta.json.JsonObjectBuilder; +import edu.harvard.iq.dataverse.authorization.Permission; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; + +@RequiredPermissions(Permission.AddDataverse) +public class GetDataverseAllowedStorageDriverCommand extends AbstractCommand { + + public GetDataverseAllowedStorageDriverCommand(DataverseRequest aRequest, Dataverse dv) { + super(aRequest, dv); + } + + @Override + public JsonObjectBuilder execute(CommandContext ctxt) { + + JsonObjectBuilder bld = jsonObjectBuilder(); + DataAccess.getStorageDriverLabels().entrySet().forEach(s -> bld.add(s.getKey(), s.getValue())); + return bld; + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseStorageDriverCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseStorageDriverCommand.java new file mode 100644 index 00000000000..85adf791800 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/GetDataverseStorageDriverCommand.java @@ -0,0 +1,40 @@ +package edu.harvard.iq.dataverse.engine.command.impl; + +import java.util.Collections; +import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.engine.command.AbstractCommand; +import edu.harvard.iq.dataverse.engine.command.CommandContext; +import edu.harvard.iq.dataverse.engine.command.DataverseRequest; +import edu.harvard.iq.dataverse.authorization.Permission; +import java.util.Map; +import java.util.Set; + +public class GetDataverseStorageDriverCommand extends AbstractCommand { + + private Dataverse dv; + private Boolean getEffective; + + public GetDataverseStorageDriverCommand(DataverseRequest aRequest, Dataverse dv, Boolean getEffective) { + super(aRequest, dv); + this.dv = dv; + this.getEffective = getEffective; + } + + @Override + public String execute(CommandContext ctxt) { + + if (getEffective != null && getEffective) { + return dv.getEffectiveStorageDriverId(); + } else { + return dv.getStorageDriverId(); + } + } + + @Override + public Map> getRequiredPermissions() { + return Collections.singletonMap("", + dv.isReleased() ? Collections.emptySet() + : Collections.singleton(Permission.ViewUnpublishedDataverse)); + } + +} diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseMetadataLanguageCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseMetadataLanguageCommand.java index 438c332436a..d290f3747e6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseMetadataLanguageCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseMetadataLanguageCommand.java @@ -4,7 +4,6 @@ import java.util.Map; import edu.harvard.iq.dataverse.Dataverse; -import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.engine.command.AbstractCommand; import edu.harvard.iq.dataverse.engine.command.CommandContext; diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseStorageDriverCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseStorageDriverCommand.java new file mode 100644 index 00000000000..447e3ed0e8d --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SetDataverseStorageDriverCommand.java @@ -0,0 +1,43 @@ +package edu.harvard.iq.dataverse.engine.command.impl; + +import java.util.Map.Entry; +import edu.harvard.iq.dataverse.Dataverse; +import edu.harvard.iq.dataverse.dataaccess.DataAccess; +import edu.harvard.iq.dataverse.engine.command.AbstractCommand; +import edu.harvard.iq.dataverse.engine.command.CommandContext; +import edu.harvard.iq.dataverse.engine.command.DataverseRequest; +import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; +import edu.harvard.iq.dataverse.authorization.Permission; + +@RequiredPermissions(Permission.EditDataverse) +public class SetDataverseStorageDriverCommand extends AbstractCommand { + + private Dataverse dv; + private String label; + + public SetDataverseStorageDriverCommand(DataverseRequest aRequest, Dataverse dv, String label) { + super(aRequest, dv); + this.dv = dv; + this.label = label; + } + + @Override + public String execute(CommandContext ctxt) { + + String storageDriverId = null; + for (Entry store: DataAccess.getStorageDriverLabels().entrySet()) { + if(store.getKey().equals(label)) { + storageDriverId = store.getValue(); + } + } + + if (storageDriverId != null) { + dv.setStorageDriverId(storageDriverId); + return "Storage set to: " + storageDriverId + "/" + label; + } else { + throw new IllegalArgumentException("No Storage Driver found for : " + label); + } + + } + +} diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index d9e21d9fdc7..596318519d4 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -6294,7 +6294,7 @@ public void testSetGetDatasetStorageDriver() { Response createDataset = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, apiToken); Integer datasetId = UtilIT.getDatasetIdFromResponse(createDataset); - Response storageDrivers = UtilIT.listStorageDrivers(apiToken); + Response storageDrivers = UtilIT.listStorageDrivers(apiToken, dataverseAlias); storageDrivers.prettyPrint(); JsonObject data = JsonUtil.getJsonObject(storageDrivers.getBody().asString()); String first = data.getJsonObject("data").keySet().iterator().next(); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/S3AccessIT.java b/src/test/java/edu/harvard/iq/dataverse/api/S3AccessIT.java index 60e83f9f2ba..48a64490796 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/S3AccessIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/S3AccessIT.java @@ -116,7 +116,7 @@ public void testNonDirectUpload() { String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser); String superusername = UtilIT.getUsernameFromResponse(createSuperuser); UtilIT.makeSuperUser(superusername).then().assertThat().statusCode(200); - Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken); + Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken, "root"); storageDrivers.prettyPrint(); // TODO where is "Local/local" coming from? String drivers = """ @@ -250,7 +250,7 @@ public void testDirectUpload() { String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser); String superusername = UtilIT.getUsernameFromResponse(createSuperuser); UtilIT.makeSuperUser(superusername).then().assertThat().statusCode(200); - Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken); + Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken, "root"); storageDrivers.prettyPrint(); // TODO where is "Local/local" coming from? String drivers = """ @@ -468,7 +468,7 @@ public void testDirectUploadDetectStataFile() { String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser); String superusername = UtilIT.getUsernameFromResponse(createSuperuser); UtilIT.makeSuperUser(superusername).then().assertThat().statusCode(200); - Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken); + Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken, "root"); storageDrivers.prettyPrint(); // TODO where is "Local/local" coming from? String drivers = """ @@ -655,7 +655,7 @@ public void testDirectUploadWithFileCountLimit() throws JsonParseException { String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperuser); String superusername = UtilIT.getUsernameFromResponse(createSuperuser); UtilIT.makeSuperUser(superusername).then().assertThat().statusCode(200); - Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken); + Response storageDrivers = UtilIT.listStorageDrivers(superuserApiToken, "root"); storageDrivers.prettyPrint(); // TODO where is "Local/local" coming from? String drivers = """ diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 24ab8b56eff..322bf9f4986 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -2920,10 +2920,10 @@ static Response deleteStorageSite(long storageSiteId) { .delete("/api/admin/storageSites/" + storageSiteId); } - static Response listStorageDrivers(String apiToken) { + static Response listStorageDrivers(String apiToken, String dataverseAlias) { return given() .header(API_TOKEN_HTTP_HEADER, apiToken) - .get("/api/admin/dataverse/storageDrivers"); + .get("/api/dataverses/" + dataverseAlias + "/storageDrivers"); } static Response getStorageDriver(String dvAlias, String apiToken) { @@ -2933,14 +2933,14 @@ static Response getStorageDriver(String dvAlias, String apiToken, Boolean getEff String params = getEffective != null ? "?getEffective=" + getEffective : ""; return given() .header(API_TOKEN_HTTP_HEADER, apiToken) - .get("/api/admin/dataverse/" + dvAlias + "/storageDriver" + params); + .get("/api/dataverses/" + dvAlias + "/storageDriver" + params); } static Response setStorageDriver(String dvAlias, String label, String apiToken) { return given() .header(API_TOKEN_HTTP_HEADER, apiToken) .body(label) - .put("/api/admin/dataverse/" + dvAlias + "/storageDriver"); + .put("/api/dataverses/" + dvAlias + "/storageDriver"); } static Response getUploadUrls(String idOrPersistentIdOfDataset, long sizeInBytes, String apiToken) {