From f1658569987fdc30c43f3ab09492ca7f4cfe326b Mon Sep 17 00:00:00 2001
From: Rick Herrick <jrherrick@wustl.edu>
Date: Tue, 3 May 2016 08:07:44 -0500
Subject: [PATCH] Added SiteConfigApi, refactored other REST APIs to use
 updated abstract base.

---
 .../nrg/xapi/rest/event/EventHandlerApi.java  |   3 +-
 .../rest/notifications/NotificationsApi.java  | 157 ++++++++++--------
 .../nrg/xapi/rest/settings/SiteConfigApi.java | 130 +++++++++++++++
 .../org/nrg/xapi/rest/theme/ThemeApi.java     |   3 +-
 .../nrg/xnat/initialization/RootConfig.java   |  29 +++-
 5 files changed, 247 insertions(+), 75 deletions(-)
 create mode 100644 src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java

diff --git a/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java b/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java
index 1e0ad096..07e1ff4e 100644
--- a/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java
+++ b/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java
@@ -9,6 +9,7 @@ import org.nrg.xdat.XDAT;
 import org.nrg.xdat.om.XnatProjectdata;
 import org.nrg.xdat.om.base.auto.AutoXnatProjectdata;
 import org.nrg.xdat.security.XDATUser;
+import org.nrg.xdat.security.helpers.Permissions;
 import org.nrg.xdat.security.helpers.Roles;
 import org.nrg.xdat.services.impl.hibernate.HibernateAutomationEventIdsService;
 import org.nrg.xdat.services.impl.hibernate.HibernateAutomationFiltersService;
