Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7ebb100
placeholder
jp-tosca Nov 6, 2025
4c9044a
Endpoints work but need polish.
jp-tosca Nov 10, 2025
9460189
Merge remote-tracking branch 'origin/develop' into 11914-set-template…
jp-tosca Nov 12, 2025
097e972
pr notes
jp-tosca Nov 12, 2025
5d7379e
Merge remote-tracking branch 'origin/develop' into 11914-set-template…
jp-tosca Nov 18, 2025
d5aab83
Initial test
jp-tosca Nov 18, 2025
31a2078
Changes to show the ID of the created template
jp-tosca Nov 20, 2025
76ff3e0
Changes to the set default endpoint
jp-tosca Nov 20, 2025
8e72fea
Flush entity manager after setting default template in CreateTemplate…
jp-tosca Nov 20, 2025
17bb055
Update success messages for removing default dataset template
jp-tosca Nov 20, 2025
04fcb16
Implement RemoveDefaultDatasetCommand and update endpoint to use it f…
jp-tosca Nov 20, 2025
72237fb
Add tests for setting and removing default template in DataversesIT
jp-tosca Nov 21, 2025
a86a9ab
Fix permission description in API documentation and method signatures…
jp-tosca Nov 24, 2025
924da37
Merge branch 'develop' into 11914-set-template-default
jp-tosca Nov 24, 2025
fd645d8
Merge branch 'develop' into 11914-set-template-default
sekmiller Jan 8, 2026
1599767
#11914 fix merge conflicts
sekmiller Jan 8, 2026
e57568e
#11914 return default true for test
sekmiller Jan 8, 2026
1649109
#11914 fix find template and tests
sekmiller Jan 9, 2026
93fcb43
#11914 update command name for clarity
sekmiller Jan 9, 2026
bf10460
Merge branch 'develop' into 11914-set-template-default
sekmiller Jan 12, 2026
671901b
Merge branch 'develop' into 11914-set-template-default
sekmiller Jan 14, 2026
dc1c200
Update src/main/java/edu/harvard/iq/dataverse/engine/command/impl/Set…
sekmiller Jan 14, 2026
eef6ce0
Update src/main/java/edu/harvard/iq/dataverse/engine/command/impl/Rem…
sekmiller Jan 14, 2026
2fd494f
#11914 change path
sekmiller Jan 14, 2026
23253fb
Update native-api.rst
sekmiller Jan 14, 2026
f668cfa
Update native-api.rst
sekmiller Jan 14, 2026
53447e0
Merge branch 'develop' into 11914-set-template-default
sekmiller Jan 14, 2026
3e04cee
fix docs
stevenwinship Jan 14, 2026
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
15 changes: 15 additions & 0 deletions doc/release-notes/11914-set-template-default-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## New Endpoint: POST `/dataverses/{id}/template/default/{templateId}`

A new endpoint has been implemented to set the default template to a given dataverse collection.

### Functionality
- Sets the default template of the given dataverse collection.
- You must have edit dataverse permission in the collection in order to use this endpoint.

## New Endpoint: DELETE `/dataverses/{id}/template/default`

A new endpoint has been implemented to remove the default template to a given dataverse collection.

### Functionality
- Removes the default template of the given dataverse collection.
- You must have edit dataverse permission in the collection in order to use this endpoint.
44 changes: 44 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,50 @@ The fully expanded example above (without environment variables) looks like this

curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/dataverses/1/templates" --upload-file dataverse-template.json

Set a Default Template for a Collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sets a template as the default template for a collection:

.. code-block:: bash

export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export SERVER_URL=https://demo.dataverse.org
export ID=1
export TEMPLATEID=2

curl -H "X-Dataverse-key:$API_TOKEN" -X POST "$SERVER_URL/api/dataverses/$ID/template/default/$TEMPLATEID"

The fully expanded example above (without environment variables) looks like this:

.. code-block:: bash

curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST "https://demo.dataverse.org/api/dataverses/1/template/default/2"

You must have Edit Dataverse permission within the given dataverse collection to invoke this api.

Remove a Default Template for a Collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Remove a template as the default template for a collection(Note: the template is not deleted; it will still be available for use in the collection):

.. code-block:: bash

export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export SERVER_URL=https://demo.dataverse.org
export ID=1


curl -H "X-Dataverse-key:$API_TOKEN" -X DELETE "$SERVER_URL/api/dataverses/$ID/template/default"

The fully expanded example above (without environment variables) looks like this:

.. code-block:: bash

curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE "https://demo.dataverse.org/api/dataverses/1/template/default"

You must have Edit Dataverse permission within the given dataverse collection to invoke this api.


Dataverse Role Assignment History
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,25 @@ protected Dataverse findDataverseOrDie( String dvIdtf ) throws WrappedResponse {
}
return dv;
}

