Skip to content

Commit 87a8511

Browse files
committed
feat: add putAllSettings endpoint to Admin API for bulk settings update #11639
Introduced a new `PUT /api/admin/settings` endpoint to update all settings in bulk with JSON input. Added `setAllFromJson` method and placeholder implementation for `replaceAllSettings` in `SettingsServiceBean`. Validates input structure and ensures atomic updates.
1 parent 7c6dfd4 commit 87a8511

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

src/main/java/edu/harvard/iq/dataverse/api/Admin.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import jakarta.ws.rs.PathParam;
6464
import jakarta.ws.rs.container.ContainerRequestContext;
6565
import jakarta.ws.rs.core.Context;
66+
import jakarta.ws.rs.core.MediaType;
6667
import jakarta.ws.rs.core.Response;
6768
import static edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder.jsonObjectBuilder;
6869

@@ -211,6 +212,28 @@ public Response listAllSettings() {
211212
return ok(settingsSvc.listAllAsJson());
212213
}
213214

215+
@Path("settings")
216+
@PUT
217+
@Consumes(MediaType.APPLICATION_JSON)
218+
@APIResponses({
219+
@APIResponse(responseCode = "200", description = "All database options successfully updated")
220+
})
221+
public Response putAllSettings(JsonObject settings) {
222+
try {
223+
// Basic JSON structure validation only
224+
if (settings == null || settings.isEmpty()) {
225+
return error(Response.Status.BAD_REQUEST, "Empty or invalid JSON object");
226+
}
227+
228+
// Transfer to domain objects and deeper validation to be handled by the service layer.
229+
settingsSvc.setAllFromJson(settings);
230+
return ok("All database options successfully updated.");
231+
232+
} catch (IllegalArgumentException iae) {
233+
return error(Response.Status.BAD_REQUEST, iae.getMessage());
234+
}
235+
}
236+
214237
@Path("settings/{name}")
215238
@PUT
216239
public Response putSetting(@PathParam("name") String name, String content) {

src/main/java/edu/harvard/iq/dataverse/settings/SettingsServiceBean.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
import jakarta.persistence.EntityManager;
1717
import jakarta.persistence.PersistenceContext;
1818

19+
import jakarta.transaction.Transactional;
1920
import org.json.JSONArray;
2021
import org.json.JSONException;
2122
import org.json.JSONObject;
2223

24+
import java.util.ArrayList;
2325
import java.util.Arrays;
2426
import java.util.Collections;
2527
import java.util.HashMap;
@@ -1077,6 +1079,31 @@ public JsonObject listAllAsJson() {
10771079
return response.build();
10781080
}
10791081

1082+
/**
1083+
* Updates all settings by replacing them with the settings provided in the given JSON object.
1084+
* This method validates the keys and values from the JSON object, converts them into
1085+
* a list of Setting objects, and performs an atomic update of the internal settings.
1086+
*
1087+
* @param settings a JsonObject containing the new settings to apply.
1088+
* Each key corresponds to a setting name, and each value corresponds
1089+
* to its respective value. The keys and values will be validated before
1090+
* applying the updates.
1091+
* @throws IllegalArgumentException if the JSON object contains invalid keys or invalid settings.
1092+
*/
1093+
public void setAllFromJson(JsonObject settings) {
1094+
// Validate the input
1095+
List<String> invalidKeys = validateKeys(settings);
1096+
if (!invalidKeys.isEmpty()) {
1097+
throw new IllegalArgumentException("Invalid key(s): " + String.join(", ", invalidKeys));
1098+
}
1099+
1100+
// Convert JSON to Setting objects
1101+
List<Setting> newSettings = convertJsonToSettings(settings);
1102+
1103+
// Perform atomic update (replace all settings)
1104+
replaceAllSettings(newSettings);
1105+
}
1106+
10801107
/**
10811108
* Converts a JSON object representing settings into a list of Setting objects.
10821109
* Each entry in the JSON object is processed to create a Setting instance.
@@ -1112,6 +1139,21 @@ static List<Setting> convertJsonToSettings(JsonObject settings) {
11121139
.collect(Collectors.toList());
11131140
}
11141141

1142+
/**
1143+
* Replaces all existing settings with a new list of settings within a single transaction.
1144+
* The operation is atomic, ensuring that either all changes are applied or none in case of a failure.
1145+
*
1146+
* @param newSettings the list of new {@link Setting} objects to replace the existing settings.
1147+
* Must not be null; an empty list clears all settings.
1148+
*/
1149+
@Transactional
1150+
public void replaceAllSettings(List<Setting> newSettings) {
1151+
// Implementation for atomic replacement
1152+
// This would involve clearing existing settings and inserting new ones
1153+
// within the same transaction
1154+
throw new IllegalStateException("Not yet implemented");
1155+
}
1156+
11151157
public Map<String, String> getBaseMetadataLanguageMap(Map<String,String> languageMap, boolean refresh) {
11161158
if (languageMap == null || refresh) {
11171159
languageMap = new HashMap<String, String>();

0 commit comments

Comments
 (0)