@@ -270,7 +271,7 @@ public class EventHandlerApi {
         	if (project_id != null) {
         		final XnatProjectdata proj = AutoXnatProjectdata.getXnatProjectdatasById(project_id, sessionUser, false);
         		try {
-        			return (proj.canEdit(sessionUser)) ? null : HttpStatus.FORBIDDEN;
+        			return Permissions.canEdit(sessionUser, proj) ? null : HttpStatus.FORBIDDEN;
         		} catch (Exception e) {
         			_log.error("Error checking read status for project",e);
         			return HttpStatus.INTERNAL_SERVER_ERROR;
diff --git a/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java b/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
index 3d094657..151a17d5 100644
--- a/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
+++ b/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java
@@ -1,11 +1,10 @@
 package org.nrg.xapi.rest.notifications;
 
 import io.swagger.annotations.*;
+import org.apache.commons.lang3.StringUtils;
 import org.nrg.framework.annotations.XapiRestController;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
 import org.nrg.xdat.rest.AbstractXnatRestApi;
-import org.nrg.xdat.security.XDATUser;
-import org.nrg.xft.security.UserI;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
@@ -18,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 import javax.inject.Inject;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
 
 @Api(description = "XNAT Notifications management API")
 @XapiRestController
@@ -28,28 +28,52 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets all the mail service properties.", notes = "Sets the mail service host, port, username, password, and protocol.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service properties."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/all"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setMailProperties(@ApiParam(value = "The value to set for the email host.", required = true) @RequestParam(value="host", required=false) final String host,
-                                                  @ApiParam(value = "The value to set for the email port.", required = true) @RequestParam(value="port", required=false) final int port,
-                                                  @ApiParam(value = "The value to set for the email username.", required = true) @RequestParam(value="username", required=false) final String username,
-                                                  @ApiParam(value = "The value to set for the email password.", required = true) @RequestParam(value="password", required=false) final String password,
-                                                  @ApiParam(value = "The value to set for the email protocol.", required = true) @RequestParam(value="protocol", required=false) final String protocol) {
-        HttpStatus status = null;
-        UserI sessionUser = getSessionUser();
-        if (sessionUser == null) {
-            status = HttpStatus.UNAUTHORIZED;
-        }
-        else if ((sessionUser instanceof XDATUser)) {
-            status = ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
-        }
+    public ResponseEntity<Void> setMailProperties(@ApiParam(value = "The value to set for the email host.") @RequestParam(value = "host", required = false) final String host,
+                                                  @ApiParam(value = "The value to set for the email port.") @RequestParam(value = "port", required = false) final int port,
+                                                  @ApiParam(value = "The value to set for the email username.") @RequestParam(value = "username", required = false) final String username,
+                                                  @ApiParam(value = "The value to set for the email password.") @RequestParam(value = "password", required = false) final String password,
+                                                  @ApiParam(value = "The value to set for the email protocol.") @RequestParam(value = "protocol", required = false) final String protocol,
+                                                  @ApiParam(value = "Values to set for extra mail properties.") @RequestParam(value = "properties", required = false) final Map<String, String> properties) {
+        final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
         }
 
+        if (_log.isInfoEnabled()) {
+            final StringBuilder message = new StringBuilder("User ");
+            message.append(getSessionUser().getLogin()).append(" setting mail properties to:\n");
+            if (StringUtils.isNotBlank(host)) {
+                message.append(" * Host:     ").append(host).append("\n");
+            }
+            if (port != 0) {
+                message.append(" * Port:     ").append(port).append("\n");
+            }
+            if (StringUtils.isNotBlank(username)) {
+                message.append(" * Username: ").append(username).append("\n");
+            }
+            if (StringUtils.isNotBlank(password)) {
+                message.append(" * Password: ********\n");
+            }
+            if (StringUtils.isNotBlank(protocol)) {
+                message.append(" * Protocol: ").append(protocol).append("\n");
+            }
+            if (properties != null && properties.size() > 0) {
+                for (final String property : properties.keySet()) {
+                    message.append(" * ").append(property).append(": ").append(properties.get(property)).append("\n");
+                }
+            }
+            _log.info(message.toString());
+        }
         _javaMailSender.setHost(host);
         _javaMailSender.setPort(port);
         _javaMailSender.setUsername(username);
         _javaMailSender.setPassword(password);
         _javaMailSender.setProtocol(protocol);
+        if (properties != null) {
+            final Properties javaMailProperties = new Properties();
+            javaMailProperties.putAll(properties);
+            _javaMailSender.setJavaMailProperties(javaMailProperties);
+        }
         setSmtp();
         return new ResponseEntity<>(HttpStatus.OK);
     }
@@ -57,9 +81,14 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets the mail service host.", notes = "Sets the mail service host.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service host successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service host."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/host"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setHostProperty(@ApiParam(value = "The value to set for the email host.", required = true) @RequestParam(value="host", required=true) final String host) {
-
-
+    public ResponseEntity<Void> setHostProperty(@ApiParam(value = "The value to set for the email host.", required = true) @RequestParam("host") final String host) {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+        if (_log.isInfoEnabled()) {
+            _log.info("User " + getSessionUser().getLogin() + " setting mail host to: " + host);
+        }
         _javaMailSender.setHost(host);
         setSmtp();
         return new ResponseEntity<>(HttpStatus.OK);
@@ -68,19 +97,14 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets the mail service port.", notes = "Sets the mail service port.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service port successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service port."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/port"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setPortProperty(@ApiParam(value = "The value to set for the email port.", required = true) @RequestParam(value="port", required=true) final int port) {
-        HttpStatus status = null;
-        UserI sessionUser = getSessionUser();
-        if (sessionUser == null) {
-            status = HttpStatus.UNAUTHORIZED;
-        }
-        else if ((sessionUser instanceof XDATUser)) {
-            status = ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
-        }
+    public ResponseEntity<Void> setPortProperty(@ApiParam(value = "The value to set for the email port.", required = true) @RequestParam("port") final int port) {
+        final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
         }
-
+        if (_log.isInfoEnabled()) {
+            _log.info("User " + getSessionUser().getLogin() + " setting mail port to: " + port);
+        }
         _javaMailSender.setPort(port);
         setSmtp();
         return new ResponseEntity<>(HttpStatus.OK);
@@ -89,19 +113,14 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets the mail service protocol.", notes = "Sets the mail service protocol.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service protocol successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service protocol."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/protocol"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setProtocolProperty(@ApiParam(value = "The value to set for the email protocol.", required = true) @RequestParam(value="protocol", required=true) final String protocol) {
-        HttpStatus status = null;
-        UserI sessionUser = getSessionUser();
-        if (sessionUser == null) {
-            status = HttpStatus.UNAUTHORIZED;
-        }
-        else if ((sessionUser instanceof XDATUser)) {
-            status = ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
-        }
+    public ResponseEntity<Void> setProtocolProperty(@ApiParam(value = "The value to set for the email protocol.", required = true) @RequestParam("protocol") final String protocol) {
+        final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
         }
-
+        if (_log.isInfoEnabled()) {
+            _log.info("User " + getSessionUser().getLogin() + " setting mail protocol to: " + protocol);
+        }
         _javaMailSender.setProtocol(protocol);
         return new ResponseEntity<>(HttpStatus.OK);
     }
@@ -109,19 +128,14 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets the mail service username.", notes = "Sets the mail service username.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service username successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service username."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/username"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setUsernameProperty(@ApiParam(value = "The value to set for the email username.", required = true) @RequestParam(value="username", required=true) final String username) {
-        HttpStatus status = null;
-        UserI sessionUser = getSessionUser();
-        if (sessionUser == null) {
-            status = HttpStatus.UNAUTHORIZED;
-        }
-        else if ((sessionUser instanceof XDATUser)) {
-            status = ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
-        }
+    public ResponseEntity<Void> setUsernameProperty(@ApiParam(value = "The value to set for the email username.", required = true) @RequestParam("username") final String username) {
+        final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
         }
-
+        if (_log.isInfoEnabled()) {
+            _log.info("User " + getSessionUser().getLogin() + " setting mail username to: " + username);
+        }
         _javaMailSender.setUsername(username);
         return new ResponseEntity<>(HttpStatus.OK);
     }
@@ -129,39 +143,40 @@ public class NotificationsApi extends AbstractXnatRestApi {
     @ApiOperation(value = "Sets the mail service password.", notes = "Sets the mail service password.", response = Void.class)
     @ApiResponses({@ApiResponse(code = 200, message = "Mail service password successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set the mail service password."), @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = {"/password"}, produces = {"application/json"}, method = {RequestMethod.POST})
-    public ResponseEntity<Void> setPasswordProperty(@ApiParam(value = "The value to set for the email password.", required = true) @RequestParam(value="password", required=true) final String password) {
-        HttpStatus status = null;
-        UserI sessionUser = getSessionUser();
-        if (sessionUser == null) {
-            status = HttpStatus.UNAUTHORIZED;
-        }
-        else if ((sessionUser instanceof XDATUser)) {
-            status = ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
-        }
+    public ResponseEntity<Void> setPasswordProperty(@ApiParam(value = "The value to set for the email password.", required = true) @RequestParam("password") final String password) {
+        final HttpStatus status = isPermitted();
         if (status != null) {
             return new ResponseEntity<>(status);
         }
-
+        if (_log.isInfoEnabled()) {
+            _log.info("User " + getSessionUser().getLogin() + " setting mail password to: ********");
+        }
         _javaMailSender.setPassword(password);
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
-    private void setSmtp(){
-        Map<String, String> smtp = new HashMap<String, String>();
-        String host = _javaMailSender.getHost();
-        if(host==null){
-            host = "";
-        }
-        smtp.put("host", host);
-        String port = ""+_javaMailSender.getPort();
-        if(port==null){
-            port = "";
-        }
-        smtp.put("port", port);
+    private void setSmtp() {
+        Map<String, String> smtp = new HashMap<>();
+        smtp.put("host", StringUtils.defaultIfBlank(_javaMailSender.getHost(), "localhost"));
+        smtp.put("port", Integer.toString(_javaMailSender.getPort()));
+        if (StringUtils.isNotBlank(_javaMailSender.getUsername())) {
+            smtp.put("username", _javaMailSender.getUsername());
+        }
+        if (StringUtils.isNotBlank(_javaMailSender.getPassword())) {
+            smtp.put("password", _javaMailSender.getPassword());
+        }
+        if (StringUtils.isNotBlank(_javaMailSender.getProtocol())) {
+            smtp.put("protocol", _javaMailSender.getProtocol());
+        }
+        final Properties properties = _javaMailSender.getJavaMailProperties();
+        if (properties.size() > 0) {
+            for (final String property : properties.stringPropertyNames()) {
+                smtp.put(property, properties.getProperty(property));
+            }
+        }
         _siteConfigPrefs.setSmtpServer(smtp);
     }
 
-
     @Inject
     private SiteConfigPreferences _siteConfigPrefs;
 
diff --git a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
new file mode 100644
index 00000000..c9f5766a
--- /dev/null
+++ b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
@@ -0,0 +1,130 @@
+package org.nrg.xapi.rest.settings;
+
+import com.google.common.base.Joiner;
+import io.swagger.annotations.*;
+import org.nrg.framework.annotations.XapiRestController;
+import org.nrg.prefs.exceptions.InvalidPreferenceName;
+import org.nrg.xdat.preferences.SiteConfigPreferences;
+import org.nrg.xdat.rest.AbstractXnatRestApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Api(description = "XNAT Site Configuration Management API")
+@XapiRestController
+@RequestMapping(value = "/siteConfig")
+public class SiteConfigApi extends AbstractXnatRestApi {
+    @ApiOperation(value = "Returns the full map of site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = SiteConfigPreferences.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(produces = {"application/json"}, method = {RequestMethod.GET})
+    public ResponseEntity<SiteConfigPreferences> getAllSiteConfigProperties() {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+        if (_log.isDebugEnabled()) {
+            _log.debug("User " + getSessionUser().getUsername() + " requested the site configuration.");
+        }
+        return new ResponseEntity<>(_preferences, HttpStatus.OK);
+    }
+
+    @ApiOperation(value = "Returns a map of the selected site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = String.class, responseContainer = "Map")
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(consumes = {"application/json"}, produces = {"application/json"}, method = {RequestMethod.PUT})
+    public ResponseEntity<Map<String, String>> getSpecifiedSiteConfigProperties(@RequestBody final List<String> preferences) {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+
+        if (_log.isDebugEnabled()) {
+            _log.debug("User " + getSessionUser().getUsername() + " requested the site configuration properties " + Joiner.on(", ").join(preferences));
+        }
+
+        final Map<String, String> properties = new HashMap<>();
+        for (final String preference : preferences) {
+            properties.put(preference, _preferences.getValue(preference));
+        }
+        return new ResponseEntity<>(properties, HttpStatus.OK);
+    }
+
+    @ApiOperation(value = "Returns a map of the selected site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = String.class, responseContainer = "Map")
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = "{property}", consumes = {"application/json"}, produces = {"application/json"}, method = {RequestMethod.GET})
+    public ResponseEntity<String> getSpecifiedSiteConfigProperties(@ApiParam(value = "The site configuration property to retrieve.", required = true) @PathVariable final String property) {
+        final HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+        final String value = _preferences.getValue(property);
+        if (_log.isDebugEnabled()) {
+            _log.debug("User " + getSessionUser().getUsername() + " requested the value for the site configuration property " + property + ", got value: " + value);
+        }
+        return new ResponseEntity<>(value, HttpStatus.OK);
+    }
+
+    @ApiOperation(value = "Sets a map of site configuration properties.", notes = "Sets the site configuration properties specified in the map.", response = Void.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = {"/batch"}, consumes = {"application/json"}, produces = {"application/json"}, method = {RequestMethod.POST})
+    public ResponseEntity<Void> setBatchSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) {
+        HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+
+        if (_log.isDebugEnabled()) {
+            final StringBuilder message = new StringBuilder("User ").append(getSessionUser().getUsername()).append(" is setting the values for the following properties:\n");
+            for (final String name : properties.keySet()) {
+                message.append(" * ").append(name).append(": ").append(properties.get(name)).append("\n");
+            }
+            _log.debug(message.toString());
+        }
+
+        for (final String name : properties.keySet()) {
+            try {
+                _preferences.set(name, properties.get(name));
+            } catch (InvalidPreferenceName invalidPreferenceName) {
+                _log.error("Got an invalid preference name error for the preference: " + name + ", which is weird because the site configuration is not strict");
+            }
+        }
+
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+
+    @ApiOperation(value = "Sets a single site configuration property.", notes = "Sets the site configuration property specified in the URL to the value set in the body.", response = Void.class)
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @RequestMapping(value = {"/{property}"}, consumes = {"application/json"}, produces = {"application/json"}, method = {RequestMethod.POST})
+    public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @PathVariable("property") final String property, @RequestBody final String value) {
+        HttpStatus status = isPermitted();
+        if (status != null) {
+            return new ResponseEntity<>(status);
+        }
+
+        if (_log.isDebugEnabled()) {
+            _log.debug("User {} is setting the value of the site configuration property {} to: {}", getSessionUser().getUsername(), property, value);
+        }
+
+        try {
+            _preferences.set(property, value);
+        } catch (InvalidPreferenceName invalidPreferenceName) {
+            _log.error("Got an invalid preference name error for the preference: " + property + ", which is weird because the site configuration is not strict");
+            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+
+    private static final Logger _log = LoggerFactory.getLogger(SiteConfigApi.class);
+
+    @Autowired
+    @Lazy
+    private SiteConfigPreferences _preferences;
+}
diff --git a/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java b/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java
index deea66e3..3819a244 100644
--- a/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java
+++ b/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java
@@ -17,6 +17,7 @@ import org.nrg.framework.annotations.XapiRestController;
 import org.nrg.xapi.rest.NotFoundException;
 import org.nrg.xdat.entities.ThemeConfig;
 import org.nrg.xdat.security.XDATUser;
+import org.nrg.xdat.security.helpers.Roles;
 import org.nrg.xft.security.UserI;
 import org.nrg.xdat.services.ThemeService;
 import org.slf4j.Logger;
@@ -163,7 +164,7 @@ public class ThemeApi {
     private HttpStatus isPermitted() {
         UserI sessionUser = getSessionUser();
         if ((sessionUser instanceof XDATUser)) {
-            return ((XDATUser) sessionUser).isSiteAdmin() ? null : HttpStatus.FORBIDDEN;
+            return Roles.isSiteAdmin(sessionUser) ? null : HttpStatus.FORBIDDEN;
         }
         return null;
     }
diff --git a/src/main/java/org/nrg/xnat/initialization/RootConfig.java b/src/main/java/org/nrg/xnat/initialization/RootConfig.java
index cd76f5bf..41893262 100644
--- a/src/main/java/org/nrg/xnat/initialization/RootConfig.java
+++ b/src/main/java/org/nrg/xnat/initialization/RootConfig.java
@@ -11,11 +11,18 @@ import org.nrg.framework.exceptions.NrgServiceException;
 import org.nrg.framework.services.ContextService;
 import org.nrg.framework.services.SerializerService;
 import org.nrg.xdat.preferences.InitializerSiteConfiguration;
+import org.nrg.xdat.preferences.SiteConfigPreferences;
 import org.nrg.xnat.helpers.prearchive.PrearcConfig;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.ImportResource;
+import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+import javax.xml.bind.Marshaller;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Configuration for the XNAT root application context. This contains all of the basic infrastructure for initializing
@@ -58,7 +65,7 @@ public class RootConfig {
     @Bean
     public ObjectMapper jsonObjectMapper() {
         final PrettyPrinter printer = prettyPrinter();
-        final ObjectMapper  mapper  = new ObjectMapper().setDefaultPrettyPrinter(printer);
+        final ObjectMapper mapper = new ObjectMapper().setDefaultPrettyPrinter(printer);
         mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
         return mapper;
     }
@@ -66,11 +73,29 @@ public class RootConfig {
     @Bean
     public ObjectMapper yamlObjectMapper() {
         final PrettyPrinter printer = prettyPrinter();
-        final ObjectMapper  mapper  = new ObjectMapper(new YAMLFactory()).setDefaultPrettyPrinter(printer);
+        final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()).setDefaultPrettyPrinter(printer);
         mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
         return mapper;
     }
 
+    @Bean
+    public MarshallingHttpMessageConverter marshallingMessageConverter() {
+        return new MarshallingHttpMessageConverter(
+                jaxb2Marshaller(),
+                jaxb2Marshaller()
+        );
+    }
+
+    @Bean
+    public Jaxb2Marshaller jaxb2Marshaller() {
+        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+        marshaller.setClassesToBeBound(SiteConfigPreferences.class);
+        final Map<String, Object> marshallerProperties = new HashMap<>();
+        marshallerProperties.put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+        marshaller.setMarshallerProperties(marshallerProperties);
+        return marshaller;
+    }
+
     @Bean
     public SerializerService serializerService() {
         return new SerializerService();
-- 
GitLab