protected Template findTemplateOrDie(Long templateId, Dataverse dataverse) throws WrappedResponse {

List<Template> templates = new ArrayList<>();

templates.addAll(dataverse.getTemplates());
templates.addAll(dataverse.getParentTemplates());

Template template = templates.stream()
.filter(t -> Objects.equals(t.getId(), templateId))
.findFirst()
.orElse(null);

if (template == null) {
throw new WrappedResponse(
error(Response.Status.NOT_FOUND, "Can't find template with identifier='" + templateId + "'"));
}
return template;
}

protected DataverseLinkingDataverse findDataverseLinkingDataverseOrDie(String dataverseId, String linkedDataverseId) throws WrappedResponse {
DataverseLinkingDataverse dvld;
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
Original file line number Diff line number Diff line change
Expand Up @@ -2031,6 +2031,45 @@ public Response createTemplate(@Context ContainerRequestContext crc, String body
}
}

@POST
@AuthRequired
@Path("{identifier}/template/default/{templateId}")
public Response setDefaultTemplate(@Context ContainerRequestContext crc,
@PathParam("identifier") String dvId,
@PathParam("templateId") Long templateId) {

try {

Dataverse dataverse = findDataverseOrDie(dvId);
Template template = findTemplateOrDie(templateId, dataverse);
DataverseRequest dvReq = createDataverseRequest(getRequestUser(crc));
SetDefaultTemplateCommand command = new SetDefaultTemplateCommand(template, dvReq, dataverse);

execCommand(command);

return ok(BundleUtil.getStringFromBundle("dataverse.setDefaultTemplate.success"));

} catch (WrappedResponse e) {
return e.getResponse();
}
}

@DELETE
@AuthRequired
@Path("{identifier}/template/default")
public Response removeDefaultTemplate(@Context ContainerRequestContext crc,
@PathParam("identifier") String dvId) {
try {
Dataverse dataverse = findDataverseOrDie(dvId);
RemoveDefaultTemplateCommand command = new RemoveDefaultTemplateCommand(createDataverseRequest(getRequestUser(crc)), dataverse);
execCommand(command);
return ok(BundleUtil.getStringFromBundle("dataverse.removeDefaultTemplate.success"));
} catch (WrappedResponse e) {
return e.getResponse();
}
}


@GET
@AuthRequired
@Path("{identifier}/allowedMetadataLanguages")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public Template execute(CommandContext ctxt) throws CommandException {
if (initialize && createdTemplate.isIsDefaultForDataverse()) {
dataverse.setDefaultTemplate(createdTemplate);
ctxt.em().merge(dataverse);
ctxt.em().flush();
}

//Flush so that api response can include the id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package edu.harvard.iq.dataverse.engine.command.impl;

import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.authorization.Permission;

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.engine.command.exception.CommandException;

/**
* @author J.P. Tosca
* Removes the default template {@link Template} for a {@link Dataverse}.
*/
@RequiredPermissions(Permission.EditDataverse)
public class RemoveDefaultTemplateCommand extends AbstractCommand<Dataverse>{

private final Dataverse dataverse;

public RemoveDefaultTemplateCommand(DataverseRequest request, Dataverse dataverse) {
super(request, dataverse);
this.dataverse = dataverse;
}

@Override
public Dataverse execute(CommandContext ctxt) throws CommandException {
dataverse.setDefaultTemplate(null);
Dataverse mergedDataverse = ctxt.em().merge(dataverse);
return mergedDataverse;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package edu.harvard.iq.dataverse.engine.command.impl;

import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.authorization.Permission;

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.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.Template;

/**
* @author J.P. Tosca
* Sets a default template {@link Template} for a {@link Dataverse}.
*/
@RequiredPermissions(Permission.EditDataverse)
public class SetDefaultTemplateCommand extends AbstractCommand<Template> {

private final Template template;
private final Dataverse dataverse;

public SetDefaultTemplateCommand(Template template, DataverseRequest request, Dataverse dataverse) {
super(request, dataverse);
this.template = template;
this.dataverse = dataverse;
}

@Override
public Template execute(CommandContext ctxt) throws CommandException {
dataverse.setDefaultTemplate(template);
ctxt.em().merge(dataverse);
return template;
}

}
2 changes: 2 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,8 @@ dataverse.update.featuredItems.error.invalidType=Unknown 'type' must be one of {
dataverse.update.featuredItems.error.typeAndDvObjectMismatch=The 'type' passed does not match the dvObject type.
dataverse.delete.featuredItems.success=All featured items of this Dataverse have been successfully deleted.
dataverse.createTemplate.error.jsonParseMetadataFields=Error parsing the POSTed template dataset fields: {0}
dataverse.setDefaultTemplate.success=The default dataset template has been successfully set for this dataverse.
dataverse.removeDefaultTemplate.success=The default dataset template has been successfully removed from this dataverse.
# rolesAndPermissionsFragment.xhtml

# advanced.xhtml
Expand Down
Loading
Loading