diff --git a/src/main/java/org/nrg/dcm/DicomSCPManager.java b/src/main/java/org/nrg/dcm/DicomSCPManager.java index f91b8e5d296ca5a810478368de25fe9b8071e5fb..89b8847795cf03723519fb22fb62b7fe38840ec3 100644 --- a/src/main/java/org/nrg/dcm/DicomSCPManager.java +++ b/src/main/java/org/nrg/dcm/DicomSCPManager.java @@ -39,15 +39,23 @@ public class DicomSCPManager { } public DicomSCP create(final DicomSCPInstance instance) throws NrgServiceException { + final DicomSCPInstance atPort = _dicomScpPreferences.getDicomSCPAtPort(instance.getPort()); + if (atPort != null) { + throw new NrgServiceException(NrgServiceError.AlreadyInitialized, "Unable to create DICOM SCP [" + instance.toString() + "]: there is an existing enabled receiver already using the same port."); + } instance.setId(getNextKey()); try { _dicomScpPreferences.setDicomSCPInstance(instance); if (_log.isDebugEnabled()) { _log.debug("Created new DICOM SCP: " + instance.toString()); } - return _dicomScpPreferences.getDicomSCP(instance.getId()); + final DicomSCP dicomSCP = _dicomScpPreferences.getDicomSCP(instance.getId()); + if (instance.isEnabled()) { + dicomSCP.start(); + } + return dicomSCP; } catch (IOException e) { - throw new NrgServiceRuntimeException(NrgServiceError.Unknown, "Unable to create DICOM SCP: " + instance.getAeTitle() + ":" + instance.getPort(), e); + throw new NrgServiceException(NrgServiceError.Unknown, "Unable to create DICOM SCP: " + instance.getAeTitle() + ":" + instance.getPort(), e); } } diff --git a/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java b/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java index 545d8b3016977428f0290ce712b331450afb943e..2d72c19fcca444b9e47544704bdf190de6c2573f 100644 --- a/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java +++ b/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java @@ -41,7 +41,6 @@ public class DicomSCPInstance { setEnabled(enabled); } - public int getId() { return _id; } @@ -92,14 +91,7 @@ public class DicomSCPInstance { @Override public String toString() { - return "DicomSCPInstance{" + - "_id='" + _id + '\'' + - ", _port=" + _port + - ", _aeTitle='" + _aeTitle + '\'' + - ", _identifier='" + _identifier + '\'' + - ", _fileNamer='" + _fileNamer + '\'' + - ", _enabled='" + _enabled + '\'' + - '}'; + return _aeTitle + ":" + _port; } private int _id; diff --git a/src/main/java/org/nrg/dcm/preferences/DicomSCPPreference.java b/src/main/java/org/nrg/dcm/preferences/DicomSCPPreference.java index 1fd53a1eec983b4e1f6501e39d179535801f0cfb..fff208869e86791da09fb04db3470fb522b399d8 100644 --- a/src/main/java/org/nrg/dcm/preferences/DicomSCPPreference.java +++ b/src/main/java/org/nrg/dcm/preferences/DicomSCPPreference.java @@ -27,8 +27,8 @@ import java.util.concurrent.Executors; @NrgPreferenceBean(toolId = "dicomScpManager", toolName = "DICOM SCP Manager", description = "Manages configuration of the various DICOM SCP endpoints on the XNAT system.") public class DicomSCPPreference extends AbstractPreferenceBean { @Autowired - public DicomSCPPreference(final XnatUserProvider provider, final ApplicationContext context) { - _provider = provider; + public DicomSCPPreference(final XnatUserProvider primaryAdminUserProvider, final ApplicationContext context) { + _provider = primaryAdminUserProvider; _context = context; } @@ -36,6 +36,37 @@ public class DicomSCPPreference extends AbstractPreferenceBean { return getDicomSCPInstances().containsKey(Integer.toString(id)); } + @SuppressWarnings("unused") + public List<DicomSCPInstance> getDicomSCPAtAETitle(final String aeTitle) { + final List<DicomSCPInstance> found = new ArrayList<>(); + for (final DicomSCPInstance instance : getDicomSCPInstances().values()) { + if (StringUtils.equals(aeTitle, instance.getAeTitle())) { + found.add(instance); + } + } + return found; + } + + public DicomSCPInstance getDicomSCPAtPort(final int port) { + for (final DicomSCPInstance instance : getDicomSCPInstances().values()) { + if (port == instance.getPort() && instance.isEnabled()) { + return instance; + } + } + return null; + } + + @SuppressWarnings("unused") + public List<DicomSCPInstance> getAllDicomSCPsAtPort(final int port) { + final List<DicomSCPInstance> found = new ArrayList<>(); + for (final DicomSCPInstance instance : getDicomSCPInstances().values()) { + if (port == instance.getPort() && instance.isEnabled()) { + found.add(instance); + } + } + return found; + } + @NrgPreference(defaultValue = "{'1': {'id': '1', 'aeTitle': 'XNAT', 'port': 8104, 'enabled': true}}", key = "id") public Map<String, DicomSCPInstance> getDicomSCPInstances() { return getMapValue(PREF_ID); diff --git a/src/main/java/org/nrg/xapi/exceptions/DuplicateEnabledDICOMReceiverPort.java b/src/main/java/org/nrg/xapi/exceptions/DuplicateEnabledDICOMReceiverPort.java new file mode 100644 index 0000000000000000000000000000000000000000..292b4df55101f0e97af841d32e2a6e17031f7020 --- /dev/null +++ b/src/main/java/org/nrg/xapi/exceptions/DuplicateEnabledDICOMReceiverPort.java @@ -0,0 +1,9 @@ +package org.nrg.xapi.exceptions; + +import org.nrg.framework.exceptions.NrgServiceException; + +public class DuplicateEnabledDICOMReceiverPort extends NrgServiceException { + public DuplicateEnabledDICOMReceiverPort(final String message) { + super(message); + } +} diff --git a/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApi.java b/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApi.java index ce166f5dea24770375e60c0fc4ab2d24be98680c..04c79ec7b7b2bc242be8563994f0b65deabf24ab 100644 --- a/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApi.java +++ b/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApi.java @@ -6,8 +6,11 @@ import org.nrg.dcm.DicomSCPManager; import org.nrg.dcm.preferences.DicomSCPInstance; import org.nrg.framework.annotations.XapiRestController; import org.nrg.framework.exceptions.NrgServiceException; +import org.nrg.xapi.exceptions.DuplicateEnabledDICOMReceiverPort; import org.nrg.xapi.rest.NotFoundException; import org.nrg.xdat.rest.AbstractXapiRestController; +import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -24,21 +27,45 @@ import java.util.List; public class DicomSCPApi extends AbstractXapiRestController { @Autowired - public DicomSCPApi(final DicomSCPManager manager) { + public DicomSCPApi(final DicomSCPManager manager, final UserManagementServiceI userManagementService, final RoleHolder roleHolder) { + super(userManagementService, roleHolder); _manager = manager; } @ApiOperation(value = "Get list of all configured DICOM SCP receiver definitions.", notes = "The primary DICOM SCP retrieval function returns a list of all DICOM SCP receivers defined for the current system.", response = DicomSCPInstance.class, responseContainer = "List") @ApiResponses({@ApiResponse(code = 200, message = "A list of DICOM SCP receiver definitions."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET) + @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) @ResponseBody public ResponseEntity<List<DicomSCPInstance>> dicomSCPsGet() { return new ResponseEntity<>(_manager.getDicomSCPInstances(), HttpStatus.OK); } + @ApiOperation(value = "Creates a new DICOM SCP receiver from the request body.", notes = "The newly created DICOM SCP receiver instance is returned from the call. This should include the instance ID for the new object.", response = DicomSCPInstance.class) + @ApiResponses({@ApiResponse(code = 200, message = "The newly created DICOM SCP receiver definition."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to view this DICOM SCP receiver definition."), @ApiResponse(code = 409, message = "A DICOM SCP receiver already exists and is enabled at the same port."), @ApiResponse(code = 500, message = "Unexpected error")}) + @RequestMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST) + @ResponseBody + public ResponseEntity<DicomSCPInstance> dicomSCPCreate(@RequestBody final DicomSCPInstance instance) throws DuplicateEnabledDICOMReceiverPort { + HttpStatus status = isPermitted(); + if (status != null) { + return new ResponseEntity<>(status); + } + try { + _manager.create(instance); + } catch (final NrgServiceException e) { + switch (e.getServiceError()) { + case AlreadyInitialized: + throw new DuplicateEnabledDICOMReceiverPort(e.getMessage()); + case Unknown: + _log.error("An error occurred trying to create a new DICOM SCP instance", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + return new ResponseEntity<>(instance, HttpStatus.OK); + } + @ApiOperation(value = "Gets the DICOM SCP receiver definition with the specified ID.", notes = "Returns the DICOM SCP receiver definition with the specified ID.", response = DicomSCPInstance.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver definition successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to view this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) + @RequestMapping(value = {"/{id}"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.GET}) public ResponseEntity<DicomSCPInstance> dicomSCPInstanceGet(@ApiParam(value = "ID of the DICOM SCP receiver definition to fetch", required = true) @PathVariable("id") final int id) { HttpStatus status = isPermitted(); if (status != null) { @@ -48,9 +75,9 @@ public class DicomSCPApi extends AbstractXapiRestController { : new ResponseEntity<DicomSCPInstance>(HttpStatus.NOT_FOUND); } - @ApiOperation(value = "Creates or updates the DICOM SCP receiver definition object with the specified ID.", notes = "Returns the updated DICOM SCP receiver definition.", response = DicomSCPInstance.class) + @ApiOperation(value = "Updates the DICOM SCP receiver definition object with the specified ID.", notes = "Returns the updated DICOM SCP receiver definition.", response = DicomSCPInstance.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver definition successfully created or updated."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to create or update this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/{id}"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<DicomSCPInstance> dicomSCPInstanceCreateOrUpdate(@ApiParam(value = "The ID of the DICOM SCP receiver definition to create or update.", required = true) @PathVariable("id") final int id, @RequestBody final DicomSCPInstance instance) throws NotFoundException { HttpStatus status = isPermitted(); if (status != null) { @@ -77,7 +104,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Deletes the DICOM SCP receiver definition object with the specified ID.", notes = "This call will stop the receiver if it's currently running.", response = Void.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver definition successfully created or updated."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to delete this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.DELETE}) + @RequestMapping(value = {"/{id}"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.DELETE}) public ResponseEntity<Void> dicomSCPInstanceDelete(@ApiParam(value = "The ID of the DICOM SCP receiver definition to delete.", required = true) @PathVariable("id") final int id) throws NotFoundException { HttpStatus status = isPermitted(); if (status != null) { @@ -97,7 +124,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Returns whether the DICOM SCP receiver definition with the specified ID is enabled.", notes = "Returns true or false based on whether the specified DICOM SCP receiver definition is enabled or not.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver definition enabled status successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to view this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}/enabled"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) + @RequestMapping(value = {"/{id}/enabled"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.GET}) public ResponseEntity<Boolean> dicomSCPInstanceEnabledGet(@ApiParam(value = "The ID of the DICOM SCP receiver definition to retrieve the enabled status for.", required = true) @PathVariable("id") final int id) { HttpStatus status = isPermitted(); if (status != null) { @@ -109,7 +136,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Sets the DICOM SCP receiver definition's enabled state.", notes = "Sets the enabled state of the DICOM SCP receiver definition with the specified ID to the value of the flag parameter.", response = Void.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver definition enabled status successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}/enabled/{flag}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/{id}/enabled/{flag}"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<Void> dicomSCPInstanceSetEnabledFlag(@ApiParam(value = "ID of the DICOM SCP receiver definition to modify", required = true) @PathVariable("id") final int id, @ApiParam(value = "The value to set for the enabled status.", required = true) @PathVariable("flag") final Boolean flag) { HttpStatus status = isPermitted(); @@ -134,7 +161,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Starts all enabled DICOM SCP receivers.", notes = "This starts all enabled DICOM SCP receivers. The return value contains the definitions of all of the started receivers.", responseContainer = "List", response = DicomSCP.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receivers successfully started."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/start"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/start"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<List<DicomSCP>> dicomSCPInstancesStart() { HttpStatus status = isPermitted(); if (status != null) { @@ -145,7 +172,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Starts the DICOM SCP receiver.", notes = "This starts the DICOM SCP receiver. Note that this will start the receiver regardless of its enabled or disabled setting. This returns true if the instance was started and false if not.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver successfully started."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}/start"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/{id}/start"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<Boolean> dicomSCPInstanceStart(@ApiParam(value = "ID of the DICOM SCP receiver to start.", required = true) @PathVariable("id") final int id) { HttpStatus status = isPermitted(); if (status != null) { @@ -160,7 +187,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Stops all enabled DICOM SCP receivers.", notes = "This stops all enabled DICOM SCP receivers. The return value contains the definitions of all of the started receivers.", responseContainer = "List", response = DicomSCP.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receivers successfully stopped."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/stop"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/stop"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<List<DicomSCP>> dicomSCPInstancesStop() { HttpStatus status = isPermitted(); if (status != null) { @@ -171,7 +198,7 @@ public class DicomSCPApi extends AbstractXapiRestController { @ApiOperation(value = "Stops the DICOM SCP receiver.", notes = "This stops the DICOM SCP receiver. Note that this will stop the receiver regardless of its enabled or disabled setting. This returns true if the instance was stopped and false if not.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "DICOM SCP receiver successfully stopped."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this DICOM SCP receiver definition."), @ApiResponse(code = 404, message = "DICOM SCP receiver definition not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/{id}/stop"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/{id}/stop"}, produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.PUT}) public ResponseEntity<Boolean> dicomSCPInstanceStop(@ApiParam(value = "ID of the DICOM SCP receiver to stop.", required = true) @PathVariable("id") final int id) { HttpStatus status = isPermitted(); if (status != null) { diff --git a/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApiAdvice.java b/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApiAdvice.java new file mode 100644 index 0000000000000000000000000000000000000000..7e80a1180147b052a0a8ffccf0c2fcb12aaa52e2 --- /dev/null +++ b/src/main/java/org/nrg/xapi/rest/dicomscp/DicomSCPApiAdvice.java @@ -0,0 +1,21 @@ +package org.nrg.xapi.rest.dicomscp; + +import org.nrg.framework.exceptions.NrgServiceException; +import org.nrg.xapi.exceptions.DuplicateEnabledDICOMReceiverPort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class DicomSCPApiAdvice { + @ExceptionHandler(DuplicateEnabledDICOMReceiverPort.class) + public ResponseEntity<String> handleDuplicateEnabledDICOMReceiverPort(final DuplicateEnabledDICOMReceiverPort exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.CONFLICT); + } + + @ExceptionHandler(NrgServiceException.class) + public ResponseEntity<String> handleNrgServiceException(final NrgServiceException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.CONFLICT); + } +} 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 e3e37fede60e8c679c92d5489bf54e00be103d43..e2922e1b6e8f47b234a80430bff6a62ca94971a0 100644 --- a/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java +++ b/src/main/java/org/nrg/xapi/rest/event/EventHandlerApi.java @@ -18,12 +18,13 @@ import org.nrg.framework.event.Filterable; import org.nrg.framework.utilities.BasicXnatResourceLocator; import org.nrg.xapi.model.event.EventClassInfo; import org.nrg.xapi.model.event.EventHandlerFilterInfo; -import org.nrg.xdat.XDAT; import org.nrg.xdat.om.XnatProjectdata; import org.nrg.xdat.om.base.auto.AutoXnatProjectdata; +import org.nrg.xdat.rest.AbstractXapiRestController; import org.nrg.xdat.security.XDATUser; import org.nrg.xdat.security.helpers.Permissions; import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xft.security.UserI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,13 +35,11 @@ import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import javax.annotation.PostConstruct; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -56,45 +55,19 @@ import java.util.Properties; */ @Api(description = "The XNAT Event Handler API") @XapiRestController -public class EventHandlerApi { - - /** - * The Constant _log. - */ - private static final Logger _log = LoggerFactory.getLogger(EventHandlerApi.class); - - /** The maximum number of event IDs to return for each event class in each project. */ - private static final int MAX_EVENT_IDS_LIST = 20; - - /** The _role holder. */ - @Autowired - private RoleHolder _roleHolder; - - /** - * The event ids service. - */ - @Autowired - private HibernateAutomationEventIdsIdsService eventIdsService; - - /** - * The filters service. - */ +public class EventHandlerApi extends AbstractXapiRestController { @Autowired - private HibernateAutomationFiltersService filtersService; - - /** - * Inits the this. - */ - @PostConstruct - private void initThis() { - getEventIdsService(); - getFiltersService(); + public EventHandlerApi(final UserManagementServiceI userManagementService, final RoleHolder roleHolder, final HibernateAutomationFiltersService filtersService, final HibernateAutomationEventIdsIdsService eventIdsService) { + super(userManagementService, roleHolder); + _filtersService = filtersService; + _eventIdsService = eventIdsService; } /** * Automation event classes get. * * @param project_id the project_id + * * @return the response entity */ @ApiOperation(value = "Get list of event classes.", notes = "Returns a list of classes implementing AutomationEventI.", response = List.class) @@ -102,15 +75,15 @@ public class EventHandlerApi { @RequestMapping(value = {"/projects/{project_id}/eventHandlers/automationEventClasses"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET) @ResponseBody public ResponseEntity<List<EventClassInfo>> automationEventClassesGetByProject(@PathVariable("project_id") String project_id) { - final HttpStatus status = isPermitted(project_id); + final HttpStatus status = canEditProject(project_id); if (status != null) { return new ResponseEntity<>(status); } try { - return new ResponseEntity<>(getEventInfoList(project_id), HttpStatus.OK); + return new ResponseEntity<>(getEventInfoList(project_id), HttpStatus.OK); } catch (Throwable t) { - _log.error("EventHandlerApi exception: " + t.toString()); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + _log.error("EventHandlerApi exception: " + t.toString()); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -124,15 +97,15 @@ public class EventHandlerApi { @RequestMapping(value = {"/eventHandlers/automationEventClasses"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET) @ResponseBody public ResponseEntity<List<EventClassInfo>> automationEventClassesGet() { - final HttpStatus status = isPermitted(null); + final HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); } try { - return new ResponseEntity<>(getEventInfoList(null), HttpStatus.OK); + return new ResponseEntity<>(getEventInfoList(null), HttpStatus.OK); } catch (Throwable t) { - _log.error("EventHandlerApi exception: " + t.toString()); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + _log.error("EventHandlerApi exception: " + t.toString()); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -140,15 +113,16 @@ public class EventHandlerApi { * Gets the event info list. * * @param project_id the project_id + * * @return the event info list */ private List<EventClassInfo> getEventInfoList(String project_id) { - final List<EventClassInfo> eventInfoList = Lists.newArrayList(); - final List<AutomationEventIdsIds> eventIdsList = getEventIdsService().getEventIds(project_id, false, MAX_EVENT_IDS_LIST); - final List<AutomationFilters> filtersList = getFiltersService().getAutomationFilters(project_id, false); + final List<EventClassInfo> eventInfoList = Lists.newArrayList(); + final List<AutomationEventIdsIds> eventIdsList = _eventIdsService.getEventIds(project_id, false, MAX_EVENT_IDS_LIST); + final List<AutomationFilters> filtersList = _filtersService.getAutomationFilters(project_id, false); for (final String className : getEventClassList(eventIdsList)) { - final EventClassInfo eci = new EventClassInfo(className); - final List<String> eventIds = eci.getEventIds(); + final EventClassInfo eci = new EventClassInfo(className); + final List<String> eventIds = eci.getEventIds(); final Map<String, EventHandlerFilterInfo> filterableFields = eci.getFilterableFieldsMap(); if (eci.getIncludeEventIdsFromDatabase()) { for (final AutomationEventIdsIds autoIds : eventIdsList) { @@ -165,24 +139,23 @@ public class EventHandlerApi { if (method.isAnnotationPresent(Filterable.class) && method.getName().substring(0, 3).equalsIgnoreCase("get")) { final char c[] = method.getName().substring(3).toCharArray(); c[0] = Character.toLowerCase(c[0]); - final String column = new String(c); - final Annotation anno = AnnotationUtils.findAnnotation(method, Filterable.class); + final String column = new String(c); + final Annotation anno = AnnotationUtils.findAnnotation(method, Filterable.class); - final Object annoInitialValuesObj = AnnotationUtils.getValue(anno, "initialValues"); - final String[] annoInitialValues = (annoInitialValuesObj != null && annoInitialValuesObj instanceof String[]) ? (String[]) annoInitialValuesObj : new String[] {}; + final Object annoInitialValuesObj = AnnotationUtils.getValue(anno, "initialValues"); + final String[] annoInitialValues = (annoInitialValuesObj != null && annoInitialValuesObj instanceof String[]) ? (String[]) annoInitialValuesObj : new String[]{}; - final Object annoDefaultValueObj = AnnotationUtils.getValue(anno, "defaultValue"); - final String annoDefaultValue = (annoDefaultValueObj != null) ? annoDefaultValueObj.toString() : ""; + final Object annoDefaultValueObj = AnnotationUtils.getValue(anno, "defaultValue"); + final String annoDefaultValue = (annoDefaultValueObj != null) ? annoDefaultValueObj.toString() : ""; final Object annoFilterRequired = AnnotationUtils.getValue(anno, "filterRequired"); - boolean filterRequired = (annoFilterRequired == null || !(annoFilterRequired instanceof Boolean)) ? false : (boolean) annoFilterRequired; + boolean filterRequired = !(annoFilterRequired == null || !(annoFilterRequired instanceof Boolean)) && (boolean) annoFilterRequired; final Object annoIncludeValuesFromDatabase = AnnotationUtils.getValue(anno, "includeValuesFromDatabase"); - boolean includeValuesFromDatabase = (annoIncludeValuesFromDatabase == null || !(annoIncludeValuesFromDatabase instanceof Boolean)) ? true :(boolean) annoIncludeValuesFromDatabase; + boolean includeValuesFromDatabase = (annoIncludeValuesFromDatabase == null || !(annoIncludeValuesFromDatabase instanceof Boolean)) || (boolean) annoIncludeValuesFromDatabase; if (!filterableFields.containsKey(column)) { - EventHandlerFilterInfo filterInfo = new EventHandlerFilterInfo(); - filterInfo.setFilterValues(new ArrayList<String>()); - final List<String> newValueList = Lists.newArrayList(); + EventHandlerFilterInfo filterInfo = new EventHandlerFilterInfo(); + filterInfo.setFilterValues(new ArrayList<String>()); filterableFields.put(column, filterInfo); } final EventHandlerFilterInfo filterInfo = filterableFields.get(column); @@ -200,19 +173,19 @@ public class EventHandlerApi { } } Collections.sort(valueList); - + if (!filterRequired) { - // TODO: Should probably add an EventFilterInfo class and keep the list of filter values there, along with a - // a boolean required value and a default value. - // NOTE: This is handled in JavaScript as non-required filter - valueList.add(0,"_FILTER_NOT_REQUIRED_"); + // TODO: Should probably add an EventFilterInfo class and keep the list of filter values there, along with a + // a boolean required value and a default value. + // NOTE: This is handled in JavaScript as non-required filter + valueList.add(0, "_FILTER_NOT_REQUIRED_"); } } } } catch (SecurityException | ClassNotFoundException e) { for (final AutomationFilters autoFilters : filtersList) { if (!filterableFields.containsKey(autoFilters.getField())) { - EventHandlerFilterInfo filterInfo = new EventHandlerFilterInfo(); + EventHandlerFilterInfo filterInfo = new EventHandlerFilterInfo(); final List<String> valueList = Lists.newArrayList(autoFilters.getValues()); filterInfo.setFilterValues(valueList); filterInfo.setFilterRequired(false); @@ -239,32 +212,33 @@ public class EventHandlerApi { * Gets the event class list. * * @param eventIdsList the event ids list + * * @return the event class list */ private List<String> getEventClassList(List<AutomationEventIdsIds> eventIdsList) { final List<String> classList = Lists.newArrayList(); try { - for (final Resource resource : BasicXnatResourceLocator.getResources("classpath*:META-INF/xnat/event/*-event.properties")) { - final Properties properties = PropertiesLoaderUtils.loadProperties(resource); - if (!properties.containsKey(EventClass.EVENT_CLASS)) { - continue; - } - final String clssStr = properties.get(EventClass.EVENT_CLASS).toString(); - try { - final Class<?> clazz = Class.forName(clssStr); - if (AutomationEventImplementerI.class.isAssignableFrom(clazz) && !clazz.isInterface() && - !Modifier.isAbstract(clazz.getModifiers())) { - if (!classList.contains(clazz.getName())) { - classList.add(clazz.getName()); - } - } - } catch (ClassNotFoundException cex) { - _log.debug("Could not load class for class name (" + clssStr + ")"); - } - } - } catch (IOException e) { - _log.debug("Could not load event class properties resources (META-INF/xnat/event/*-event.properties)"); - } + for (final Resource resource : BasicXnatResourceLocator.getResources("classpath*:META-INF/xnat/event/*-event.properties")) { + final Properties properties = PropertiesLoaderUtils.loadProperties(resource); + if (!properties.containsKey(EventClass.EVENT_CLASS)) { + continue; + } + final String clssStr = properties.get(EventClass.EVENT_CLASS).toString(); + try { + final Class<?> clazz = Class.forName(clssStr); + if (AutomationEventImplementerI.class.isAssignableFrom(clazz) && !clazz.isInterface() && + !Modifier.isAbstract(clazz.getModifiers())) { + if (!classList.contains(clazz.getName())) { + classList.add(clazz.getName()); + } + } + } catch (ClassNotFoundException cex) { + _log.debug("Could not load class for class name (" + clssStr + ")"); + } + } + } catch (IOException e) { + _log.debug("Could not load event class properties resources (META-INF/xnat/event/*-event.properties)"); + } // I think for now we'll not pull from the database if we've found event classes. If the database // contains any thing different, it should only be event classes that are no longer available. if (classList.size() < 1) { @@ -277,50 +251,15 @@ public class EventHandlerApi { return classList; } - /** - * Gets the event ids service. - * - * @return the event ids service - */ - private HibernateAutomationEventIdsIdsService getEventIdsService() { - if (eventIdsService == null) { - eventIdsService = XDAT.getContextService().getBean(HibernateAutomationEventIdsIdsService.class); - } - return eventIdsService; - } - - /** - * Gets the filters service. - * - * @return the filters service - */ - private HibernateAutomationFiltersService getFiltersService() { - if (filtersService == null) { - filtersService = XDAT.getContextService().getBean(HibernateAutomationFiltersService.class); - } - return filtersService; - } - - /** - * Gets the session user. - * - * @return the session user - */ - private UserI getSessionUser() { - final Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - if ((principal instanceof UserI)) { - return (UserI) principal; - } - return null; - } - /** * Checks if is permitted. * * @param projectId the project ID + * * @return the http status */ - private HttpStatus isPermitted(String projectId) { + // TODO: Migrate this to the abstract superclass. Can't right now because XDAT doesn't know about XnatProjectdata, etc. + protected HttpStatus canEditProject(String projectId) { final UserI sessionUser = getSessionUser(); if ((sessionUser instanceof XDATUser)) { if (projectId != null) { @@ -332,10 +271,23 @@ public class EventHandlerApi { return HttpStatus.INTERNAL_SERVER_ERROR; } } else { - return (_roleHolder.isSiteAdmin(sessionUser)) ? null : HttpStatus.FORBIDDEN; + return isPermitted() == null ? null : HttpStatus.FORBIDDEN; } } _log.error("Error checking read status for project"); return HttpStatus.INTERNAL_SERVER_ERROR; } + + /** + * The Constant _log. + */ + private static final Logger _log = LoggerFactory.getLogger(EventHandlerApi.class); + + /** + * The maximum number of event IDs to return for each event class in each project. + */ + private static final int MAX_EVENT_IDS_LIST = 20; + + private final HibernateAutomationEventIdsIdsService _eventIdsService; + private final HibernateAutomationFiltersService _filtersService; } 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 ebb5c42a9e22c2bbc2a7227fb4d4ed7f5ead0ecc..314181db60ff6a8a31a2c45f0632717ee6229c12 100644 --- a/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java +++ b/src/main/java/org/nrg/xapi/rest/notifications/NotificationsApi.java @@ -5,17 +5,16 @@ import org.apache.commons.lang3.StringUtils; import org.nrg.framework.annotations.XapiRestController; import org.nrg.framework.exceptions.NrgServiceError; import org.nrg.framework.exceptions.NrgServiceRuntimeException; -import org.nrg.notify.services.NotificationService; import org.nrg.prefs.exceptions.InvalidPreferenceName; import org.nrg.xapi.exceptions.InitializationException; import org.nrg.xdat.preferences.NotificationsPreferences; import org.nrg.xdat.rest.AbstractXapiRestController; +import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.utils.XnatHttpUtils; 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.MediaType; import org.springframework.http.ResponseEntity; @@ -24,7 +23,9 @@ import org.springframework.web.bind.annotation.*; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; @Api(description = "XNAT Notifications management API") @XapiRestController @@ -45,6 +46,15 @@ public class NotificationsApi extends AbstractXapiRestController { + "remove existing properties by setting the property with an empty value. This will " + "modify the existing server configuration. You can completely replace the configuration " + "by calling the POST version of this method."; + + @Inject + public NotificationsApi(final UserManagementServiceI userManagementService, final RoleHolder roleHolder, final NotificationsPreferences notificationsPrefs, final JavaMailSenderImpl javaMailSender, final XnatAppInfo appInfo) { + super(userManagementService, roleHolder); + _notificationsPrefs = notificationsPrefs; + _javaMailSender = javaMailSender; + _appInfo = appInfo; + } + @ApiOperation(value = "Returns the full map of 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(produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) @@ -67,10 +77,10 @@ public class NotificationsApi extends AbstractXapiRestController { preferences.put("siteUrl", XnatHttpUtils.getServerRoot(request)); } - preferences.put("notifications.emailRecipientErrorMessages",_notificationsPrefs.getEmailRecipientErrorMessages()); - preferences.put("notifications.emailRecipientIssueReports",_notificationsPrefs.getEmailRecipientIssueReports()); - preferences.put("notifications.emailRecipientNewUserAlert",_notificationsPrefs.getEmailRecipientNewUserAlert()); - preferences.put("notifications.emailRecipientUpdate",_notificationsPrefs.getEmailRecipientUpdate()); + preferences.put("notifications.emailRecipientErrorMessages", _notificationsPrefs.getEmailRecipientErrorMessages()); + preferences.put("notifications.emailRecipientIssueReports", _notificationsPrefs.getEmailRecipientIssueReports()); + preferences.put("notifications.emailRecipientNewUserAlert", _notificationsPrefs.getEmailRecipientNewUserAlert()); + preferences.put("notifications.emailRecipientUpdate", _notificationsPrefs.getEmailRecipientUpdate()); return new ResponseEntity<>(preferences, HttpStatus.OK); } @@ -84,29 +94,19 @@ public class NotificationsApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } - if (_log.isInfoEnabled()) { - 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.info(message.toString()); - } + logSetProperties(properties); for (final String name : properties.keySet()) { try { - if(StringUtils.equals(name, "notifications.emailRecipientErrorMessages")){ + if (StringUtils.equals(name, "notifications.emailRecipientErrorMessages")) { _notificationsPrefs.setEmailRecipientErrorMessages(properties.get(name)); - } - else if(StringUtils.equals(name, "notifications.emailRecipientIssueReports")){ + } else if (StringUtils.equals(name, "notifications.emailRecipientIssueReports")) { _notificationsPrefs.setEmailRecipientIssueReports(properties.get(name)); - } - else if(StringUtils.equals(name, "notifications.emailRecipientNewUserAlert")){ + } else if (StringUtils.equals(name, "notifications.emailRecipientNewUserAlert")) { _notificationsPrefs.setEmailRecipientNewUserAlert(properties.get(name)); - } - else if(StringUtils.equals(name, "notifications.emailRecipientUpdate")){ + } else if (StringUtils.equals(name, "notifications.emailRecipientUpdate")) { _notificationsPrefs.setEmailRecipientUpdate(properties.get(name)); - } - else { + } else { _notificationsPrefs.set(properties.get(name), name); } if (_log.isInfoEnabled()) { @@ -116,10 +116,6 @@ public class NotificationsApi extends AbstractXapiRestController { _log.error("Got an invalid preference name error for the preference: " + name + ", which is weird because the site configuration is not strict"); } } -// ArcSpecManager initializaton not required for notifications since none of their properties are set in the ArcSpec. -// if (properties.containsKey("initialized") && StringUtils.equals("true", properties.get("initialized"))) { -// initialize(); -// } return new ResponseEntity<>(HttpStatus.OK); } @@ -133,13 +129,7 @@ public class NotificationsApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } - if (_log.isInfoEnabled()) { - 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.info(message.toString()); - } + logSetProperties(properties); for (final String name : properties.keySet()) { try { @@ -158,7 +148,7 @@ public class NotificationsApi extends AbstractXapiRestController { String username = _notificationsPrefs.getUsername(); String password = _notificationsPrefs.getPassword(); - logConfigurationSubmit(host,port,protocol,username,password, properties); + logConfigurationSubmit(host, port, protocol, username, password, properties); setHost(host, false); setPort(port); @@ -166,23 +156,13 @@ public class NotificationsApi extends AbstractXapiRestController { setUsername(username); setPassword(password); - final Properties javaMailProperties = new Properties(); - if (properties != null) { - for (final String property : properties.keySet()) { - final String value = properties.get(property); - if (StringUtils.isNotBlank(value)) { - javaMailProperties.setProperty(property, value); - } - } - } - _javaMailSender.setJavaMailProperties(javaMailProperties); + _javaMailSender.setJavaMailProperties(getSubmittedProperties(properties)); setSmtp(); return new ResponseEntity<>(HttpStatus.OK); } - @ApiOperation(value = "Returns the full SMTP server configuration.", notes = "Returns the configuration as a map of the standard Java mail sender properties–host, port, protocol, username, and password–along with any extended properties required for the configuration, e.g. configuring SSL- or TLS-secured SMTP services.", response = Properties.class) @ApiResponses({@ApiResponse(code = 200, message = "SMTP service 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 = "smtp", produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) @@ -241,6 +221,14 @@ public class NotificationsApi extends AbstractXapiRestController { setUsername(username); setPassword(password); + _javaMailSender.setJavaMailProperties(getSubmittedProperties(properties)); + + setSmtp(); + + return getSmtpServerProperties(); + } + + protected Properties getSubmittedProperties(final Map<String, String> properties) { // Set all of the submitted properties. final Properties javaMailProperties = new Properties(); if (properties != null) { @@ -260,11 +248,7 @@ public class NotificationsApi extends AbstractXapiRestController { javaMailProperties.setProperty(property, ""); } } - _javaMailSender.setJavaMailProperties(javaMailProperties); - - setSmtp(); - - return getSmtpServerProperties(); + return javaMailProperties; } @ApiOperation(value = "Sets the submitted mail service properties. This returns the SMTP server configuration as it exists after being set.", notes = PUT_PROPERTIES_NOTES, response = Properties.class) @@ -690,17 +674,7 @@ public class NotificationsApi extends AbstractXapiRestController { private static final Logger _log = LoggerFactory.getLogger(NotificationsApi.class); private static final String NOT_SET = "NotSet"; - @Autowired - @Lazy - private NotificationsPreferences _notificationsPrefs; - - @Inject - private JavaMailSenderImpl _javaMailSender; - - @Inject - private NotificationService _notificationService; - - @Autowired - @Lazy - private XnatAppInfo _appInfo; + private final NotificationsPreferences _notificationsPrefs; + private final JavaMailSenderImpl _javaMailSender; + private final XnatAppInfo _appInfo; } diff --git a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java index 8efe9d55314e6afe2027f7b5f5eb6778c5035a22..628af014ba9952124baf0a441413e33a041ab102 100644 --- a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java +++ b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java @@ -8,13 +8,14 @@ import org.nrg.prefs.exceptions.InvalidPreferenceName; import org.nrg.xapi.exceptions.InitializationException; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.rest.AbstractXapiRestController; +import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.turbine.utils.ArcSpecManager; import org.nrg.xnat.utils.XnatHttpUtils; 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.MediaType; import org.springframework.http.ResponseEntity; @@ -33,6 +34,13 @@ import java.util.Properties; @XapiRestController @RequestMapping(value = "/siteConfig") public class SiteConfigApi extends AbstractXapiRestController { + @Autowired + public SiteConfigApi(final SiteConfigPreferences preferences, final UserManagementServiceI userManagementService, final RoleHolder roleHolder, final XnatAppInfo appInfo) { + super(userManagementService, roleHolder); + _preferences = preferences; + _appInfo = appInfo; + } + @ApiOperation(value = "Returns a map of application build properties.", notes = "This includes the implementation version, Git commit hash, and build number and number.", response = Properties.class) @ApiResponses({@ApiResponse(code = 200, message = "Application build properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = "buildInfo", produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) @@ -149,14 +157,6 @@ public class SiteConfigApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } - if (_log.isInfoEnabled()) { - 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.info(message.toString()); - } - // Is this call initializing the system? final boolean isInitializing = properties.containsKey("initialized") && StringUtils.equals("true", properties.get("initialized")); for (final String name : properties.keySet()) { @@ -227,11 +227,6 @@ public class SiteConfigApi extends AbstractXapiRestController { private static final Logger _log = LoggerFactory.getLogger(SiteConfigApi.class); - @Autowired - @Lazy - private SiteConfigPreferences _preferences; - - @Autowired - @Lazy - private XnatAppInfo _appInfo; + private final SiteConfigPreferences _preferences; + private final XnatAppInfo _appInfo; } 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 69fb69b2ea31264d4335e4a46919402db4d984ac..b650d8d041644e8fe8c2071e1ddb7462e5f51376 100644 --- a/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java +++ b/src/main/java/org/nrg/xapi/rest/theme/ThemeApi.java @@ -16,17 +16,16 @@ import org.apache.commons.io.FileUtils; 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.rest.AbstractXapiRestController; import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xdat.services.ThemeService; -import org.nrg.xft.security.UserI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -41,27 +40,28 @@ import java.util.List; @Api(description = "XNAT Theme Management API") @XapiRestController @RequestMapping(value = "/theme") -public class ThemeApi { - private static final Logger _log = LoggerFactory.getLogger(ThemeApi.class); - +public class ThemeApi extends AbstractXapiRestController { @Autowired - private ThemeService themeService; + public ThemeApi(final ThemeService themeService, final UserManagementServiceI userManagementService, final RoleHolder roleHolder) { + super(userManagementService, roleHolder); + _themeService = themeService; + } @ApiOperation(value = "Get the currently selected global theme or a role based theme if specified.", notes = "Use this to get the theme selected by the system administrator on the Theme Management page.", response = ThemeConfig.class, responseContainer = "ThemeConfig") @ApiResponses({@ApiResponse(code = 200, message = "Reports the currently selected global theme (if there is one) and whether or not it's enabled."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = {"/{role}"}, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET) public ResponseEntity<ThemeConfig> themeGet(@ApiParam(value = "\"global\" or role name of currently set theme", required = true) @PathVariable("role") String role) { - if("global".equalsIgnoreCase(role)){ - return new ResponseEntity<>(themeService.getTheme(), HttpStatus.OK); + if ("global".equalsIgnoreCase(role)) { + return new ResponseEntity<>(_themeService.getTheme(), HttpStatus.OK); } - return new ResponseEntity<>(themeService.getTheme(role), HttpStatus.OK); + return new ResponseEntity<>(_themeService.getTheme(role), HttpStatus.OK); } @ApiOperation(value = "Get list of available themes.", notes = "Use this to get a list of all available themes on the XNAT system.", response = ThemeService.TypeOption.class, responseContainer = "List") @ApiResponses({@ApiResponse(code = 200, message = "Reports the currently selected global theme (if there is one), whether or not it's enabled, and a list of available themes on the system in a JSON string."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET) public ResponseEntity<List<ThemeService.TypeOption>> themesGet() { - return new ResponseEntity<>(themeService.loadExistingThemes(), HttpStatus.OK); + return new ResponseEntity<>(_themeService.loadExistingThemes(), HttpStatus.OK); } @ApiOperation(value = "Deletes the theme with the specified name.", notes = "Returns success on deletion. ", response = String.class) @@ -73,20 +73,20 @@ public class ThemeApi { if (status != null) { return new ResponseEntity<>(status); } - if("null".equals(theme)){ + if ("null".equals(theme)) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - if(!themeService.themeExists(theme)) { + if (!_themeService.themeExists(theme)) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } try { - File f = new File(themeService.getThemesPath() + File.separator + theme); + File f = new File(_themeService.getThemesPath() + File.separator + theme); FileUtils.deleteDirectory(f); - if(!f.exists()) { - themeConfig = themeService.getTheme(); + if (!f.exists()) { + themeConfig = _themeService.getTheme(); String themeName = (themeConfig != null) ? themeConfig.getName() : null; if (theme.equals(themeName)) { - themeService.setTheme((ThemeConfig) null); + _themeService.setTheme((ThemeConfig) null); } } } catch (Exception e) { @@ -99,7 +99,7 @@ public class ThemeApi { @ApiOperation(value = "Sets the current global theme to the one specified.", notes = "Returns the updated serialized theme object.", response = ThemeConfig.class) @ApiResponses({@ApiResponse(code = 200, message = "Successfully updated the current global theme."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to create or update this user."), @ApiResponse(code = 404, message = "Theme not found."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = {"/{theme}"}, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_HTML_VALUE}, method = {RequestMethod.PUT}) - public ResponseEntity<ThemeConfig> themePut(@ApiParam(value = "The name of the theme to select.", required = true) @PathVariable("theme") String theme, @RequestParam(value = "enabled", required=false, defaultValue="true") String enabled) throws NotFoundException { + public ResponseEntity<ThemeConfig> themePut(@ApiParam(value = "The name of the theme to select.", required = true) @PathVariable("theme") String theme, @RequestParam(value = "enabled", required = false, defaultValue = "true") String enabled) throws NotFoundException { HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); @@ -107,15 +107,15 @@ public class ThemeApi { ThemeConfig themeConfig; try { boolean themeEnabled = true; - if("false".equalsIgnoreCase(enabled)){ + if ("false".equalsIgnoreCase(enabled)) { themeEnabled = false; } - if("null".equals(theme)){ + if ("null".equals(theme)) { theme = null; } - themeConfig = themeService.setTheme(theme, themeEnabled); + themeConfig = _themeService.setTheme(theme, themeEnabled); } catch (ThemeService.ThemeNotFoundException e) { - _log.error(e.getInvalidTheme()+" not found."); + _log.error(e.getInvalidTheme() + " not found."); return new ResponseEntity<>(HttpStatus.NOT_FOUND); } catch (Exception e) { _log.error("An error occurred setting the theme " + theme, e); @@ -127,19 +127,19 @@ public class ThemeApi { @ApiOperation(value = "Accepts a multipart form with a zip file upload and extracts its contents in the theme system folder. If successful, the first (root) directory name (or theme name) unzipped is returned in the response. This will overwrite any other directories already existing with the same name without warning.", notes = "The structure of the zipped package must have only directories at it's root.", response = String.class) @ApiResponses({@ApiResponse(code = 200, message = "Theme package successfully uploaded and extracted."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to upload a theme package."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST}) - public ResponseEntity<List<ThemeService.TypeOption>> themePostUpload(@ApiParam(value = "Multipart file object being uploaded", required = true) @RequestParam(value="themePackage", required=false) MultipartFile themePackage) { + public ResponseEntity<List<ThemeService.TypeOption>> themePostUpload(@ApiParam(value = "Multipart file object being uploaded", required = true) @RequestParam(value = "themePackage", required = false) MultipartFile themePackage) { HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); } List<ThemeService.TypeOption> themeOptions = new ArrayList<>(); try { - if(!themePackage.getContentType().contains("zip")) { + if (!themePackage.getContentType().contains("zip")) { String error = "No valid files were uploaded. Theme package must be of type: application/x-zip-compressed"; _log.error(error); return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } - List<String> dirs = themeService.extractTheme(themePackage.getInputStream()); + List<String> dirs = _themeService.extractTheme(themePackage.getInputStream()); for (String dir : dirs) { themeOptions.add(new ThemeService.TypeOption(dir, dir)); } @@ -157,22 +157,7 @@ public class ThemeApi { return new ResponseEntity<>(themeOptions, HttpStatus.OK); } - private UserI getSessionUser() { - Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - if ((principal instanceof UserI)) { - return (UserI) principal; - } - return null; - } - - private HttpStatus isPermitted() { - UserI sessionUser = getSessionUser(); - if ((sessionUser instanceof XDATUser)) { - return _roleHolder.isSiteAdmin(sessionUser) ? null : HttpStatus.FORBIDDEN; - } - return null; - } + private static final Logger _log = LoggerFactory.getLogger(ThemeApi.class); - @Autowired - private RoleHolder _roleHolder; + private final ThemeService _themeService; } diff --git a/src/main/java/org/nrg/xapi/rest/users/UsersApi.java b/src/main/java/org/nrg/xapi/rest/users/UsersApi.java index dca118723dd34a2b6b3cadeaeccd3a6b51d6d261..af585d8c80e2f35922d1229670e6e85925e9a3a5 100644 --- a/src/main/java/org/nrg/xapi/rest/users/UsersApi.java +++ b/src/main/java/org/nrg/xapi/rest/users/UsersApi.java @@ -3,6 +3,8 @@ package org.nrg.xapi.rest.users; import io.swagger.annotations.*; import org.apache.commons.lang3.StringUtils; import org.nrg.framework.annotations.XapiRestController; +import org.nrg.framework.exceptions.NrgServiceError; +import org.nrg.framework.exceptions.NrgServiceRuntimeException; import org.nrg.xapi.model.users.User; import org.nrg.xapi.rest.NotFoundException; import org.nrg.xdat.XDAT; @@ -12,6 +14,7 @@ import org.nrg.xdat.security.UserGroupI; import org.nrg.xdat.security.helpers.Groups; import org.nrg.xdat.security.helpers.Users; import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xdat.security.user.exceptions.UserInitException; import org.nrg.xdat.security.user.exceptions.UserNotFoundException; import org.nrg.xdat.services.AliasTokenService; @@ -21,7 +24,6 @@ import org.nrg.xft.security.UserI; 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.MediaType; import org.springframework.http.ResponseEntity; @@ -33,7 +35,11 @@ import java.util.*; @XapiRestController @RequestMapping(value = "/users") public class UsersApi extends AbstractXapiRestController { - private static final Logger _log = LoggerFactory.getLogger(UsersApi.class); + @Autowired + public UsersApi(final SiteConfigPreferences preferences, final UserManagementServiceI userManagementService, final RoleHolder roleHolder) { + super(userManagementService, roleHolder); + _preferences = preferences; + } @ApiOperation(value = "Get list of users.", notes = "The primary users function returns a list of all users of the XNAT system.", response = User.class, responseContainer = "List") @ApiResponses({@ApiResponse(code = 200, message = "An array of users"), @ApiResponse(code = 500, message = "Unexpected error")}) @@ -60,21 +66,24 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } } - List<UserI> users = Users.getUsers(); - List<Map<String, String>> userMaps = new ArrayList<>(); - for (UserI user : users) { - try { - Map<String, String> userMap = new HashMap<>(); - userMap.put("firstname", user.getFirstname()); - userMap.put("lastname", user.getLastname()); - userMap.put("username", user.getUsername()); - userMap.put("email", user.getEmail()); - userMap.put("id", String.valueOf(user.getID())); - userMap.put("enabled", String.valueOf(user.isEnabled())); - userMap.put("verified", String.valueOf(user.isVerified())); - userMaps.add(userMap); - } catch (Exception e) { - _log.error("", e); + List<UserI> users = getUserManagementService().getUsers(); + List<Map<String, String>> userMaps = null; + if (users != null && users.size() > 0) { + userMaps = new ArrayList<>(); + for (UserI user : users) { + try { + Map<String, String> userMap = new HashMap<>(); + userMap.put("firstname", user.getFirstname()); + userMap.put("lastname", user.getLastname()); + userMap.put("username", user.getUsername()); + userMap.put("email", user.getEmail()); + userMap.put("id", String.valueOf(user.getID())); + userMap.put("enabled", String.valueOf(user.isEnabled())); + userMap.put("verified", String.valueOf(user.isVerified())); + userMaps.add(userMap); + } catch (Exception e) { + _log.error("", e); + } } } return new ResponseEntity<>(userMaps, HttpStatus.OK); @@ -90,7 +99,7 @@ public class UsersApi extends AbstractXapiRestController { } final UserI user; try { - user = Users.getUser(id); + user = getUserManagementService().getUser(id); return user == null ? new ResponseEntity<User>(HttpStatus.NOT_FOUND) : new ResponseEntity<>(new User(user), HttpStatus.OK); } catch (UserInitException e) { _log.error("An error occurred initializing the user " + id, e); @@ -110,12 +119,15 @@ public class UsersApi extends AbstractXapiRestController { } UserI user; try { - user = Users.getUser(username); + user = getUserManagementService().getUser(username); } catch (Exception e) { //Create new User - user = Users.createUser(); + user = getUserManagementService().createUser(); user.setLogin(username); } + if (user == null) { + throw new NrgServiceRuntimeException(NrgServiceError.Unknown, "Failed to retrieve or create a user object for user " + username); + } if ((StringUtils.isNotBlank(model.getFirstName())) && (!StringUtils.equals(model.getFirstName(), user.getFirstname()))) { user.setFirstname(model.getFirstName()); } @@ -141,7 +153,7 @@ public class UsersApi extends AbstractXapiRestController { } try { - Users.save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, Event.Modified, "", "")); + getUserManagementService().save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, Event.Modified, "", "")); return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { _log.error("Error occurred modifying user " + user.getLogin()); @@ -158,7 +170,7 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -180,13 +192,13 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } user.setEnabled(flag); try { - Users.save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, flag ? Event.Enabled : Event.Disabled, "", "")); + getUserManagementService().save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, flag ? Event.Enabled : Event.Disabled, "", "")); return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { _log.error("Error occurred " + (flag ? "enabling" : "disabling") + " user " + user.getLogin()); @@ -209,7 +221,7 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -231,13 +243,13 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } user.setVerified(flag); try { - Users.save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, flag ? Event.Enabled : Event.Disabled, "", "")); + getUserManagementService().save(user, getSessionUser(), false, new EventDetails(EventUtils.CATEGORY.DATA, EventUtils.TYPE.WEB_SERVICE, flag ? Event.Enabled : Event.Disabled, "", "")); return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { _log.error("Error occurred " + (flag ? "enabling" : "disabling") + " user " + user.getLogin()); @@ -254,41 +266,30 @@ public class UsersApi extends AbstractXapiRestController { @ApiOperation(value = "Returns the roles for the user with the specified user ID.", notes = "Returns a collection of the user's roles.", response = Collection.class) @ApiResponses({@ApiResponse(code = 200, message = "User roles successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to view this user."), @ApiResponse(code = 404, message = "User not found."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = {"/profiles/{id}/roles"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.GET}) - public ResponseEntity<Collection<String>> usersIdRolesGet(@ApiParam(value = "The ID of the user to retrieve the roles for.", required = true) @PathVariable("id") String id) { + public ResponseEntity<Collection<String>> usersIdRolesGet(@ApiParam(value = "The ID of the user to retrieve the roles for.", required = true) @PathVariable("id") final String id) { HttpStatus status = isPermitted(id); if (status != null) { return new ResponseEntity<>(status); } - try { - final UserI user = Users.getUser(id); - if (user == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - Collection<String> roles = _roleHolder.getRoles(user); - return new ResponseEntity<>(roles, HttpStatus.OK); - } catch (UserInitException e) { - _log.error("An error occurred initializing the user " + id, e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } catch (UserNotFoundException e) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } + final Collection<String> roles = getUserRoles(id); + return roles != null ? new ResponseEntity<>(roles, HttpStatus.OK) : new ResponseEntity<Collection<String>>(HttpStatus.FORBIDDEN); } @ApiOperation(value = "Adds a role to a user.", notes = "Assigns a new role to a user.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "User role successfully added."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this user."), @ApiResponse(code = 404, message = "User not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/profiles/{id}/addrole/{role}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/profiles/{id}/roles/{role}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) public ResponseEntity<Boolean> usersIdAddRole(@ApiParam(value = "ID of the user to add a role to", required = true) @PathVariable("id") String id, @ApiParam(value = "The user's new role.", required = true) @PathVariable("role") String role) { HttpStatus status = isPermitted(id); if (status != null) { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } try { - _roleHolder.addRole(getSessionUser(), user, role); + getRoleHolder().addRole(getSessionUser(), user, role); return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { _log.error("Error occurred adding role " + role + " to user " + user.getLogin() + "."); @@ -302,22 +303,21 @@ public class UsersApi extends AbstractXapiRestController { } } - @ApiOperation(value = "Remove a user's role.", notes = "Removes a user's role.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "User role successfully removed."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this user."), @ApiResponse(code = 404, message = "User not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/profiles/{id}/removerole/{role}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + @RequestMapping(value = {"/profiles/{id}/roles/{role}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.DELETE}) public ResponseEntity<Boolean> usersIdRemoveRole(@ApiParam(value = "ID of the user to delete a role from", required = true) @PathVariable("id") String id, @ApiParam(value = "The user role to delete.", required = true) @PathVariable("role") String role) { HttpStatus status = isPermitted(id); if (status != null) { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } try { - _roleHolder.deleteRole(getSessionUser(), user, role); + getRoleHolder().deleteRole(getSessionUser(), user, role); return new ResponseEntity<>(HttpStatus.OK); } catch (Exception e) { _log.error("Error occurred removing role " + role + " from user " + user.getLogin() + "."); @@ -340,7 +340,7 @@ public class UsersApi extends AbstractXapiRestController { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -356,14 +356,14 @@ public class UsersApi extends AbstractXapiRestController { @ApiOperation(value = "Adds a user to a group.", notes = "Assigns user to a group.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "User successfully added to group."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this user."), @ApiResponse(code = 404, message = "User not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/profiles/{id}/addgroup/{group}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) - public ResponseEntity<Boolean> usersIdAddGroup(@ApiParam(value = "ID of the user to add to a group", required = true) @PathVariable("id") String id, @ApiParam(value = "The user's new group.", required = true) @PathVariable("group") String group) { + @RequestMapping(value = {"/profiles/{id}/groups/{group}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) + public ResponseEntity<Boolean> usersIdAddGroup(@ApiParam(value = "ID of the user to add to a group", required = true) @PathVariable("id") String id, @ApiParam(value = "The user's new group.", required = true) @PathVariable("group") final String group) { HttpStatus status = isPermitted(id); if (status != null) { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -382,17 +382,16 @@ public class UsersApi extends AbstractXapiRestController { } } - @ApiOperation(value = "Removes a user from a group.", notes = "Removes a user from a group.", response = Boolean.class) @ApiResponses({@ApiResponse(code = 200, message = "User's group successfully removed."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to enable or disable this user."), @ApiResponse(code = 404, message = "User not found."), @ApiResponse(code = 500, message = "Unexpected error")}) - @RequestMapping(value = {"/profiles/{id}/removegroup/{group}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.PUT}) - public ResponseEntity<Boolean> usersIdRemoveGroup(@ApiParam(value = "ID of the user to remove from group", required = true) @PathVariable("id") String id, @ApiParam(value = "The group to remove the user from.", required = true) @PathVariable("group") String group) { + @RequestMapping(value = {"/profiles/{id}/groups/{group}"}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.DELETE}) + public ResponseEntity<Boolean> usersIdRemoveGroup(@ApiParam(value = "ID of the user to remove from group", required = true) @PathVariable("id") final String id, @ApiParam(value = "The group to remove the user from.", required = true) @PathVariable("group") final String group) { HttpStatus status = isPermitted(id); if (status != null) { return new ResponseEntity<>(status); } try { - final UserI user = Users.getUser(id); + final UserI user = getUserManagementService().getUser(id); if (user == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -425,10 +424,7 @@ public class UsersApi extends AbstractXapiRestController { public static String VerifiedEmail = "Verified User Email"; } - @Autowired - @Lazy - private SiteConfigPreferences _preferences; + private static final Logger _log = LoggerFactory.getLogger(UsersApi.class); - @Autowired - private RoleHolder _roleHolder; + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java index fc87250dc16ca6e9219b38b3529ae256e3a211ad..01aaf58904c7f581d42e1284ceabdc408d85c6f4 100644 --- a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java @@ -1,8 +1,8 @@ package org.nrg.xnat.configuration; import org.nrg.config.exceptions.SiteConfigurationException; -import org.nrg.framework.services.ContextService; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.config.services.ConfigService; +import org.nrg.framework.services.NrgEventService; import org.nrg.xdat.preferences.NotificationsPreferences; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.security.HistoricPasswordValidator; @@ -12,6 +12,7 @@ import org.nrg.xdat.security.XDATUserMgmtServiceImpl; import org.nrg.xdat.security.services.UserManagementServiceI; import org.nrg.xdat.services.ThemeService; import org.nrg.xdat.services.impl.ThemeServiceImpl; +import org.nrg.xnat.initialization.InitializingTask; import org.nrg.xnat.initialization.InitializingTasksExecutor; import org.nrg.xnat.restlet.XnatRestletExtensions; import org.nrg.xnat.restlet.actions.importer.ImporterHandlerPackages; @@ -19,7 +20,6 @@ import org.nrg.xnat.services.PETTracerUtils; import org.nrg.xnat.utils.XnatUserProvider; import org.springframework.context.annotation.*; -import javax.inject.Inject; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -41,29 +41,23 @@ public class ApplicationConfig { } @Bean - @Primary - public ContextService contextService() { - return ContextService.getInstance(); + public InitializingTasksExecutor initializingTasksExecutor(final List<InitializingTask> tasks) { + return new InitializingTasksExecutor(tasks); } @Bean - public InitializingTasksExecutor initializingTasksExecutor() { - return new InitializingTasksExecutor(); + public SiteConfigPreferences siteConfigPreferences(final NrgEventService service) { + return new SiteConfigPreferences(service); } @Bean - public SiteConfigPreferences siteConfigPreferences() { - return new SiteConfigPreferences(); + public NotificationsPreferences notificationsPreferences(final NrgEventService service) { + return new NotificationsPreferences(service); } @Bean - public NotificationsPreferences notificationsPreferences() { - return new NotificationsPreferences(); - } - - @Bean - public PETTracerUtils petTracerUtils() throws Exception { - return new PETTracerUtils(); + public PETTracerUtils petTracerUtils(final ConfigService configService) throws Exception { + return new PETTracerUtils(configService); } @Bean @@ -94,9 +88,13 @@ public class ApplicationConfig { } @Bean - public XnatUserProvider receivedFileUserProvider() throws SiteConfigurationException { - final String receivedFileUser = _preferences.getReceivedFileUser(); - return new XnatUserProvider(receivedFileUser); + public XnatUserProvider primaryAdminUserProvider(final SiteConfigPreferences preferences) throws SiteConfigurationException { + return new XnatUserProvider(preferences.getPrimaryAdminUsername()); + } + + @Bean + public XnatUserProvider receivedFileUserProvider(final SiteConfigPreferences preferences) throws SiteConfigurationException { + return new XnatUserProvider(preferences.getReceivedFileUser()); } @Bean @@ -108,7 +106,4 @@ public class ApplicationConfig { public ImporterHandlerPackages importerHandlerPackages() { return new ImporterHandlerPackages(new HashSet<>(Arrays.asList(new String[] {"org.nrg.xnat.restlet.actions", "org.nrg.xnat.archive"}))); } - - @Inject - private InitializerSiteConfiguration _preferences; } diff --git a/src/main/java/org/nrg/xnat/configuration/DicomImportConfig.java b/src/main/java/org/nrg/xnat/configuration/DicomImportConfig.java index 3485070631c2ba8d98472da424807b975656bdb6..1a8aa273d59b8b51bdd17558a83b21dcc09c508c 100644 --- a/src/main/java/org/nrg/xnat/configuration/DicomImportConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/DicomImportConfig.java @@ -21,9 +21,9 @@ import java.util.List; @ComponentScan("org.nrg.dcm.preferences") public class DicomImportConfig { @Bean - public DicomObjectIdentifier<XnatProjectdata> dicomObjectIdentifier(final XnatUserProvider provider) { + public DicomObjectIdentifier<XnatProjectdata> dicomObjectIdentifier(final XnatUserProvider receivedFileUserProvider) { final ClassicDicomObjectIdentifier identifier = new ClassicDicomObjectIdentifier(); - identifier.setUserProvider(provider); + identifier.setUserProvider(receivedFileUserProvider); return identifier; } diff --git a/src/main/java/org/nrg/xnat/configuration/FeaturesConfig.java b/src/main/java/org/nrg/xnat/configuration/FeaturesConfig.java index 8731059b15e79897648a91e0c0fa52c3f4ee8363..913d610b05cc91db69e2b7e46a53a8de3e60314c 100644 --- a/src/main/java/org/nrg/xnat/configuration/FeaturesConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/FeaturesConfig.java @@ -2,15 +2,13 @@ package org.nrg.xnat.configuration; import org.apache.commons.lang3.StringUtils; import org.nrg.config.exceptions.SiteConfigurationException; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.security.services.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import javax.inject.Inject; - import static org.nrg.xdat.security.services.FeatureRepositoryServiceI.DEFAULT_FEATURE_REPO_SERVICE; import static org.nrg.xdat.security.services.FeatureServiceI.DEFAULT_FEATURE_SERVICE; import static org.nrg.xdat.security.services.RoleRepositoryServiceI.DEFAULT_ROLE_REPO_SERVICE; @@ -20,8 +18,8 @@ import static org.nrg.xdat.security.services.RoleServiceI.DEFAULT_ROLE_SERVICE; public class FeaturesConfig { @Bean - public FeatureServiceI featureService() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { - final String serviceImpl = StringUtils.defaultIfBlank(_preferences.getFeatureService(), DEFAULT_FEATURE_SERVICE); + public FeatureServiceI featureService(final SiteConfigPreferences preferences) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { + final String serviceImpl = StringUtils.defaultIfBlank(preferences.getFeatureService(), DEFAULT_FEATURE_SERVICE); if (_log.isDebugEnabled()) { _log.debug("Creating feature service with implementing class " + serviceImpl); } @@ -29,8 +27,8 @@ public class FeaturesConfig { } @Bean - public FeatureRepositoryServiceI featureRepositoryService() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { - final String serviceImpl = StringUtils.defaultIfBlank(_preferences.getFeatureRepositoryService(), DEFAULT_FEATURE_REPO_SERVICE); + public FeatureRepositoryServiceI featureRepositoryService(final SiteConfigPreferences preferences) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { + final String serviceImpl = StringUtils.defaultIfBlank(preferences.getFeatureRepositoryService(), DEFAULT_FEATURE_REPO_SERVICE); if (_log.isDebugEnabled()) { _log.debug("Creating feature repository service with implementing class " + serviceImpl); } @@ -38,8 +36,8 @@ public class FeaturesConfig { } @Bean - public RoleHolder roleService() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { - final String serviceImpl = StringUtils.defaultIfBlank(_preferences.getRoleService(), DEFAULT_ROLE_SERVICE); + public RoleHolder roleService(final SiteConfigPreferences preferences) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { + final String serviceImpl = StringUtils.defaultIfBlank(preferences.getRoleService(), DEFAULT_ROLE_SERVICE); if (_log.isDebugEnabled()) { _log.debug("Creating role service with implementing class " + serviceImpl); } @@ -47,8 +45,8 @@ public class FeaturesConfig { } @Bean - public RoleRepositoryHolder roleRepositoryService() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { - final String serviceImpl = StringUtils.defaultIfBlank(_preferences.getRoleRepositoryService(), DEFAULT_ROLE_REPO_SERVICE); + public RoleRepositoryHolder roleRepositoryService(final SiteConfigPreferences preferences) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { + final String serviceImpl = StringUtils.defaultIfBlank(preferences.getRoleRepositoryService(), DEFAULT_ROLE_REPO_SERVICE); if (_log.isDebugEnabled()) { _log.debug("Creating role repository service with implementing class " + serviceImpl); } @@ -56,7 +54,4 @@ public class FeaturesConfig { } private static final Logger _log = LoggerFactory.getLogger(FeaturesConfig.class); - - @Inject - private InitializerSiteConfiguration _preferences; } diff --git a/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java b/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java index 888f8c18e9925d2ee848c0a8484043abf6e5b660..57ba799583e9d3814908d0c5c9ee1da4cf729fd5 100644 --- a/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/NotificationsConfig.java @@ -3,16 +3,17 @@ package org.nrg.xnat.configuration; import org.apache.commons.lang3.StringUtils; import org.nrg.config.exceptions.SiteConfigurationException; import org.nrg.framework.orm.hibernate.HibernateEntityPackageList; +import org.nrg.mail.services.MailService; import org.nrg.notify.entities.ChannelRendererProvider; import org.nrg.notify.renderers.ChannelRenderer; import org.nrg.notify.renderers.NrgMailChannelRenderer; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.NotificationsPreferences; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.mail.javamail.JavaMailSenderImpl; -import javax.inject.Inject; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -24,8 +25,8 @@ import java.util.Properties; public class NotificationsConfig { @Bean - public JavaMailSenderImpl mailSender() throws IOException, SiteConfigurationException { - final Map<String, String> smtp = _preferences.getSmtpServer(); + public JavaMailSenderImpl mailSender(final NotificationsPreferences preferences) throws IOException, SiteConfigurationException { + final Map<String, String> smtp = preferences.getSmtpServer(); final JavaMailSenderImpl sender = new JavaMailSenderImpl(); if(smtp!=null) { sender.setHost(StringUtils.defaultIfBlank(smtp.remove("host"), "localhost")); @@ -50,28 +51,20 @@ public class NotificationsConfig { } @Bean - public ChannelRenderer mailChannelRenderer() throws SiteConfigurationException { - final NrgMailChannelRenderer renderer = new NrgMailChannelRenderer(); - renderer.setFromAddress(_preferences.getAdminEmail()); - renderer.setSubjectPrefix(_preferences.getEmailPrefix()); + public NrgMailChannelRenderer mailChannelRenderer(final SiteConfigPreferences siteConfigPreferences, final NotificationsPreferences notificationsPreferences, final MailService mailService) throws SiteConfigurationException { + final NrgMailChannelRenderer renderer = new NrgMailChannelRenderer(mailService); + renderer.setFromAddress(siteConfigPreferences.getAdminEmail()); + renderer.setSubjectPrefix(notificationsPreferences.getEmailPrefix()); return renderer; } @Bean - public Map<String, ChannelRenderer> renderers() throws SiteConfigurationException { - final Map<String, ChannelRenderer> renderers = new HashMap<>(); - renderers.put("htmlMail", mailChannelRenderer()); - renderers.put("textMail", mailChannelRenderer()); - return renderers; - } - - @Bean - public ChannelRendererProvider rendererProvider() throws SiteConfigurationException { + public ChannelRendererProvider rendererProvider(final NrgMailChannelRenderer renderer) throws SiteConfigurationException { final ChannelRendererProvider provider = new ChannelRendererProvider(); - provider.setRenderers(renderers()); + final Map<String, ChannelRenderer> renderers = new HashMap<>(); + renderers.put("htmlMail", renderer); + renderers.put("textMail", renderer); + provider.setRenderers(renderers); return provider; } - - @Inject - private InitializerSiteConfiguration _preferences; } diff --git a/src/main/java/org/nrg/xnat/configuration/OrmConfig.java b/src/main/java/org/nrg/xnat/configuration/OrmConfig.java index 6a43ca8d6f3f5221dff2a91f1e8d3871b8ad83ac..a8025ac329bdfb62df785abb1e6410eb0b349f4d 100644 --- a/src/main/java/org/nrg/xnat/configuration/OrmConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/OrmConfig.java @@ -1,15 +1,12 @@ package org.nrg.xnat.configuration; -import com.google.common.base.Joiner; -import org.apache.commons.io.IOUtils; import org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cfg.ImprovedNamingStrategy; import org.nrg.framework.exceptions.NrgServiceError; import org.nrg.framework.exceptions.NrgServiceException; +import org.nrg.framework.orm.hibernate.AggregatedAnnotationSessionFactoryBean; import org.nrg.framework.orm.hibernate.PrefixedTableNamingStrategy; -import org.nrg.framework.processors.XnatPluginBean; -import org.nrg.framework.utilities.BasicXnatResourceLocator; import org.nrg.framework.utilities.Beans; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,19 +14,14 @@ import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; -import org.springframework.core.io.Resource; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import javax.inject.Inject; import javax.sql.DataSource; import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; import java.util.Properties; -import java.util.Set; @Configuration @EnableTransactionManagement(proxyTargetClass = true) @@ -40,9 +32,9 @@ public class OrmConfig { } @Bean - public PropertiesFactoryBean hibernateProperties() { + public PropertiesFactoryBean hibernateProperties(final Environment environment) { final PropertiesFactoryBean bean = new PropertiesFactoryBean(); - final Properties properties = Beans.getNamespacedProperties(_environment, "hibernate", false); + final Properties properties = Beans.getNamespacedProperties(environment, "hibernate", false); if (properties.size() == 0) { if (_log.isDebugEnabled()) { final StringBuilder message = new StringBuilder("No Hibernate properties specified, using default properties:\n"); @@ -58,30 +50,21 @@ public class OrmConfig { } @Bean - public RegionFactory regionFactory() throws NrgServiceException { + public RegionFactory regionFactory(final Environment environment) throws NrgServiceException { try { - return new SingletonEhCacheRegionFactory(hibernateProperties().getObject()); + return new SingletonEhCacheRegionFactory(hibernateProperties(environment).getObject()); } catch (IOException e) { throw new NrgServiceException(NrgServiceError.Unknown, "An error occurred trying to retrieve the Hibernate properties", e); } } @Bean - public LocalSessionFactoryBean sessionFactory(final DataSource dataSource) throws NrgServiceException { + public LocalSessionFactoryBean sessionFactory(final Environment environment, final DataSource dataSource) throws NrgServiceException { try { - final LocalSessionFactoryBean bean = new LocalSessionFactoryBean(); - final String[] packages = getXnatEntityPackages(); - if (_log.isDebugEnabled()) { - final StringBuilder message = new StringBuilder("The following packages will be scanned for persistent entities:\n"); - for (final String packageName : packages) { - message.append(" * ").append(packageName).append("\n"); - } - _log.debug(message.toString()); - } - bean.setPackagesToScan(packages); + final AggregatedAnnotationSessionFactoryBean bean = new AggregatedAnnotationSessionFactoryBean(); bean.setDataSource(dataSource); - bean.setCacheRegionFactory(regionFactory()); - bean.setHibernateProperties(hibernateProperties().getObject()); + bean.setCacheRegionFactory(regionFactory(environment)); + bean.setHibernateProperties(hibernateProperties(environment).getObject()); bean.setNamingStrategy(namingStrategy()); return bean; } catch (IOException e) { @@ -90,31 +73,8 @@ public class OrmConfig { } @Bean - public PlatformTransactionManager transactionManager(final DataSource dataSource) throws NrgServiceException { - return new HibernateTransactionManager(sessionFactory(dataSource).getObject()); - } - - private static String[] getXnatEntityPackages() throws IOException { - final Set<String> packages = new HashSet<>(); - for (final Resource resource : BasicXnatResourceLocator.getResources("classpath*:META-INF/xnat/entities/**/*-entity-packages.txt")) { - if (_log.isDebugEnabled()) { - _log.debug("Processing entity packages from the resource: {}", resource.getFilename()); - } - try (final InputStream input = resource.getInputStream()) { - packages.addAll(IOUtils.readLines(input, "UTF-8")); - } - } - try { - for (final XnatPluginBean plugin : XnatPluginBean.findAllXnatPluginBeans()) { - if (_log.isDebugEnabled()) { - _log.debug("Processing entity packages from plugin {}: {}", plugin.getId(), Joiner.on(", ").join(plugin.getEntityPackages())); - } - packages.addAll(plugin.getEntityPackages()); - } - } catch (IOException e) { - throw new RuntimeException("An error occurred trying to locate XNAT plugin definitions."); - } - return packages.toArray(new String[packages.size()]); + public PlatformTransactionManager transactionManager(final Environment environment, final DataSource dataSource) throws NrgServiceException { + return new HibernateTransactionManager(sessionFactory(environment, dataSource).getObject()); } private static final Properties DEFAULT_HIBERNATE_PROPERTIES = new Properties() {{ @@ -126,7 +86,4 @@ public class OrmConfig { }}; private static final Logger _log = LoggerFactory.getLogger(OrmConfig.class); - - @Inject - private Environment _environment; } diff --git a/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java b/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java index 7154bfe7925b461befc0327ccce506a77180be0f..74329d3464588247db1b896382f394f789b38663 100644 --- a/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/PreferencesConfig.java @@ -6,21 +6,24 @@ import org.nrg.config.services.SiteConfigurationService; import org.nrg.config.services.UserConfigurationService; import org.nrg.config.services.impl.DefaultConfigService; import org.nrg.config.services.impl.DefaultUserConfigurationService; -import org.nrg.prefs.configuration.NrgPrefsServiceConfiguration; +import org.nrg.prefs.configuration.NrgPrefsConfiguration; +import org.nrg.prefs.services.NrgPreferenceService; import org.nrg.prefs.services.PreferenceService; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.resolvers.XnatPreferenceEntityResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; -import javax.inject.Inject; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; @Configuration @ComponentScan("org.nrg.config.daos") -@Import(NrgPrefsServiceConfiguration.class) +@Import(NrgPrefsConfiguration.class) public class PreferencesConfig { @Bean @@ -30,13 +33,26 @@ public class PreferencesConfig { @Bean public UserConfigurationService userConfigurationService() { - return new DefaultUserConfigurationService(); + return new DefaultUserConfigurationService(configService()); } @Bean - public SiteConfigurationService siteConfigurationService() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { - // TODO: Add direct prefs call or JDBC call to get the site configuration setting from the database. - final Class<? extends SiteConfigurationService> clazz = Class.forName(_preferences.getSiteConfigurationService()).asSubclass(SiteConfigurationService.class); + public SiteConfigurationService siteConfigurationService(final SiteConfigPreferences preferences, final NrgPreferenceService nrgPreferenceService, final ConfigService configService, final Environment environment) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SiteConfigurationException { + final Class<? extends SiteConfigurationService> clazz = Class.forName(preferences.getSiteConfigurationService()).asSubclass(SiteConfigurationService.class); + try { + @SuppressWarnings("unchecked") + final Constructor<? extends SiteConfigurationService> constructor = clazz.getConstructor(NrgPreferenceService.class, Environment.class); + return constructor.newInstance(nrgPreferenceService, environment); + } catch (NoSuchMethodException | InvocationTargetException ignored) { + // No worries, it just doesn't have that constructor. + } + try { + @SuppressWarnings("unchecked") + final Constructor<? extends SiteConfigurationService> constructor = clazz.getConstructor(ConfigService.class, Environment.class); + return constructor.newInstance(configService, environment); + } catch (NoSuchMethodException | InvocationTargetException ignored) { + // No worries, it just doesn't have that constructor. + } return clazz.newInstance(); } @@ -44,7 +60,4 @@ public class PreferencesConfig { public XnatPreferenceEntityResolver defaultResolver(final PreferenceService preferenceService) throws IOException { return new XnatPreferenceEntityResolver(preferenceService); } - - @Inject - private InitializerSiteConfiguration _preferences; } diff --git a/src/main/java/org/nrg/xnat/configuration/ReactorConfig.java b/src/main/java/org/nrg/xnat/configuration/ReactorConfig.java index d831d26cc2c0ac18405ca4c72617f6f4e5ae5750..13f555e7f76d825d7d1b446899c8b3d2ab1d1273 100755 --- a/src/main/java/org/nrg/xnat/configuration/ReactorConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/ReactorConfig.java @@ -17,8 +17,8 @@ import java.util.HashSet; @Configuration public class ReactorConfig { @Bean - public NrgEventService xftEventService() { - return new NrgEventService(); + public NrgEventService eventService(final EventBus eventBus) { + return new NrgEventService(eventBus); } @Bean diff --git a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java index 991f1ab6f9fc1ede61981b6dc8dbce60609fa3cc..da3c22618e1b3f76d6d52b297e01ca16a516bcf1 100644 --- a/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/SchedulerConfig.java @@ -1,17 +1,14 @@ package org.nrg.xnat.configuration; -import org.nrg.config.exceptions.SiteConfigurationException; import org.nrg.framework.services.NrgEventService; import org.nrg.mail.services.EmailRequestLogService; -import org.nrg.xdat.XDAT; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.NotificationsPreferences; import org.nrg.xdat.preferences.PreferenceEvent; -import org.nrg.xnat.helpers.prearchive.SessionXMLRebuilder; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.ResetEmailRequests; -import org.nrg.xnat.utils.XnatUserProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.jms.core.JmsTemplate; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; @@ -19,15 +16,14 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.config.TriggerTask; import org.springframework.scheduling.support.PeriodicTrigger; -import javax.inject.Inject; import java.util.List; @Configuration @EnableScheduling public class SchedulerConfig implements SchedulingConfigurer { @Bean - public TriggerTask resetEmailRequests() { - return new TriggerTask(new ResetEmailRequests(_emailRequestLogService), new PeriodicTrigger(900000)); + public TriggerTask resetEmailRequests(final EmailRequestLogService service) { + return new TriggerTask(new ResetEmailRequests(service), new PeriodicTrigger(900000)); } @Bean(destroyMethod = "shutdown") @@ -37,43 +33,51 @@ public class SchedulerConfig implements SchedulingConfigurer { return scheduler; } - @Override - public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) { - taskRegistrar.setScheduler(taskScheduler()); - _eventService.triggerEvent(new PreferenceEvent("sessionXmlRebuilderRepeat", String.valueOf(XDAT.getSiteConfigPreferences().getSessionXmlRebuilderRepeat()))); - _eventService.triggerEvent(new PreferenceEvent("aliasTokenTimeout", String.valueOf(XDAT.getSiteConfigPreferences().getAliasTokenTimeout()))); - _eventService.triggerEvent(new PreferenceEvent("inactivityBeforeLockout", String.valueOf(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout()))); - _eventService.triggerEvent(new PreferenceEvent("maxFailedLoginsLockoutDuration", String.valueOf(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()))); - _eventService.triggerEvent(new PreferenceEvent("emailPrefix", String.valueOf(XDAT.getNotificationsPreferences().getEmailPrefix()))); - _eventService.triggerEvent(new PreferenceEvent("host", String.valueOf(XDAT.getNotificationsPreferences().getHostname()))); - _eventService.triggerEvent(new PreferenceEvent("requireLogin", String.valueOf(XDAT.getSiteConfigPreferences().getRequireLogin()))); - _eventService.triggerEvent(new PreferenceEvent("security.channel", String.valueOf(XDAT.getSiteConfigPreferences().getSecurityChannel()))); - _eventService.triggerEvent(new PreferenceEvent("passwordExpirationType", String.valueOf(XDAT.getSiteConfigPreferences().getPasswordExpirationType()))); - _eventService.triggerEvent(new PreferenceEvent("archivePath", String.valueOf(XDAT.getSiteConfigPreferences().getArchivePath()))); - _eventService.triggerEvent(new PreferenceEvent("security.services.role.default", String.valueOf(XDAT.getSiteConfigPreferences().getRoleService()))); - _eventService.triggerEvent(new PreferenceEvent("checksums", String.valueOf(XDAT.getSiteConfigPreferences().getChecksums()))); - _eventService.triggerEvent(new PreferenceEvent("sitewidePetTracers", String.valueOf(XDAT.getSiteConfigPreferences().getSitewidePetTracers()))); - for (final TriggerTask triggerTask : _triggerTasks) { - taskRegistrar.addTriggerTask(triggerTask); - } + @Autowired + public void setNrgEventService(final NrgEventService service) { + _service = service; } - @Inject - private EmailRequestLogService _emailRequestLogService; + @Autowired + public void setSiteConfigPreferences(final SiteConfigPreferences siteConfigPreferences) { + _siteConfigPreferences = siteConfigPreferences; + } - @Inject - private XnatUserProvider _provider; + @Autowired + public void setNotificationsPreferences(final NotificationsPreferences notificationsPreferences) { + _notificationsPreferences = notificationsPreferences; + } - @Inject - private JmsTemplate _jmsTemplate; + @Autowired + public void setTriggerTasks(final List<TriggerTask> tasks) { + _tasks = tasks; + } - @Inject - private InitializerSiteConfiguration _preferences; + @Override + public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(taskScheduler()); + + _service.triggerEvent(new PreferenceEvent("sessionXmlRebuilderRepeat", String.valueOf(_siteConfigPreferences.getSessionXmlRebuilderRepeat()))); + _service.triggerEvent(new PreferenceEvent("aliasTokenTimeout", String.valueOf(_siteConfigPreferences.getAliasTokenTimeout()))); + _service.triggerEvent(new PreferenceEvent("inactivityBeforeLockout", String.valueOf(_siteConfigPreferences.getInactivityBeforeLockout()))); + _service.triggerEvent(new PreferenceEvent("maxFailedLoginsLockoutDuration", String.valueOf(_siteConfigPreferences.getMaxFailedLoginsLockoutDuration()))); + _service.triggerEvent(new PreferenceEvent("emailPrefix", String.valueOf(_notificationsPreferences.getEmailPrefix()))); + _service.triggerEvent(new PreferenceEvent("host", String.valueOf(_notificationsPreferences.getHostname()))); + _service.triggerEvent(new PreferenceEvent("requireLogin", String.valueOf(_siteConfigPreferences.getRequireLogin()))); + _service.triggerEvent(new PreferenceEvent("security.channel", String.valueOf(_siteConfigPreferences.getSecurityChannel()))); + _service.triggerEvent(new PreferenceEvent("passwordExpirationType", String.valueOf(_siteConfigPreferences.getPasswordExpirationType()))); + _service.triggerEvent(new PreferenceEvent("archivePath", String.valueOf(_siteConfigPreferences.getArchivePath()))); + _service.triggerEvent(new PreferenceEvent("security.services.role.default", String.valueOf(_siteConfigPreferences.getRoleService()))); + _service.triggerEvent(new PreferenceEvent("checksums", String.valueOf(_siteConfigPreferences.getChecksums()))); + _service.triggerEvent(new PreferenceEvent("sitewidePetTracers", String.valueOf(_siteConfigPreferences.getSitewidePetTracers()))); - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Inject - private List<TriggerTask> _triggerTasks; + for (final TriggerTask triggerTask : _tasks) { + taskRegistrar.addTriggerTask(triggerTask); + } + } - @Inject - private NrgEventService _eventService; + private SiteConfigPreferences _siteConfigPreferences; + private NotificationsPreferences _notificationsPreferences; + private List<TriggerTask> _tasks; + private NrgEventService _service; } \ No newline at end of file diff --git a/src/main/java/org/nrg/xnat/configuration/WebConfig.java b/src/main/java/org/nrg/xnat/configuration/WebConfig.java index 6780f6787be29cf1daccd58c4de811d94dedd305..4bc2cdc48227cc9ffa88c9408ad4fb4d9959ecc0 100644 --- a/src/main/java/org/nrg/xnat/configuration/WebConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/WebConfig.java @@ -60,7 +60,7 @@ public class WebConfig extends WebMvcConfigurerAdapter { @Bean public MessageSource messageSource() { return new ResourceBundleMessageSource() {{ - setBasename("messages"); + setBasename("org/nrg/xnat/messages/system.properties"); }}; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/AutoRunEmailHandler.java b/src/main/java/org/nrg/xnat/event/listeners/AutoRunEmailHandler.java index 838f5a495360a89161983cfb674a300f59a02ec1..08f84f6ee7eefe17af30e49e3094baa1211d660f 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/AutoRunEmailHandler.java +++ b/src/main/java/org/nrg/xnat/event/listeners/AutoRunEmailHandler.java @@ -2,7 +2,7 @@ package org.nrg.xnat.event.listeners; import com.google.common.collect.Maps; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.NotificationsPreferences; import reactor.bus.Event; import reactor.bus.EventBus; import reactor.fn.Consumer; @@ -24,50 +24,55 @@ import javax.inject.Inject; @Service public class AutoRunEmailHandler extends PipelineEmailHandlerAbst implements Consumer<Event<WorkflowStatusEvent>> { - /** The pipeline name. */ - private final String PIPELINE_NAME = "xnat_tools/AutoRun.xml"; - - /** The pipeline name pretty. */ - private final String PIPELINE_NAME_PRETTY = "AutoRun"; - - /** - * Instantiates a new auto run email handler. - * - * @param eventBus the event bus - */ - @Inject public AutoRunEmailHandler( EventBus eventBus ){ - eventBus.on(R(WorkflowStatusEvent.class.getName() + "[.](" - + PersistentWorkflowUtils.COMPLETE + "|" + PersistentWorkflowUtils.FAILED + ")"), this); - } - - /* (non-Javadoc) - * @see reactor.fn.Consumer#accept(java.lang.Object) - */ - @Override - public void accept(Event<WorkflowStatusEvent> event) { - - final WorkflowStatusEvent wfsEvent = event.getData(); - if (wfsEvent.getWorkflow() instanceof WrkWorkflowdata) { - handleEvent(wfsEvent); - } - - } + /** + * Instantiates a new auto run email handler. + * + * @param eventBus the event bus + * @param preferences The notifications preferences object. + */ + @Inject + public AutoRunEmailHandler(EventBus eventBus, final NotificationsPreferences preferences) { + _preferences = preferences; + eventBus.on(R(WorkflowStatusEvent.class.getName() + "[.](" + PersistentWorkflowUtils.COMPLETE + "|" + PersistentWorkflowUtils.FAILED + ")"), this); + } + + /* (non-Javadoc) + * @see reactor.fn.Consumer#accept(java.lang.Object) + */ + @Override + public void accept(Event<WorkflowStatusEvent> event) { + + final WorkflowStatusEvent wfsEvent = event.getData(); + if (wfsEvent.getWorkflow() instanceof WrkWorkflowdata) { + handleEvent(wfsEvent); + } + + } /* (non-Javadoc) * @see org.nrg.xnat.event.listeners.WorkflowStatusEventHandlerAbst#handleEvent(org.nrg.xft.event.WorkflowStatusEvent) */ public void handleEvent(WorkflowStatusEvent e) { - Map<String,Object> params = Maps.newHashMap(); - params.put("pipelineName",PIPELINE_NAME_PRETTY); - params.put("contactEmail", XDAT.getNotificationsPreferences().getHelpContactInfo()); + Map<String, Object> params = Maps.newHashMap(); + /* + The pipeline name pretty. + */ + final String PIPELINE_NAME_PRETTY = "AutoRun"; + params.put("pipelineName", PIPELINE_NAME_PRETTY); + params.put("contactEmail", _preferences.getHelpContactInfo()); if (!(e.getWorkflow() instanceof WrkWorkflowdata)) { - return; + return; } + /* + The pipeline name. + */ + final String PIPELINE_NAME = "xnat_tools/AutoRun.xml"; if (completed(e)) { - standardPipelineEmailImpl(e, (WrkWorkflowdata)e.getWorkflow(), PIPELINE_NAME, "/screens/PipelineEmail_AutoRun_success.vm", " archiving complete", "archival.lst", params); + standardPipelineEmailImpl(e, (WrkWorkflowdata) e.getWorkflow(), PIPELINE_NAME, "/screens/PipelineEmail_AutoRun_success.vm", " archiving complete", "archival.lst", params); } else if (failed(e)) { - standardPipelineEmailImpl(e, (WrkWorkflowdata)e.getWorkflow(), PIPELINE_NAME, DEFAULT_TEMPLATE_FAILURE, DEFAULT_SUBJECT_FAILURE, "archival.lst", params); + standardPipelineEmailImpl(e, (WrkWorkflowdata) e.getWorkflow(), PIPELINE_NAME, DEFAULT_TEMPLATE_FAILURE, DEFAULT_SUBJECT_FAILURE, "archival.lst", params); } } + private final NotificationsPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/AutomationCompletionEventListener.java b/src/main/java/org/nrg/xnat/event/listeners/AutomationCompletionEventListener.java index ceb1ba91f75cba086c644f01a0e4d49d3478677f..98f8e587d3afd3811add263c0adbc5ba122b2a07 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/AutomationCompletionEventListener.java +++ b/src/main/java/org/nrg/xnat/event/listeners/AutomationCompletionEventListener.java @@ -1,106 +1,90 @@ package org.nrg.xnat.event.listeners; import com.google.common.collect.Lists; -import reactor.bus.Event; -import reactor.bus.EventBus; -import reactor.fn.Consumer; - import org.nrg.automation.event.entities.AutomationCompletionEvent; -import org.nrg.xdat.XDAT; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import static reactor.bus.selector.Selectors.type; +import reactor.bus.Event; +import reactor.bus.EventBus; +import reactor.fn.Consumer; + +import javax.inject.Inject; import java.util.Iterator; import java.util.List; -import javax.inject.Inject; + +import static reactor.bus.selector.Selectors.type; /** * The Class AutomatedScriptHandler. */ @Service public class AutomationCompletionEventListener implements Consumer<Event<AutomationCompletionEvent>> { - - /** The Constant logger. */ + + /** + * The Constant logger. + */ private static final Logger logger = LoggerFactory.getLogger(AutomationCompletionEventListener.class); - /** The current instance */ - private static AutomationCompletionEventListener _instance; - /** cache of completed events */ - private List<AutomationCompletionEvent> completedCache = Lists.newArrayList(); - /** HOW LONG WILL WE LET OBJECTS STAY IN CACHE? */ - int CACHE_TIME_MILLIS = 60000; - - /** - * Instantiates a new automation completion event listener. - * - * @throws Exception the exception - */ - public AutomationCompletionEventListener() throws Exception { - if (_instance != null) { - throw new Exception("The AutomationCompletionEventListener service is already initialized. Try calling getService() instead."); - } - _instance = this; - } - - /** - * Instantiates a new automated script handler. - * - * @param eventBus the event bus - * @throws Exception - */ - @Inject public AutomationCompletionEventListener( EventBus eventBus ) throws Exception{ - this(); - eventBus.on(type(AutomationCompletionEvent.class), this); - } - - public static AutomationCompletionEventListener getService() { - if (_instance == null) { - _instance = XDAT.getContextService().getBean(AutomationCompletionEventListener.class); - } - return _instance; - } - - @Override - public void accept(Event<AutomationCompletionEvent> event) { - cleanUpCache(); - if (logger.isDebugEnabled()) { - logger.debug("Receved event " + event.getId() + " - CURRENT TIME: " + System.currentTimeMillis()); - } - if (event.getData().getEventCompletionTime()==null) { - if (logger.isDebugEnabled()) { - logger.debug("WARNING: AutomationCompletionEvent - eventCompletionTime is null"); - } - } - completedCache.add(event.getData()); - } - - private synchronized void cleanUpCache() { - final Iterator<AutomationCompletionEvent> i = completedCache.iterator(); - final long currentTime = System.currentTimeMillis(); - while (i.hasNext()) { - final AutomationCompletionEvent thisEvent = i.next(); - if (thisEvent.getEventCompletionTime()==null || ((currentTime-thisEvent.getEventCompletionTime())>CACHE_TIME_MILLIS)) { - if (logger.isDebugEnabled()) { - logger.debug("cleanUpCache - removed item " + thisEvent.getId() + " - CURRENT TIME: " + currentTime); - } - i.remove(); - } - } - } + /** + * cache of completed events + */ + private List<AutomationCompletionEvent> completedCache = Lists.newArrayList(); + /** + * HOW LONG WILL WE LET OBJECTS STAY IN CACHE? + */ + int CACHE_TIME_MILLIS = 60000; + + /** + * Instantiates a new automated script handler. + * + * @param eventBus the event bus + */ + @Inject + public AutomationCompletionEventListener(final EventBus eventBus) { + eventBus.on(type(AutomationCompletionEvent.class), this); + } + + @Override + public void accept(Event<AutomationCompletionEvent> event) { + cleanUpCache(); + if (logger.isDebugEnabled()) { + logger.debug("Received event " + event.getId() + " - CURRENT TIME: " + System.currentTimeMillis()); + } + if (event.getData().getEventCompletionTime() == null) { + if (logger.isDebugEnabled()) { + logger.debug("WARNING: AutomationCompletionEvent - eventCompletionTime is null"); + } + } + completedCache.add(event.getData()); + } + + private synchronized void cleanUpCache() { + final Iterator<AutomationCompletionEvent> i = completedCache.iterator(); + final long currentTime = System.currentTimeMillis(); + while (i.hasNext()) { + final AutomationCompletionEvent thisEvent = i.next(); + if (thisEvent.getEventCompletionTime() == null || ((currentTime - thisEvent.getEventCompletionTime()) > CACHE_TIME_MILLIS)) { + if (logger.isDebugEnabled()) { + logger.debug("cleanUpCache - removed item " + thisEvent.getId() + " - CURRENT TIME: " + currentTime); + } + i.remove(); + } + } + } - public synchronized AutomationCompletionEvent getEvent(String id) { - final Iterator<AutomationCompletionEvent> i = completedCache.iterator(); - while (i.hasNext()) { - final AutomationCompletionEvent thisEvent = i.next(); - if (thisEvent.getId().equals(id)) { - i.remove(); - return thisEvent; - } - } - if (logger.isDebugEnabled()) { - logger.debug("getEvent - item not found " + id); - } - return null; - } + public synchronized AutomationCompletionEvent getEvent(String id) { + final Iterator<AutomationCompletionEvent> i = completedCache.iterator(); + while (i.hasNext()) { + final AutomationCompletionEvent thisEvent = i.next(); + if (thisEvent.getId().equals(id)) { + i.remove(); + return thisEvent; + } + } + if (logger.isDebugEnabled()) { + logger.debug("getEvent - item not found " + id); + } + return null; + } } diff --git a/src/main/java/org/nrg/xnat/event/listeners/DicomToNiftiEmailHandler.java b/src/main/java/org/nrg/xnat/event/listeners/DicomToNiftiEmailHandler.java index ed5dbdee71a0dd568c6e00884b08ebfa8e00a85a..d704a327c09651bb3ac488f0a1994a003a721024 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/DicomToNiftiEmailHandler.java +++ b/src/main/java/org/nrg/xnat/event/listeners/DicomToNiftiEmailHandler.java @@ -1,47 +1,32 @@ package org.nrg.xnat.event.listeners; import com.google.common.collect.Maps; - -import org.nrg.xdat.XDAT; -import reactor.bus.Event; -import reactor.bus.EventBus; -import reactor.fn.Consumer; - -import org.apache.log4j.Logger; import org.nrg.xdat.om.WrkWorkflowdata; +import org.nrg.xdat.preferences.NotificationsPreferences; import org.nrg.xft.event.entities.WorkflowStatusEvent; import org.nrg.xft.event.persist.PersistentWorkflowUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import reactor.bus.Event; +import reactor.bus.EventBus; +import reactor.fn.Consumer; -import static reactor.bus.selector.Selectors.R; - +import javax.inject.Inject; import java.util.Map; -import javax.inject.Inject; +import static reactor.bus.selector.Selectors.R; -/** - * Created by flavin on 3/2/15. - */ @Service public class DicomToNiftiEmailHandler extends PipelineEmailHandlerAbst implements Consumer<Event<WorkflowStatusEvent>> { - - /** The Constant logger. */ - final static Logger logger = Logger.getLogger(DicomToNiftiEmailHandler.class); - - /** The pipeline name. */ - private final String PIPELINE_NAME = "mricron/DicomToNifti.xml"; - - /** The pipeline name pretty. */ - private final String PIPELINE_NAME_PRETTY = "DicomToNifti"; - /** * Instantiates a new dicom to nifti email handler. - * - * @param eventBus the event bus + * @param eventBus the event bus + * @param preferences The site configuration preferences. */ - @Inject public DicomToNiftiEmailHandler( EventBus eventBus ){ - eventBus.on(R(WorkflowStatusEvent.class.getName() + "[.](" - + PersistentWorkflowUtils.COMPLETE + "|" + PersistentWorkflowUtils.FAILED + ")"), this); + @Autowired + public DicomToNiftiEmailHandler(EventBus eventBus, final NotificationsPreferences preferences){ + _preferences = preferences; + eventBus.on(R(WorkflowStatusEvent.class.getName() + "[.](" + PersistentWorkflowUtils.COMPLETE + "|" + PersistentWorkflowUtils.FAILED + ")"), this); } /* (non-Javadoc) @@ -49,12 +34,10 @@ public class DicomToNiftiEmailHandler extends PipelineEmailHandlerAbst implement */ @Override public void accept(Event<WorkflowStatusEvent> event) { - final WorkflowStatusEvent wfsEvent = event.getData(); if (wfsEvent.getWorkflow() instanceof WrkWorkflowdata) { handleEvent(wfsEvent); } - } /* (non-Javadoc) @@ -66,12 +49,18 @@ public class DicomToNiftiEmailHandler extends PipelineEmailHandlerAbst implement } WrkWorkflowdata wrk = (WrkWorkflowdata)e.getWorkflow(); Map<String,Object> params = Maps.newHashMap(); - params.put("pipelineName",PIPELINE_NAME_PRETTY); - params.put("contactEmail", XDAT.getNotificationsPreferences().getHelpContactInfo()); - if (completed(e)) { + /* The pipeline name pretty. */ + final String PIPELINE_NAME_PRETTY = "DicomToNifti"; + params.put("pipelineName", PIPELINE_NAME_PRETTY); + params.put("contactEmail", _preferences.getHelpContactInfo()); + /* The pipeline name. */ + final String PIPELINE_NAME = "mricron/DicomToNifti.xml"; + if (completed(e)) { standardPipelineEmailImpl(e, wrk, PIPELINE_NAME, DEFAULT_TEMPLATE_SUCCESS, DEFAULT_SUBJECT_SUCCESS, "processed.lst", params); } else if (failed(e)) { standardPipelineEmailImpl(e, wrk, PIPELINE_NAME, DEFAULT_TEMPLATE_FAILURE, DEFAULT_SUBJECT_FAILURE, "processed.lst", params); } } + + private final NotificationsPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractNotificationsPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractNotificationsPreferenceHandlerMethod.java index 5b2c2547e17b1330bc3c90f1a5e35d18f5b932ef..4fd8de2e31056078d1aa83507aeb654d007b5142 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractNotificationsPreferenceHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractNotificationsPreferenceHandlerMethod.java @@ -4,12 +4,12 @@ import org.nrg.prefs.events.PreferenceHandlerMethod; import org.nrg.xdat.preferences.NotificationsPreferences; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public abstract class AbstractNotificationsPreferenceHandlerMethod implements PreferenceHandlerMethod { @Override public List<String> getToolIds() { - return new ArrayList<String>(Arrays.asList(NotificationsPreferences.NOTIFICATIONS_TOOL_ID)); + return new ArrayList<>(Collections.singletonList(NotificationsPreferences.NOTIFICATIONS_TOOL_ID)); } } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigNotificationsPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigNotificationsPreferenceHandlerMethod.java index f79800eea1813ad931dd43c43e842405eb62e520..588def3a0809f1075c486a5eb468f95e34e26e00 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigNotificationsPreferenceHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigNotificationsPreferenceHandlerMethod.java @@ -11,6 +11,6 @@ import java.util.List; public abstract class AbstractSiteConfigNotificationsPreferenceHandlerMethod implements PreferenceHandlerMethod { @Override public List<String> getToolIds() { - return new ArrayList<String>(Arrays.asList(NotificationsPreferences.NOTIFICATIONS_TOOL_ID, SiteConfigPreferences.SITE_CONFIG_TOOL_ID)); + return new ArrayList<>(Arrays.asList(NotificationsPreferences.NOTIFICATIONS_TOOL_ID, SiteConfigPreferences.SITE_CONFIG_TOOL_ID)); } } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigPreferenceHandlerMethod.java index 31dd51bcf200b611b9dd29210834fc651ef4e669..ca11bc01e0a03d449d98e57f040d27df5e0093ed 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigPreferenceHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AbstractSiteConfigPreferenceHandlerMethod.java @@ -1,16 +1,35 @@ package org.nrg.xnat.event.listeners.methods; import org.nrg.prefs.events.PreferenceHandlerMethod; -import org.nrg.xdat.preferences.NotificationsPreferences; import org.nrg.xdat.preferences.SiteConfigPreferences; +import org.nrg.xft.security.UserI; +import org.nrg.xnat.utils.XnatUserProvider; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public abstract class AbstractSiteConfigPreferenceHandlerMethod implements PreferenceHandlerMethod { + protected AbstractSiteConfigPreferenceHandlerMethod() { + _userProvider = null; + } + + protected AbstractSiteConfigPreferenceHandlerMethod(final XnatUserProvider userProvider) { + _userProvider = userProvider; + } + @Override public List<String> getToolIds() { - return new ArrayList<String>(Arrays.asList(SiteConfigPreferences.SITE_CONFIG_TOOL_ID)); + return new ArrayList<>(Collections.singletonList(SiteConfigPreferences.SITE_CONFIG_TOOL_ID)); } + + protected UserI getAdminUser() { + return _userProvider != null ? _userProvider.get() : null; + } + + protected String getAdminUsername() { + return _userProvider != null ? _userProvider.getLogin() : ""; + } + + private final XnatUserProvider _userProvider; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java index 56669628955fd28850927d1e15a9d81541273ebe..77436980b7b0ac55bdba9116f609622e9f51f997 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AliasTokenPreferenceHandlerMethod.java @@ -1,13 +1,11 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.alias.ClearExpiredAliasTokens; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; @@ -18,6 +16,13 @@ import java.util.concurrent.ScheduledFuture; @Component public class AliasTokenPreferenceHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public AliasTokenPreferenceHandlerMethod(final SiteConfigPreferences preferences, final JdbcTemplate template, final ThreadPoolTaskScheduler scheduler) { + _preferences = preferences; + _template = template; + _scheduler = scheduler; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -44,7 +49,7 @@ public class AliasTokenPreferenceHandlerMethod extends AbstractSiteConfigPrefere future.cancel(false); } _timeouts.clear(); - _timeouts.add(_scheduler.schedule(new ClearExpiredAliasTokens(_template), new CronTrigger(XDAT.getSiteConfigPreferences().getAliasTokenTimeoutSchedule()))); + _timeouts.add(_scheduler.schedule(new ClearExpiredAliasTokens(_template), new CronTrigger(_preferences.getAliasTokenTimeoutSchedule()))); } catch (Exception e1) { _log.error("", e1); } @@ -53,13 +58,8 @@ public class AliasTokenPreferenceHandlerMethod extends AbstractSiteConfigPrefere private static final Logger _log = LoggerFactory.getLogger(AliasTokenPreferenceHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("aliasTokenTimeout", "aliasTokenTimeoutSchedule")); - @Autowired - @Lazy - private JdbcTemplate _template; - + private final SiteConfigPreferences _preferences; + private final JdbcTemplate _template; + private final ThreadPoolTaskScheduler _scheduler; private ArrayList<ScheduledFuture> _timeouts = new ArrayList<>(); - - @Autowired - @Qualifier("taskScheduler") - private ThreadPoolTaskScheduler _scheduler; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/AnonymizationHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/AnonymizationHandlerMethod.java index 1729ff32f4adac7c199c6dc53f534d9263765ef6..eae6aa8fa17ada219465177511fb84e65ff57132 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/AnonymizationHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/AnonymizationHandlerMethod.java @@ -1,12 +1,10 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xdat.security.services.RoleHolder; -import org.nrg.xft.security.UserI; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.helpers.editscript.DicomEdit; import org.nrg.xnat.helpers.merge.AnonUtils; +import org.nrg.xnat.utils.XnatUserProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -19,6 +17,12 @@ import java.util.Map; @Component public class AnonymizationHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public AnonymizationHandlerMethod(final SiteConfigPreferences preferences, final XnatUserProvider primaryAdminUserProvider) { + super(primaryAdminUserProvider); + _preferences = preferences; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -33,42 +37,30 @@ public class AnonymizationHandlerMethod extends AbstractSiteConfigPreferenceHand @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateAnon(); } } - private void updateAnon(){ + private void updateAnon() { try { - AnonUtils.getService().setSiteWideScript(getAdminUser().getLogin(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null), XDAT.getSiteConfigPreferences().getSitewideAnonymizationScript()); - } - catch(Exception e){ - _log.error("Failed to set sitewide anon script.",e); + AnonUtils.getService().setSiteWideScript(getAdminUsername(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null), _preferences.getSitewideAnonymizationScript()); + } catch (Exception e) { + _log.error("Failed to set sitewide anon script.", e); } try { - if (XDAT.getSiteConfigPreferences().getEnableSitewideAnonymizationScript()) { - AnonUtils.getService().enableSiteWide(getAdminUser().getLogin(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null)); + if (_preferences.getEnableSitewideAnonymizationScript()) { + AnonUtils.getService().enableSiteWide(getAdminUsername(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null)); } else { - AnonUtils.getService().disableSiteWide(getAdminUser().getLogin(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null)); + AnonUtils.getService().disableSiteWide(getAdminUsername(), DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null)); } - } - catch(Exception e){ - _log.error("Failed to enable/disable sitewide anon script.",e); + } catch (Exception e) { + _log.error("Failed to enable/disable sitewide anon script.", e); } } private static final Logger _log = LoggerFactory.getLogger(AnonymizationHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("enableSitewideAnonymizationScript", "sitewideAnonymizationScript")); - private UserI getAdminUser() throws Exception { - for (String login : Users.getAllLogins()) { - final UserI user = Users.getUser(login); - if (_roleHolder.isSiteAdmin(user)) { - return user; - } - } - return null; - } - @Autowired - private RoleHolder _roleHolder; + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/ChecksumsHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/ChecksumsHandlerMethod.java index 4e4cd1647e5a62949376aa3ba23482e6bec708fc..ef0141d0d4f33b533e77aafabd339371c7ab2b17 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/ChecksumsHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/ChecksumsHandlerMethod.java @@ -1,19 +1,22 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.utils.CatalogUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @Component public class ChecksumsHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public ChecksumsHandlerMethod(final SiteConfigPreferences preferences) { + _preferences = preferences; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -28,16 +31,16 @@ public class ChecksumsHandlerMethod extends AbstractSiteConfigPreferenceHandlerM @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateChecksums(); } } - private void updateChecksums(){ - CatalogUtils.setChecksumConfiguration(XDAT.getSiteConfigPreferences().getChecksums()); + private void updateChecksums() { + CatalogUtils.setChecksumConfiguration(_preferences.getChecksums()); } - private static final Logger _log = LoggerFactory.getLogger(ChecksumsHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("checksums")); + private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("checksums")); + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/InactivityBeforeLockoutHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/InactivityBeforeLockoutHandlerMethod.java index a4c2eae6d28ad1b72e59fd385a2a6858d79e40fe..df40d25a86d99afd47591858cc7aa520de0d03e4 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/InactivityBeforeLockoutHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/InactivityBeforeLockoutHandlerMethod.java @@ -1,22 +1,25 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.DisableInactiveUsers; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; +import java.sql.SQLException; import java.util.*; import java.util.concurrent.ScheduledFuture; @Component public class InactivityBeforeLockoutHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public InactivityBeforeLockoutHandlerMethod(final SiteConfigPreferences preferences, final ThreadPoolTaskScheduler scheduler) { + _preferences = preferences; + _scheduler = scheduler; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -31,33 +34,28 @@ public class InactivityBeforeLockoutHandlerMethod extends AbstractSiteConfigPref @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateInactivityBeforeLockout(); } } - private void updateInactivityBeforeLockout(){ - try { - _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); - - - for(ScheduledFuture temp: scheduledInactivityBeforeLockout){ - temp.cancel(false); - } - scheduledInactivityBeforeLockout.clear(); - scheduledInactivityBeforeLockout.add(_scheduler.schedule(new DisableInactiveUsers((new Long(SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getInactivityBeforeLockout()))).intValue(),(new Long(SiteConfigPreferences.convertPGIntervalToSeconds(XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()))).intValue()),new CronTrigger(XDAT.getSiteConfigPreferences().getInactivityBeforeLockoutSchedule()))); - - } catch (Exception e1) { - _log.error("", e1); - } - } + private void updateInactivityBeforeLockout() { + _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); + for (ScheduledFuture temp : _scheduledInactivityBeforeLockout) { + temp.cancel(false); + } + _scheduledInactivityBeforeLockout.clear(); + try { + _scheduledInactivityBeforeLockout.add(_scheduler.schedule(new DisableInactiveUsers((new Long(SiteConfigPreferences.convertPGIntervalToSeconds(_preferences.getInactivityBeforeLockout()))).intValue(), (new Long(SiteConfigPreferences.convertPGIntervalToSeconds(_preferences.getMaxFailedLoginsLockoutDuration()))).intValue()), new CronTrigger(_preferences.getInactivityBeforeLockoutSchedule()))); + } catch (SQLException ignored) { + // Do nothing: the SQL exception here is superfluous. + } + } - private static final Logger _log = LoggerFactory.getLogger(InactivityBeforeLockoutHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("inactivityBeforeLockout", "inactivityBeforeLockoutSchedule")); - private ArrayList<ScheduledFuture> scheduledInactivityBeforeLockout = new ArrayList<>(); + private final ArrayList<ScheduledFuture> _scheduledInactivityBeforeLockout = new ArrayList<>(); - @Autowired - @Qualifier("taskScheduler") - private ThreadPoolTaskScheduler _scheduler; + private final SiteConfigPreferences _preferences; + private final ThreadPoolTaskScheduler _scheduler; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/MailHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/MailHandlerMethod.java index c42579dd7a639f4634b20cbc70409db0797a3e84..95d70d9282944036569c595d8389e2f4d304e992 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/MailHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/MailHandlerMethod.java @@ -3,12 +3,13 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; import org.nrg.notify.renderers.ChannelRenderer; import org.nrg.notify.renderers.NrgMailChannelRenderer; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.NotificationsPreferences; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.inject.Inject; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -16,6 +17,13 @@ import java.util.Map; @Component public class MailHandlerMethod extends AbstractSiteConfigNotificationsPreferenceHandlerMethod { + @Autowired + public MailHandlerMethod(final SiteConfigPreferences siteConfigPreferences, final NotificationsPreferences notificationsPreferences, final ChannelRenderer mailRenderer) { + _siteConfigPreferences = siteConfigPreferences; + _notificationsPreferences = notificationsPreferences; + _mailRenderer = mailRenderer; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -37,9 +45,8 @@ public class MailHandlerMethod extends AbstractSiteConfigNotificationsPreference private void updateMail(){ try { - ((NrgMailChannelRenderer)_mailRenderer).setFromAddress(XDAT.getSiteConfigPreferences().getAdminEmail()); - ((NrgMailChannelRenderer)_mailRenderer).setSubjectPrefix(XDAT.getNotificationsPreferences().getEmailPrefix()); - + ((NrgMailChannelRenderer)_mailRenderer).setFromAddress(_siteConfigPreferences.getAdminEmail()); + ((NrgMailChannelRenderer)_mailRenderer).setSubjectPrefix(_notificationsPreferences.getEmailPrefix()); } catch (Exception e1) { _log.error("", e1); } @@ -48,7 +55,7 @@ public class MailHandlerMethod extends AbstractSiteConfigNotificationsPreference private static final Logger _log = LoggerFactory.getLogger(MailHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("emailPrefix", "adminEmail")); - @Inject - private ChannelRenderer _mailRenderer; - + private final SiteConfigPreferences _siteConfigPreferences; + private final NotificationsPreferences _notificationsPreferences; + private final ChannelRenderer _mailRenderer; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/PasswordExpirationHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/PasswordExpirationHandlerMethod.java index baa4ac3d3a4418d837117ef3aafdb2cf3f210005..090ea9de12b966fd73715e1baa7505bd85ba7069 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/PasswordExpirationHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/PasswordExpirationHandlerMethod.java @@ -5,7 +5,6 @@ import org.nrg.xnat.security.XnatExpiredPasswordFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -15,6 +14,11 @@ import java.util.Map; @Component public class PasswordExpirationHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public PasswordExpirationHandlerMethod(final XnatExpiredPasswordFilter filter) { + _filter = filter; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -41,7 +45,5 @@ public class PasswordExpirationHandlerMethod extends AbstractSiteConfigPreferenc private static final Logger _log = LoggerFactory.getLogger(PasswordExpirationHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("passwordExpirationType", "passwordExpirationInterval", "passwordExpirationDate")); - @Autowired - @Qualifier("expiredPasswordFilter") - private XnatExpiredPasswordFilter _filter; + private final XnatExpiredPasswordFilter _filter; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/PathHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/PathHandlerMethod.java index 933144ddf0cf25f81506bae0724c0cae88766e7c..55fde87ce670c203b66b539f0abcd3ddd1a7d267 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/PathHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/PathHandlerMethod.java @@ -1,10 +1,14 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xdat.security.services.RoleHolder; +import org.nrg.framework.exceptions.NrgServiceError; +import org.nrg.framework.exceptions.NrgServiceRuntimeException; +import org.nrg.xdat.security.user.exceptions.UserInitException; +import org.nrg.xft.exception.ElementNotFoundException; import org.nrg.xft.security.UserI; +import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.turbine.utils.ArcSpecManager; +import org.nrg.xnat.utils.XnatUserProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +21,12 @@ import java.util.Map; @Component public class PathHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public PathHandlerMethod(final XnatUserProvider primaryAdminUserProvider, final XnatAppInfo appInfo) { + super(primaryAdminUserProvider); + _appInfo = appInfo; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -37,31 +47,31 @@ public class PathHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod } private void updateArchivePath() { - try { - ArcSpecManager.initialize(getAdminUser()); - } catch (Exception e) { - _log.error("",e); + if (!_appInfo.isInitialized()) { + _log.warn("Application is not yet initialized, update archive path operation aborted."); + return; } - } - private UserI getAdminUser() { - for (String login : Users.getAllLogins()) { - try { - final UserI user = Users.getUser(login); - if (_roleHolder.isSiteAdmin(user)) { - return user; - } + try { + final UserI adminUser = getAdminUser(); + if (adminUser == null) { + _log.error("No error occurred but failed to retrieve admin user, can't proceed with archive path update."); + } else { + ArcSpecManager.initialize(adminUser); } - catch(Exception e){ - + } catch (final ElementNotFoundException | UserInitException | NrgServiceRuntimeException e) { + if (!(e instanceof NrgServiceRuntimeException) || ((NrgServiceRuntimeException) e).getServiceError() == NrgServiceError.UserServiceError) { + _log.warn("The user for initializing the arcspec could not be initialized. This probably means the system is still initializing. Check the database if this is not the case."); + } else { + _log.error("An unknown error occurred trying to update the archive path.", e); } + } catch (final Exception e) { + _log.error("An unknown error occurred trying to update the archive path.", e); } - return null; } private static final Logger _log = LoggerFactory.getLogger(PathHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("archivePath","prearchivePath","cachePath","ftpPath","buildPath","pipelinePath")); + private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("archivePath", "prearchivePath", "cachePath", "ftpPath", "buildPath", "pipelinePath")); - @Autowired - private RoleHolder _roleHolder; + private final XnatAppInfo _appInfo; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/PetTracerHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/PetTracerHandlerMethod.java index 6e2c5d232ce0c9b49b95b74ea7204cafd30a7d47..e5e8f0a28efa93c481316e40e9f5d209b47842e4 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/PetTracerHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/PetTracerHandlerMethod.java @@ -1,23 +1,27 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xdat.security.services.RoleHolder; -import org.nrg.xft.security.UserI; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.services.PETTracerUtils; +import org.nrg.xnat.utils.XnatUserProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @Component public class PetTracerHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public PetTracerHandlerMethod(final SiteConfigPreferences preferences, final XnatUserProvider primaryAdminUserProvider, final PETTracerUtils petTracerUtils) { + super(primaryAdminUserProvider); + _preferences = preferences; + _petTracerUtils = petTracerUtils; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -32,32 +36,22 @@ public class PetTracerHandlerMethod extends AbstractSiteConfigPreferenceHandlerM @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updatePetTracer(); } } - private void updatePetTracer(){ + private void updatePetTracer() { try { - PETTracerUtils.getService().setSiteWideTracerList(getAdminUser().getLogin(), PETTracerUtils.buildScriptPath(PETTracerUtils.ResourceScope.SITE_WIDE, ""), XDAT.getSiteConfigPreferences().getSitewidePetTracers()); - } - catch(Exception e){ - _log.error("Failed to set sitewide anon script.",e); + _petTracerUtils.setSiteWideTracerList(getAdminUsername(), PETTracerUtils.buildScriptPath(PETTracerUtils.ResourceScope.SITE_WIDE, ""), _preferences.getSitewidePetTracers()); + } catch (Exception e) { + _log.error("Failed to set sitewide anon script.", e); } } private static final Logger _log = LoggerFactory.getLogger(PetTracerHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("sitewidePetTracers")); - - private UserI getAdminUser() throws Exception { - for (String login : Users.getAllLogins()) { - final UserI user = Users.getUser(login); - if (_roleHolder.isSiteAdmin(user)) { - return user; - } - } - return null; - } - @Autowired - private RoleHolder _roleHolder; + private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("sitewidePetTracers")); + + private final SiteConfigPreferences _preferences; + private final PETTracerUtils _petTracerUtils; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java index b21487cf645575628e938587a08b69ec4bb98efe..3aee25ec083c03961d876e3a18ba18b7ac445d9f 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/RequiredChannelHandlerMethod.java @@ -1,21 +1,23 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.TranslatingChannelProcessingFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @Component public class RequiredChannelHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public RequiredChannelHandlerMethod(final SiteConfigPreferences preferences, final TranslatingChannelProcessingFilter filter) { + _preferences = preferences; + _filter = filter; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -30,19 +32,17 @@ public class RequiredChannelHandlerMethod extends AbstractSiteConfigPreferenceHa @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateRequiredChannel(); } } - private void updateRequiredChannel(){ - _filter.setRequiredChannel(XDAT.getSiteConfigPreferences().getSecurityChannel()); - } + private void updateRequiredChannel() { + _filter.setRequiredChannel(_preferences.getSecurityChannel()); + } - private static final Logger _log = LoggerFactory.getLogger(RequiredChannelHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("security.channel")); + private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("security.channel")); - @Autowired - @Qualifier("channelProcessingFilter") - private TranslatingChannelProcessingFilter _filter; + private final SiteConfigPreferences _preferences; + private final TranslatingChannelProcessingFilter _filter; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/ResetFailedLoginsHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/ResetFailedLoginsHandlerMethod.java index fd94e3146ff6068c9583bee3ec033cec416cf0a9..9f9e50681b256eef9b25d2931df858f668b6b811 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/ResetFailedLoginsHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/ResetFailedLoginsHandlerMethod.java @@ -1,13 +1,9 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.ResetFailedLogins; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; @@ -18,6 +14,13 @@ import java.util.concurrent.ScheduledFuture; @Component public class ResetFailedLoginsHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public ResetFailedLoginsHandlerMethod(final SiteConfigPreferences preferences, final JdbcTemplate template, final ThreadPoolTaskScheduler scheduler) { + _preferences = preferences; + _template = template; + _scheduler = scheduler; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -32,37 +35,26 @@ public class ResetFailedLoginsHandlerMethod extends AbstractSiteConfigPreference @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateResetFailedLogins(); } } - private void updateResetFailedLogins(){ - try { - _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); - _scheduler.getScheduledThreadPoolExecutor().getQueue().iterator(); - - for(ScheduledFuture temp: scheduledResetFailedLogins){ - temp.cancel(false); - } - scheduledResetFailedLogins.clear(); - scheduledResetFailedLogins.add(_scheduler.schedule(new ResetFailedLogins(_template,XDAT.getSiteConfigPreferences().getMaxFailedLoginsLockoutDuration()),new CronTrigger(XDAT.getSiteConfigPreferences().getResetFailedLoginsSchedule()))); - - } catch (Exception e1) { - _log.error("", e1); - } - } + private void updateResetFailedLogins() { + _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); + _scheduler.getScheduledThreadPoolExecutor().getQueue().iterator(); + for (ScheduledFuture temp : scheduledResetFailedLogins) { + temp.cancel(false); + } + scheduledResetFailedLogins.clear(); + scheduledResetFailedLogins.add(_scheduler.schedule(new ResetFailedLogins(_template, _preferences.getMaxFailedLoginsLockoutDuration()), new CronTrigger(_preferences.getResetFailedLoginsSchedule()))); + } - private static final Logger _log = LoggerFactory.getLogger(ResetFailedLoginsHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("maxFailedLoginsLockoutDuration", "resetFailedLoginsSchedule")); - @Autowired - @Lazy - private JdbcTemplate _template; + private final ArrayList<ScheduledFuture> scheduledResetFailedLogins = new ArrayList<>(); - private ArrayList<ScheduledFuture> scheduledResetFailedLogins = new ArrayList<>(); - - @Autowired - @Qualifier("taskScheduler") - private ThreadPoolTaskScheduler _scheduler; + private final SiteConfigPreferences _preferences; + private final JdbcTemplate _template; + private final ThreadPoolTaskScheduler _scheduler; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java index a1072e3dbd7650dfa72bd1e9cb91cd968e9d2338..bdfdda227a053b651e9aebfe1202d4f98450b974 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/RoleServicesHandlerMethod.java @@ -1,7 +1,7 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.security.services.RoleHolder; import org.nrg.xdat.security.services.RoleRepositoryHolder; import org.nrg.xdat.security.services.RoleRepositoryServiceI; @@ -18,6 +18,13 @@ import java.util.Map; @Component public class RoleServicesHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public RoleServicesHandlerMethod(final SiteConfigPreferences preferences, final RoleHolder roleHolder, final RoleRepositoryHolder roleRepositoryHolder) { + _preferences = preferences; + _roleHolder = roleHolder; + _roleRepositoryHolder = roleRepositoryHolder; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -32,34 +39,39 @@ public class RoleServicesHandlerMethod extends AbstractSiteConfigPreferenceHandl @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateFeatureServices(); } } - private void updateFeatureServices(){ + private void updateFeatureServices() { + final String roleService = _preferences.getRoleService(); + final String roleRepositoryService = _preferences.getRoleRepositoryService(); try { - _roleHolder.setRoleService(Class.forName(XDAT.getSiteConfigPreferences().getRoleService()).asSubclass(RoleServiceI.class).newInstance()); - } - catch(Exception e){ - _log.error("",e); + _roleHolder.setRoleService(Class.forName(roleService).asSubclass(RoleServiceI.class).newInstance()); + } catch (InstantiationException e) { + _log.error("An error occurred creating the role service with class: " + roleService, e); + } catch (IllegalAccessException e) { + _log.error("Access denied when creating the role service with class: " + roleService, e); + } catch (ClassNotFoundException e) { + _log.error("Could not find the specified role service class on the classpath: " + roleService, e); } try { - _roleRepositoryHolder.setRoleRepositoryService(Class.forName(XDAT.getSiteConfigPreferences().getRoleRepositoryService()).asSubclass(RoleRepositoryServiceI.class).newInstance()); - } - catch(Exception e){ - _log.error("",e); + _roleRepositoryHolder.setRoleRepositoryService(Class.forName(roleRepositoryService).asSubclass(RoleRepositoryServiceI.class).newInstance()); + } catch (InstantiationException e) { + _log.error("An error occurred creating the role repository service with class: " + roleRepositoryService, e); + } catch (IllegalAccessException e) { + _log.error("Access denied when creating the role repository service with class: " + roleRepositoryService, e); + } catch (ClassNotFoundException e) { + _log.error("Could not find the specified role repository service class on the classpath: " + roleRepositoryService, e); } } private static final Logger _log = LoggerFactory.getLogger(RoleServicesHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("security.services.role.default", "security.services.roleRepository.default")); - - @Autowired - private RoleHolder _roleHolder; - - @Autowired - private RoleRepositoryHolder _roleRepositoryHolder; + private final SiteConfigPreferences _preferences; + private final RoleHolder _roleHolder; + private final RoleRepositoryHolder _roleRepositoryHolder; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/SeriesImportFilterHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/SeriesImportFilterHandlerMethod.java index 9d5f3e2e6cebb571fffe9d56bbc1ee16090defe5..da70c241cc3df74a0c059f752e17b816121ba046 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/SeriesImportFilterHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/SeriesImportFilterHandlerMethod.java @@ -2,14 +2,11 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; import org.nrg.dicomtools.filters.*; -import org.nrg.xdat.XDAT; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xdat.security.services.RoleHolder; -import org.nrg.xft.security.UserI; +import org.nrg.xdat.preferences.SiteConfigPreferences; +import org.nrg.xnat.utils.XnatUserProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -19,6 +16,13 @@ import java.util.Map; @Component public class SeriesImportFilterHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public SeriesImportFilterHandlerMethod(final SiteConfigPreferences preferences, final DicomFilterService dicomFilterService, final XnatUserProvider primaryAdminUserProvider) { + super(primaryAdminUserProvider); + _preferences = preferences; + _dicomFilterService = dicomFilterService; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -33,58 +37,34 @@ public class SeriesImportFilterHandlerMethod extends AbstractSiteConfigPreferenc @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateSeriesImportFilter(); } } - private void updateSeriesImportFilter(){ + private void updateSeriesImportFilter() { try { - final boolean enabled = XDAT.getSiteConfigPreferences().getEnableSitewideSeriesImportFilter(); - final SeriesImportFilterMode mode = SeriesImportFilterMode.mode(XDAT.getSiteConfigPreferences().getSitewideSeriesImportFilterMode()); - final String filterContents = XDAT.getSiteConfigPreferences().getSitewideSeriesImportFilter(); + final boolean enabled = _preferences.getEnableSitewideSeriesImportFilter(); + final SeriesImportFilterMode mode = SeriesImportFilterMode.mode(_preferences.getSitewideSeriesImportFilterMode()); + final String filterContents = _preferences.getSitewideSeriesImportFilter(); final SeriesImportFilter seriesImportFilter; if (mode == SeriesImportFilterMode.ModalityMap) { seriesImportFilter = new ModalityMapSeriesImportFilter(filterContents, enabled); } else { seriesImportFilter = new RegExBasedSeriesImportFilter(filterContents, mode, enabled); } - if (!seriesImportFilter.equals(getSeriesImportFilter())) { - getDicomFilterService().commit(seriesImportFilter, getAdminUser().getLogin(), "Updated site-wide series import filter from administrator UI."); + final SeriesImportFilter sitewide = _dicomFilterService.getSeriesImportFilter(); + if (!seriesImportFilter.equals(sitewide)) { + _dicomFilterService.commit(seriesImportFilter, getAdminUsername(), "Updated site-wide series import filter from administrator UI."); } - } - catch(Exception e){ - _log.error("Failed to update Series Import Filter.",e); + } catch (Exception e) { + _log.error("Failed to update Series Import Filter.", e); } } private static final Logger _log = LoggerFactory.getLogger(SeriesImportFilterHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("enableSitewideSeriesImportFilter", "sitewideSeriesImportFilterMode", "sitewideSeriesImportFilter")); - private UserI getAdminUser() throws Exception { - for (String login : Users.getAllLogins()) { - final UserI user = Users.getUser(login); - if (_roleHolder.isSiteAdmin(user)) { - return user; - } - } - return null; - } - - private DicomFilterService getDicomFilterService() { - return XDAT.getContextService().getBean(DicomFilterService.class); - } - - private SeriesImportFilter getSeriesImportFilter() { - DicomFilterService service = getDicomFilterService(); - if (service != null) { - return service.getSeriesImportFilter(); - } - else{ - return null; - } - } - - @Autowired - private RoleHolder _roleHolder; + private final SiteConfigPreferences _preferences; + private final DicomFilterService _dicomFilterService; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/SessionXmlRebuilderHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/SessionXmlRebuilderHandlerMethod.java index b6b42b7fa088102489b668e11090e8c172ec049e..037a2cedcf6bffbbe1f43931539e95a0fd202b5f 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/SessionXmlRebuilderHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/SessionXmlRebuilderHandlerMethod.java @@ -1,24 +1,30 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.helpers.prearchive.SessionXMLRebuilder; +import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.utils.XnatUserProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jms.core.JmsTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.PeriodicTrigger; import org.springframework.stereotype.Component; -import javax.inject.Inject; import java.util.*; import java.util.concurrent.ScheduledFuture; @Component public class SessionXmlRebuilderHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public SessionXmlRebuilderHandlerMethod(final SiteConfigPreferences preferences, final ThreadPoolTaskScheduler scheduler, final JmsTemplate jmsTemplate, final XnatUserProvider primaryAdminUserProvider, final XnatAppInfo appInfo) { + _preferences = preferences; + _scheduler = scheduler; + _jmsTemplate = jmsTemplate; + _provider = primaryAdminUserProvider; + _appInfo = appInfo; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -33,38 +39,27 @@ public class SessionXmlRebuilderHandlerMethod extends AbstractSiteConfigPreferen @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateSessionXmlRebuilder(); } } - private void updateSessionXmlRebuilder(){ - try { - _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); - - for(ScheduledFuture temp: scheduledXmlRebuilder){ - temp.cancel(false); - } - scheduledXmlRebuilder.clear(); - scheduledXmlRebuilder.add(_scheduler.schedule(new SessionXMLRebuilder(_provider, XDAT.getSiteConfigPreferences().getSessionXmlRebuilderInterval(), _jmsTemplate),new PeriodicTrigger(XDAT.getSiteConfigPreferences().getSessionXmlRebuilderRepeat()))); - - } catch (Exception e1) { - _log.error("", e1); - } - } + private void updateSessionXmlRebuilder() { + _scheduler.getScheduledThreadPoolExecutor().setRemoveOnCancelPolicy(true); + for (ScheduledFuture temp : scheduledXmlRebuilder) { + temp.cancel(false); + } + scheduledXmlRebuilder.clear(); + scheduledXmlRebuilder.add(_scheduler.schedule(new SessionXMLRebuilder(_provider, _appInfo, _jmsTemplate, _preferences.getSessionXmlRebuilderInterval()), new PeriodicTrigger(_preferences.getSessionXmlRebuilderRepeat()))); + } - private static final Logger _log = LoggerFactory.getLogger(SessionXmlRebuilderHandlerMethod.class); private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("sessionXmlRebuilderRepeat", "sessionXmlRebuilderInterval")); - private ArrayList<ScheduledFuture> scheduledXmlRebuilder = new ArrayList<>(); - - @Autowired - @Qualifier("taskScheduler") - private ThreadPoolTaskScheduler _scheduler; - - @Inject - private JmsTemplate _jmsTemplate; + private final ArrayList<ScheduledFuture> scheduledXmlRebuilder = new ArrayList<>(); - @Inject - private XnatUserProvider _provider; + private final SiteConfigPreferences _preferences; + private final ThreadPoolTaskScheduler _scheduler; + private final JmsTemplate _jmsTemplate; + private final XnatUserProvider _provider; + private XnatAppInfo _appInfo; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java index 7b9a8bb304f44859c7169e81c377dd7437d80c19..ceaa07a8618622b281fd8f28393d55705d339058 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/SmtpHandlerMethod.java @@ -2,18 +2,22 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; import org.nrg.mail.services.MailService; -import org.nrg.xdat.XDAT; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.nrg.xdat.preferences.NotificationsPreferences; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.stereotype.Component; -import javax.inject.Inject; import java.util.*; @Component public class SmtpHandlerMethod extends AbstractNotificationsPreferenceHandlerMethod { + @Autowired + public SmtpHandlerMethod(final NotificationsPreferences preferences, final JavaMailSenderImpl mailSender, final MailService mailService) { + _preferences = preferences; + this._mailSender = mailSender; + _mailService = mailService; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -28,45 +32,41 @@ public class SmtpHandlerMethod extends AbstractNotificationsPreferenceHandlerMet @Override public void handlePreference(final String preference, final String value) { - if(PREFERENCES.contains(preference)){ + if (PREFERENCES.contains(preference)) { updateSmtp(); } } - private void updateSmtp(){ - try { - mailSender.setHost(XDAT.getNotificationsPreferences().getHostname()); - mailSender.setPort(XDAT.getNotificationsPreferences().getPort()); - mailSender.setUsername(XDAT.getNotificationsPreferences().getUsername()); - mailSender.setPassword(XDAT.getNotificationsPreferences().getPassword()); - mailSender.setProtocol(XDAT.getNotificationsPreferences().getProtocol()); + private void updateSmtp() { + final Properties oldMailProperties = _mailSender.getJavaMailProperties(); + + final boolean smtpEnabled = _preferences.getSmtpEnabled(); + final boolean smtpAuth = _preferences.getSmtpAuth(); + final boolean startTls = _preferences.getSmtpStartTls(); + final String sslTrust = _preferences.getSmtpSSLTrust(); - Properties oldMailProperties = mailSender.getJavaMailProperties(); - boolean smtpEnabled = XDAT.getNotificationsPreferences().getSmtpEnabled(); - boolean smtpAuth = XDAT.getNotificationsPreferences().getSmtpAuth(); - boolean startTls = XDAT.getNotificationsPreferences().getSmtpStartTls(); - String sslTrust = XDAT.getNotificationsPreferences().getSmtpSSLTrust(); - _mailService.setSmtpEnabled(smtpEnabled); - oldMailProperties.setProperty("smtp.enabled",String.valueOf(smtpEnabled)); - oldMailProperties.setProperty("mail.smtp.auth",String.valueOf(smtpAuth)); - oldMailProperties.setProperty("mail.smtp.starttls.enable",String.valueOf(startTls)); - if(sslTrust!=null) { - oldMailProperties.setProperty("mail.smtp.ssl.trust", sslTrust); - } - mailSender.setJavaMailProperties(oldMailProperties); + _mailSender.setHost(_preferences.getHostname()); + _mailSender.setPort(_preferences.getPort()); + _mailSender.setUsername(_preferences.getUsername()); + _mailSender.setPassword(_preferences.getPassword()); + _mailSender.setProtocol(_preferences.getProtocol()); + _mailService.setSmtpEnabled(smtpEnabled); - } catch (Exception e1) { - _log.error("", e1); - } - } + oldMailProperties.setProperty("smtp.enabled", String.valueOf(smtpEnabled)); + oldMailProperties.setProperty("mail.smtp.auth", String.valueOf(smtpAuth)); + oldMailProperties.setProperty("mail.smtp.starttls.enable", String.valueOf(startTls)); - private static final Logger _log = LoggerFactory.getLogger(SmtpHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("smtp.enabled", "host","port", "username","password", "protocol","smtp.enabled", "mail.smtp.auth","mail.smtp.starttls.enable", "mail.smtp.ssl.trust")); + if (sslTrust != null) { + oldMailProperties.setProperty("mail.smtp.ssl.trust", sslTrust); + } + + _mailSender.setJavaMailProperties(oldMailProperties); + } - @Inject - private JavaMailSenderImpl mailSender; + private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("smtp.enabled", "host", "port", "username", "password", "protocol", "smtp.enabled", "mail.smtp.auth", "mail.smtp.starttls.enable", "mail.smtp.ssl.trust")); - @Autowired - private MailService _mailService; + private final NotificationsPreferences _preferences; + private final JavaMailSenderImpl _mailSender; + private final MailService _mailService; } diff --git a/src/main/java/org/nrg/xnat/event/listeners/methods/UpdateSecurityFilterHandlerMethod.java b/src/main/java/org/nrg/xnat/event/listeners/methods/UpdateSecurityFilterHandlerMethod.java index 4dc18c9c6993fbc04481fb6e6858c0b0aff91c7a..76156d9245e8ac63d540d2b49c932aa2827adb80 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/methods/UpdateSecurityFilterHandlerMethod.java +++ b/src/main/java/org/nrg/xnat/event/listeners/methods/UpdateSecurityFilterHandlerMethod.java @@ -1,21 +1,25 @@ package org.nrg.xnat.event.listeners.methods; import com.google.common.collect.ImmutableList; -import org.nrg.xdat.XDAT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.FilterSecurityInterceptorBeanPostProcessor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @Component public class UpdateSecurityFilterHandlerMethod extends AbstractSiteConfigPreferenceHandlerMethod { + @Autowired + public UpdateSecurityFilterHandlerMethod(final SiteConfigPreferences preferences, @SuppressWarnings("SpringJavaAutowiringInspection") final FilterSecurityInterceptor interceptor, final FilterSecurityInterceptorBeanPostProcessor postProcessor) { + _preferences = preferences; + _interceptor = interceptor; + _postProcessor = postProcessor; + } + @Override public List<String> getHandledPreferences() { return PREFERENCES; @@ -37,17 +41,14 @@ public class UpdateSecurityFilterHandlerMethod extends AbstractSiteConfigPrefere private void updateSecurityFilter(){ if(_interceptor!=null && _postProcessor!=null){ - _interceptor.setSecurityMetadataSource(_postProcessor.getMetadataSource(XDAT.getSiteConfigPreferences().getRequireLogin())); + _interceptor.setSecurityMetadataSource(_postProcessor.getMetadataSource(_preferences.getRequireLogin())); } } - private static final Logger _log = LoggerFactory.getLogger(UpdateSecurityFilterHandlerMethod.class); - private static final List<String> PREFERENCES = ImmutableList.copyOf(Arrays.asList("requireLogin")); - - @Inject - private FilterSecurityInterceptor _interceptor; + private static final List<String> PREFERENCES = ImmutableList.copyOf(Collections.singletonList("requireLogin")); - @Inject - private FilterSecurityInterceptorBeanPostProcessor _postProcessor; + private final SiteConfigPreferences _preferences; + private final FilterSecurityInterceptor _interceptor; + private final FilterSecurityInterceptorBeanPostProcessor _postProcessor; } diff --git a/src/main/java/org/nrg/xnat/helpers/merge/AnonUtils.java b/src/main/java/org/nrg/xnat/helpers/merge/AnonUtils.java index 0a4209e2992ba6f01cd63f7edd3507a7fdb104b2..8d18fbf7f2c0d0ae6c02985b5d7a16f4aadac5a2 100644 --- a/src/main/java/org/nrg/xnat/helpers/merge/AnonUtils.java +++ b/src/main/java/org/nrg/xnat/helpers/merge/AnonUtils.java @@ -10,59 +10,62 @@ */ package org.nrg.xnat.helpers.merge; +import com.google.common.base.Joiner; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.config.CacheConfiguration; import net.sf.ehcache.config.PersistenceConfiguration; - +import org.apache.commons.io.IOUtils; import org.nrg.config.entities.Configuration; import org.nrg.config.exceptions.ConfigServiceException; import org.nrg.config.services.ConfigService; import org.nrg.framework.constants.Scope; +import org.nrg.framework.exceptions.NrgServiceError; +import org.nrg.framework.exceptions.NrgServiceRuntimeException; +import org.nrg.framework.utilities.BasicXnatResourceLocator; import org.nrg.xdat.XDAT; -import org.nrg.xft.XFT; import org.nrg.xnat.helpers.editscript.DicomEdit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import javax.inject.Inject; - -import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.util.List; @Service public class AnonUtils { - public AnonUtils() throws Exception { + public AnonUtils() throws Exception { if (_instance != null) { throw new Exception("The AnonUtils service is already initialized, try calling getInstance() instead."); } _instance = this; } - - public static AnonUtils getService() { - if (_instance == null) { - _instance = XDAT.getContextService().getBean(AnonUtils.class); - } - return _instance; - } - - public Configuration getScript(String path, Long project) { + + public static AnonUtils getService() { + if (_instance == null) { + _instance = XDAT.getContextService().getBean(AnonUtils.class); + } + return _instance; + } + + public Configuration getScript(String path, Long project) { if (logger.isDebugEnabled()) { logger.debug("Retrieving script for {}, {} for project: {}", DicomEdit.ToolName, path, project); } return project == null - ? _configService.getConfig(DicomEdit.ToolName, path) - : _configService.getConfig(DicomEdit.ToolName, path, Scope.Project, project.toString()); - } - - public boolean isEnabled(String path, Long project) { + ? _configService.getConfig(DicomEdit.ToolName, path) + : _configService.getConfig(DicomEdit.ToolName, path, Scope.Project, project.toString()); + } + + public boolean isEnabled(String path, Long project) { final Configuration config = project == null - ? _configService.getConfig(DicomEdit.ToolName, path) - : _configService.getConfig(DicomEdit.ToolName, path, Scope.Project, project.toString()); + ? _configService.getConfig(DicomEdit.ToolName, path) + : _configService.getConfig(DicomEdit.ToolName, path, Scope.Project, project.toString()); final boolean enabled = config.getStatus().equals(Configuration.ENABLED_STRING); if (logger.isDebugEnabled()) { @@ -73,12 +76,12 @@ public class AnonUtils { } } return enabled; - } - - public List<Configuration> getAllScripts (Long project) { + } + + public List<Configuration> getAllScripts(Long project) { final List<Configuration> scripts = project == null - ? _configService.getConfigsByTool(DicomEdit.ToolName) - : _configService.getConfigsByTool(DicomEdit.ToolName, Scope.Project, project.toString()); + ? _configService.getConfigsByTool(DicomEdit.ToolName) + : _configService.getConfigsByTool(DicomEdit.ToolName, Scope.Project, project.toString()); if (logger.isDebugEnabled()) { final String identifier = project == null ? "the site" : "project: " + project.toString(); @@ -91,10 +94,10 @@ public class AnonUtils { } } - return scripts; - } - - public void setProjectScript (String login, String path, String script, Long project) throws ConfigServiceException { + return scripts; + } + + public void setProjectScript(String login, String path, String script, Long project) throws ConfigServiceException { if (logger.isDebugEnabled()) { logger.debug("Setting script for {}, {} for project: {}", DicomEdit.ToolName, path, project); } @@ -103,63 +106,75 @@ public class AnonUtils { } else { _configService.replaceConfig(login, "", DicomEdit.ToolName, path, script, Scope.Project, project.toString()); } - } - - public void setSiteWideScript(String login, String path, String script) throws ConfigServiceException { + } + + public void setSiteWideScript(String login, String path, String script) throws ConfigServiceException { _configService.replaceConfig(login, "", DicomEdit.ToolName, path, script); AnonUtils.invalidateSitewideAnonCache(); - } - - public void enableSiteWide (String login, String path ) throws ConfigServiceException { + } + + public void enableSiteWide(String login, String path) throws ConfigServiceException { _configService.enable(login, "", DicomEdit.ToolName, path); AnonUtils.invalidateSitewideAnonCache(); - } - - public void enableProjectSpecific(String login, String path, Long project) throws ConfigServiceException { + } + + public void enableProjectSpecific(String login, String path, Long project) throws ConfigServiceException { if (project == null) { _configService.enable(login, "", DicomEdit.ToolName, path); } else { _configService.enable(login, "", DicomEdit.ToolName, path, Scope.Project, project.toString()); } - } - - public void disableSiteWide(String login, String path) throws ConfigServiceException { + } + + public void disableSiteWide(String login, String path) throws ConfigServiceException { _configService.disable(login, "", DicomEdit.ToolName, path); AnonUtils.invalidateSitewideAnonCache(); - } - - public void disableProjectSpecific(String login, String path, Long project) throws ConfigServiceException { + } + + public void disableProjectSpecific(String login, String path, Long project) throws ConfigServiceException { if (project == null) { _configService.disable(login, "", DicomEdit.ToolName, path); } else { _configService.disable(login, "", DicomEdit.ToolName, path, Scope.Project, project.toString()); } - } - - public static File getDefaultScript () throws FileNotFoundException { - final File def = new File (XFT.GetConfDir(), DEFAULT_ANON_SCRIPT); - if (def.exists()) { - return def; - } - else { - throw new FileNotFoundException("Default anon script: " + DEFAULT_ANON_SCRIPT + " not found in " + XFT.GetConfDir()); - } - } - - - /** - * Adds a cache of site wide anon scripts. This is currently used by GradualDicomImporter. - * @return The site anonymization script cache. - */ - public static Cache getSiteAnonCache() { + } + + public static String getDefaultScript() throws IOException { + final List<Resource> resources = BasicXnatResourceLocator.getResources(DEFAULT_ANON_SCRIPT); + if (resources.size() == 0) { + throw new NrgServiceRuntimeException(NrgServiceError.ConfigurationError, "Didn't find any default anonymization scripts at: " + DEFAULT_ANON_SCRIPT); + } else if (resources.size() > 1) { + boolean isFirst = true; + final StringBuilder duplicates = new StringBuilder(); + for (final Resource resource : resources) { + if (!isFirst) { + duplicates.append(", "); + } else { + isFirst = false; + } + duplicates.append(resource.getURI()); + } + throw new NrgServiceRuntimeException(NrgServiceError.ConfigurationError, "Found more than one \"default\" anonymization script: " + duplicates.toString()); + } + try (final InputStream input = resources.get(0).getInputStream()) { + return Joiner.on("\n").join(IOUtils.readLines(input, "UTF-8")); + } + } + + /** + * Adds a cache of site wide anon scripts. This is currently used by GradualDicomImporter. + * + * @return The site anonymization script cache. + */ + public static Cache getSiteAnonCache() { synchronized (cacheManager) { if (!cacheManager.cacheExists(cacheName)) { final CacheConfiguration config = new CacheConfiguration(cacheName, 0) - .copyOnRead(false).copyOnWrite(false) - .eternal(false) - .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)) - .timeToLiveSeconds(ANON_CACHE_EXPIRY_SECONDS) - .maxEntriesLocalHeap(MAX_ENTRIES_LOCAL_HEAP); + .copyOnRead(false).copyOnWrite(false) + .eternal(false) + .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE)) + .timeToLiveSeconds(ANON_CACHE_EXPIRY_SECONDS) + .maxEntriesLocalHeap(MAX_ENTRIES_LOCAL_HEAP); final Cache cache = new Cache(config); cacheManager.addCache(cache); return cache; @@ -168,35 +183,35 @@ public class AnonUtils { } } } - - public static void invalidateSitewideAnonCache(){ - getSiteAnonCache().removeAndReturnElement(SITE_WIDE); - } - + + public static void invalidateSitewideAnonCache() { + getSiteAnonCache().removeAndReturnElement(SITE_WIDE); + } + public static Configuration getCachedSitewideAnon() throws Exception { - final Cache anonCache=getSiteAnonCache(); - - Element cached= anonCache.get(SITE_WIDE); - if(null!=cached){ - return (Configuration)cached.getObjectValue(); - }else{ + final Cache anonCache = getSiteAnonCache(); + + Element cached = anonCache.get(SITE_WIDE); + if (null != cached) { + return (Configuration) cached.getObjectValue(); + } else { Configuration c = AnonUtils.getService().getScript(path, null); anonCache.put(new Element(SITE_WIDE, c)); return c; } } - private static String path = DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null); + private static String path = DicomEdit.buildScriptPath(DicomEdit.ResourceScope.SITE_WIDE, null); private static final String cacheName = "scripts-anon"; - - private static final CacheManager cacheManager = CacheManager.getInstance(); - private static final String SITE_WIDE = "site-wide"; - private static final long ANON_CACHE_EXPIRY_SECONDS = 120; - private static final int MAX_ENTRIES_LOCAL_HEAP = 5000; + + private static final CacheManager cacheManager = CacheManager.getInstance(); + private static final String SITE_WIDE = "site-wide"; + private static final long ANON_CACHE_EXPIRY_SECONDS = 120; + private static final int MAX_ENTRIES_LOCAL_HEAP = 5000; private static final Logger logger = LoggerFactory.getLogger(AnonUtils.class); - private static final String DEFAULT_ANON_SCRIPT = "id.das"; + private static final String DEFAULT_ANON_SCRIPT = "classpath*:META-INF/xnat/defaults/**/id.das"; private static AnonUtils _instance; diff --git a/src/main/java/org/nrg/xnat/helpers/prearchive/SessionXMLRebuilder.java b/src/main/java/org/nrg/xnat/helpers/prearchive/SessionXMLRebuilder.java index f9333c785ca42f67da612501c4e994c0947224c8..6ba5c672287c81b4fd6d5a55ab65db893efa1be1 100644 --- a/src/main/java/org/nrg/xnat/helpers/prearchive/SessionXMLRebuilder.java +++ b/src/main/java/org/nrg/xnat/helpers/prearchive/SessionXMLRebuilder.java @@ -11,9 +11,11 @@ package org.nrg.xnat.helpers.prearchive; import org.apache.commons.lang3.StringUtils; +import org.nrg.framework.exceptions.NrgServiceRuntimeException; import org.nrg.xdat.XDAT; import org.nrg.xft.exception.InvalidPermissionException; import org.nrg.xft.security.UserI; +import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.services.messaging.prearchive.PrearchiveOperationRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,70 +29,93 @@ import java.util.Calendar; import java.util.List; public class SessionXMLRebuilder implements Runnable { - public SessionXMLRebuilder(final Provider<UserI> provider, final double interval, final JmsTemplate jmsTemplate) { + public SessionXMLRebuilder(final Provider<UserI> provider, final XnatAppInfo appInfo, final JmsTemplate jmsTemplate, final double interval) { _provider = provider; + _appInfo = appInfo; _interval = interval; _jmsTemplate = jmsTemplate; } @Override public void run() { - final UserI user = _provider.get(); - logger.trace("Running prearc job as {}", user.getLogin()); - List<SessionData> sds = null; - long now = Calendar.getInstance().getTimeInMillis(); + if (!_appInfo.isInitialized()) { + if (!_markedUninitialized) { + logger.warn("Application is not yet initialized, session XML rebuild operation delayed until initialization completed."); + _markedUninitialized = true; + } + return; + } + try { - if (PrearcDatabase.ready) { - sds = PrearcDatabase.getAllSessions(); + final UserI user = _provider.get(); + if (user == null) { + logger.warn("The user for running the session XML rebuilder process was not found. Aborting for now."); + return; } - } catch (SessionException e) { - logger.error("", e); - } catch (SQLException e) { - // Swallow this message so it doesn't fill the logs before the prearchive is initialized. - if (!e.getMessage().contains("relation \"xdat_search.prearchive\" does not exist")) { + logger.trace("Running prearc job as {}", user.getLogin()); + List<SessionData> sds = null; + long now = Calendar.getInstance().getTimeInMillis(); + try { + if (PrearcDatabase.ready) { + sds = PrearcDatabase.getAllSessions(); + } + } catch (SessionException e) { + logger.error("", e); + } catch (SQLException e) { + // Swallow this message so it doesn't fill the logs before the prearchive is initialized. + if (!e.getMessage().contains("relation \"xdat_search.prearchive\" does not exist")) { + logger.error("", e); + } + } catch (Exception e) { logger.error("", e); } - } catch (Exception e) { - logger.error("", e); - } - int updated = 0; - int total = 0; - if (sds != null && sds.size() > 0) { - for (final SessionData sessionData : sds) { - total++; - if (sessionData.getStatus().equals(PrearcUtils.PrearcStatus.RECEIVING) && !sessionData.getPreventAutoCommit() && !StringUtils.trimToEmpty(sessionData.getSource()).equals("applet")) { - try { - final File sessionDir = PrearcUtils.getPrearcSessionDir(user, sessionData.getProject(), sessionData.getTimestamp(), sessionData.getFolderName(), false); - final long then = sessionData.getLastBuiltDate().getTime(); - final double diff = diffInMinutes(then, now); - if (diff >= _interval && !PrearcUtils.isSessionReceiving(sessionData.getSessionDataTriple())) { - updated++; - try { - if (PrearcDatabase.setStatus(sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject(), PrearcUtils.PrearcStatus.QUEUED_BUILDING)) { - logger.debug("Creating JMS queue entry for {} to archive {}", user.getUsername(), sessionData.getExternalUrl()); - final PrearchiveOperationRequest request = new PrearchiveOperationRequest(user, sessionData, sessionDir, "Rebuild"); - XDAT.sendJmsRequest(_jmsTemplate, request); + int updated = 0; + int total = 0; + if (sds != null && sds.size() > 0) { + for (final SessionData sessionData : sds) { + total++; + if (sessionData.getStatus().equals(PrearcUtils.PrearcStatus.RECEIVING) && !sessionData.getPreventAutoCommit() && !StringUtils.trimToEmpty(sessionData.getSource()).equals("applet")) { + try { + final File sessionDir = PrearcUtils.getPrearcSessionDir(user, sessionData.getProject(), sessionData.getTimestamp(), sessionData.getFolderName(), false); + final long then = sessionData.getLastBuiltDate().getTime(); + final double diff = diffInMinutes(then, now); + if (diff >= _interval && !PrearcUtils.isSessionReceiving(sessionData.getSessionDataTriple())) { + updated++; + try { + if (PrearcDatabase.setStatus(sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject(), PrearcUtils.PrearcStatus.QUEUED_BUILDING)) { + logger.debug("Creating JMS queue entry for {} to archive {}", user.getUsername(), sessionData.getExternalUrl()); + final PrearchiveOperationRequest request = new PrearchiveOperationRequest(user, sessionData, sessionDir, "Rebuild"); + XDAT.sendJmsRequest(_jmsTemplate, request); + } + } catch (Exception exception) { + logger.error("Error when setting prearchive session status to QUEUED", exception); } - } catch (Exception exception) { - logger.error("Error when setting prearchive session status to QUEUED", exception); + } else if (diff >= (_interval * 10)) { + logger.error(String.format("Prearchive session locked for an abnormally large time within CACHE_DIR/prearc_locks/%1$s/%2$s/%3$s", sessionData.getProject(), sessionData.getTimestamp(), sessionData.getName())); } - } else if (diff >= (_interval * 10)) { - logger.error(String.format("Prearchive session locked for an abnormally large time within CACHE_DIR/prearc_locks/%1$s/%2$s/%3$s", sessionData.getProject(), sessionData.getTimestamp(), sessionData.getName())); + } catch (IOException e) { + final String message = String.format("An error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); + logger.error(message, e); + } catch (InvalidPermissionException e) { + final String message = String.format("A permissions error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); + logger.error(message, e); + } catch (Exception e) { + final String message = String.format("An unknown error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); + logger.error(message, e); } - } catch (IOException e) { - final String message = String.format("An error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); - logger.error(message, e); - } catch (InvalidPermissionException e) { - final String message = String.format("A permissions error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); - logger.error(message, e); - } catch (Exception e) { - final String message = String.format("An unknown error occurred trying to write the session %s %s %s.", sessionData.getFolderName(), sessionData.getTimestamp(), sessionData.getProject()); - logger.error(message, e); } } } + logger.info("Built {} of {}", updated, total); + } catch (final NrgServiceRuntimeException e) { + switch (e.getServiceError()) { + case UserServiceError: + logger.warn("The user for running the session XML rebuilder process could not be initialized. This probably means the system is still initializing. Check the database if this is not the case."); + break; + default: + throw e; + } } - logger.info("Built {} of {}", updated, total); } public static double diffInMinutes(long start, long end) { @@ -101,6 +126,9 @@ public class SessionXMLRebuilder implements Runnable { private static final Logger logger = LoggerFactory.getLogger(SessionXMLRebuilder.class); private final Provider<UserI> _provider; + private XnatAppInfo _appInfo; private final double _interval; private final JmsTemplate _jmsTemplate; + + private boolean _markedUninitialized = false; } diff --git a/src/main/java/org/nrg/xnat/initialization/DatabaseConfig.java b/src/main/java/org/nrg/xnat/initialization/DatabaseConfig.java index 83b59d908feb34e04c5190357cf3748526e9e179..d4f2e81074eb65019a470b0ea81a4f75c669d0d6 100644 --- a/src/main/java/org/nrg/xnat/initialization/DatabaseConfig.java +++ b/src/main/java/org/nrg/xnat/initialization/DatabaseConfig.java @@ -13,7 +13,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.jdbc.core.JdbcTemplate; -import javax.inject.Inject; import javax.sql.DataSource; import java.lang.reflect.InvocationTargetException; import java.util.Properties; @@ -34,8 +33,8 @@ public class DatabaseConfig { public static final String DEFAULT_DATASOURCE_MAX_IDLE = "10"; @Bean - public DataSource dataSource() throws NrgServiceException { - final Properties properties = Beans.getNamespacedProperties(_environment, "datasource", true); + public DataSource dataSource(final Environment environment) throws NrgServiceException { + final Properties properties = Beans.getNamespacedProperties(environment, "datasource", true); setDefaultDatasourceProperties(properties); final String dataSourceClassName = properties.getProperty("class"); try { @@ -57,8 +56,8 @@ public class DatabaseConfig { } @Bean - public JdbcTemplate jdbcTemplate() throws NrgServiceException { - return new JdbcTemplate(dataSource()); + public JdbcTemplate jdbcTemplate(final DataSource dataSource) throws NrgServiceException { + return new JdbcTemplate(dataSource); } private static Properties setDefaultDatasourceProperties(final Properties properties) { @@ -118,7 +117,4 @@ public class DatabaseConfig { } private static final Logger _log = LoggerFactory.getLogger(DatabaseConfig.class); - - @Inject - private Environment _environment; } diff --git a/src/main/java/org/nrg/xnat/initialization/InitializingTasksExecutor.java b/src/main/java/org/nrg/xnat/initialization/InitializingTasksExecutor.java index 64fbd2d1830a459e23b5f0c8c02ee852ad9c4e86..5fd693c38d6a45d6bbe9488a38acbecc20bb81d7 100644 --- a/src/main/java/org/nrg/xnat/initialization/InitializingTasksExecutor.java +++ b/src/main/java/org/nrg/xnat/initialization/InitializingTasksExecutor.java @@ -12,6 +12,12 @@ import java.util.List; @Component public class InitializingTasksExecutor { + @Autowired + @Lazy + public InitializingTasksExecutor(final List<InitializingTask> tasks) { + _tasks = tasks; + } + @EventListener public void executeOnContextRefresh(final ContextRefreshedEvent event) { if (_log.isDebugEnabled()) { @@ -32,7 +38,5 @@ public class InitializingTasksExecutor { private static final Logger _log = LoggerFactory.getLogger(InitializingTasksExecutor.class); - @Autowired - @Lazy - private List<InitializingTask> _tasks; + private final List<InitializingTask> _tasks; } diff --git a/src/main/java/org/nrg/xnat/initialization/PropertiesConfig.java b/src/main/java/org/nrg/xnat/initialization/PropertiesConfig.java index f6134038e051af0581c406d52b12a2f8cc53e431..b96165fcd8b03629ec3249e9d963176b042d1663 100644 --- a/src/main/java/org/nrg/xnat/initialization/PropertiesConfig.java +++ b/src/main/java/org/nrg/xnat/initialization/PropertiesConfig.java @@ -12,7 +12,6 @@ import org.springframework.context.annotation.PropertySources; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.env.Environment; -import javax.inject.Inject; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; @@ -56,12 +55,12 @@ public class PropertiesConfig { } @Bean - public Path xnatHome() { + public Path xnatHome(final Environment environment) { if (_xnatHome == null) { // We just get the parent of the first folder in the list of configuration folders XNAT_HOME. This won't be // null because, if there are no valid configuration folders, the config folders method will have already // thrown an exception. - _xnatHome = configFolderPaths().get(0).getParent(); + _xnatHome = configFolderPaths(environment).get(0).getParent(); if (_log.isInfoEnabled()) { _log.info("Set path {} as the XNAT home folder.", _xnatHome); } @@ -70,22 +69,22 @@ public class PropertiesConfig { } @Bean - public List<String> configFilesLocations() { + public List<String> configFilesLocations(final Environment environment) { // The configuration service should be converted to use List<Path> instead of List<String> and this bean should // be deprecated and removed. if (_configFolderLocations.size() == 0) { - configFolderPaths(); + configFolderPaths(environment); } return _configFolderLocations; } @Bean - public List<Path> configFolderPaths() { + public List<Path> configFolderPaths(final Environment environment) { if (_configFolderPaths.size() == 0) { final Map<String, String> paths = new HashMap<>(); for (int index = 0; index < CONFIG_LOCATIONS.size(); index++) { paths.put(CONFIG_LOCATIONS.get(index), CONFIG_PATHS.get(index)); - final Path path = getConfigFolder(_environment, CONFIG_LOCATIONS.get(index), CONFIG_PATHS.get(index)); + final Path path = getConfigFolder(environment, CONFIG_LOCATIONS.get(index), CONFIG_PATHS.get(index)); if (path != null) { if (_log.isInfoEnabled()) { _log.info("Adding path {} to the list of available configuration folders.", path.toString()); @@ -98,7 +97,7 @@ public class PropertiesConfig { final StringBuilder writer = new StringBuilder("No XNAT home specified in any of the accepted locations:\n"); for (final String variable : paths.keySet()) { writer.append(" * "); - final String value = _environment.getProperty(variable); + final String value = environment.getProperty(variable); if (StringUtils.isBlank(value)) { writer.append(variable).append(": Not defined"); } else { @@ -173,7 +172,7 @@ public class PropertiesConfig { } final Path candidate = Paths.get(value, relative); - final File file = candidate.toFile(); + final File file = candidate.toFile(); if (file.exists()) { // If it's a directory... if (file.isDirectory()) { @@ -208,9 +207,6 @@ public class PropertiesConfig { private static final List<String> CONFIG_URLS = new ArrayList<>(); - @Inject - private Environment _environment; - private final List<Path> _configFolderPaths = new ArrayList<>(); private final List<String> _configFolderLocations = new ArrayList<>(); private Path _xnatHome; diff --git a/src/main/java/org/nrg/xnat/initialization/RootConfig.java b/src/main/java/org/nrg/xnat/initialization/RootConfig.java index 48088809191ccbbe976059cb01c8c1e43ae4cfed..87bb0676675ed8b2548f452898e193ee5d626723 100644 --- a/src/main/java/org/nrg/xnat/initialization/RootConfig.java +++ b/src/main/java/org/nrg/xnat/initialization/RootConfig.java @@ -12,7 +12,6 @@ import org.nrg.framework.exceptions.NrgServiceException; import org.nrg.framework.services.ContextService; import org.nrg.framework.services.SerializerService; import org.nrg.prefs.beans.PreferenceBeanMixIn; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.configuration.ApplicationConfig; import org.nrg.xnat.helpers.prearchive.PrearcConfig; @@ -23,6 +22,7 @@ import org.springframework.context.annotation.Import; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import javax.servlet.ServletContext; @@ -40,20 +40,15 @@ import java.util.Map; * for standard XNAT components should be added in the {@link ApplicationConfig application configuration class}. */ @Configuration -@Import({PropertiesConfig.class, DatabaseConfig.class, SecurityConfig.class}) +@Import({PropertiesConfig.class, DatabaseConfig.class, SecurityConfig.class, ApplicationConfig.class}) public class RootConfig { @Bean - public XnatAppInfo appInfo(final ServletContext context) throws IOException { - return new XnatAppInfo(context); + public XnatAppInfo appInfo(final ServletContext context, final JdbcTemplate template) throws IOException { + return new XnatAppInfo(context, template); } @Bean - public InitializerSiteConfiguration initializerSiteConfiguration() { - return new InitializerSiteConfiguration(); - } - - @Bean - public ContextService rootContextService() throws NrgServiceException { + public ContextService contextService() throws NrgServiceException { return ContextService.getInstance(); } diff --git a/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java b/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java index 6bca03b5a2bf491b32dc29a83aceb0a328c3331d..6bd28e333c9c895c28d22e375aabf018e4f5f8e6 100644 --- a/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java +++ b/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java @@ -5,7 +5,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import org.nrg.config.exceptions.SiteConfigurationException; import org.nrg.framework.services.SerializerService; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; +import org.nrg.xdat.services.AliasTokenService; +import org.nrg.xdat.services.XdatUserAuthService; import org.nrg.xnat.security.*; import org.nrg.xnat.security.alias.AliasTokenAuthenticationProvider; import org.nrg.xnat.security.config.AuthenticationProviderAggregator; @@ -13,19 +15,23 @@ import org.nrg.xnat.security.config.AuthenticationProviderConfigurator; import org.nrg.xnat.security.config.DatabaseAuthenticationProviderConfigurator; import org.nrg.xnat.security.config.LdapAuthenticationProviderConfigurator; import org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService; -import org.springframework.beans.factory.annotation.Autowired; +import org.nrg.xnat.services.XnatAppInfo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; -import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Primary; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.vote.AuthenticatedVoter; import org.springframework.security.access.vote.RoleVoter; import org.springframework.security.access.vote.UnanimousBased; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.AuthenticationEntryPoint; @@ -33,7 +39,6 @@ import org.springframework.security.web.access.channel.ChannelDecisionManagerImp import org.springframework.security.web.access.channel.InsecureChannelProcessor; import org.springframework.security.web.access.channel.SecureChannelProcessor; import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.security.web.authentication.session.*; @@ -45,6 +50,7 @@ import java.io.InputStream; import java.util.*; @Configuration +@EnableWebSecurity @ImportResource("WEB-INF/conf/xnat-security.xml") public class SecurityConfig { @Bean @@ -68,8 +74,8 @@ public class SecurityConfig { } @Bean - public XnatAuthenticationEntryPoint loginUrlAuthenticationEntryPoint() { - final XnatAuthenticationEntryPoint entryPoint = new XnatAuthenticationEntryPoint("/app/template/Login.vm", _configuration); + public XnatAuthenticationEntryPoint loginUrlAuthenticationEntryPoint(final SiteConfigPreferences preferences) { + final XnatAuthenticationEntryPoint entryPoint = new XnatAuthenticationEntryPoint("/app/template/Login.vm", preferences); entryPoint.setDataPaths(Arrays.asList("/xapi/**", "/data/**", "/REST/**", "/fs/**")); entryPoint.setInteractiveAgents(Arrays.asList(".*MSIE.*", ".*Mozilla.*", ".*AppleWebKit.*", ".*Opera.*")); return entryPoint; @@ -86,11 +92,12 @@ public class SecurityConfig { } @Bean - public CompositeSessionAuthenticationStrategy sas(final SessionRegistry sessionRegistry) throws SiteConfigurationException { + @Primary + public CompositeSessionAuthenticationStrategy sas(final SessionRegistry sessionRegistry, final SiteConfigPreferences preferences) throws SiteConfigurationException { ArrayList<SessionAuthenticationStrategy> authStrategies = new ArrayList<>(); final ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry); - strategy.setMaximumSessions(_configuration.getConcurrentMaxSessions()); + strategy.setMaximumSessions(preferences.getConcurrentMaxSessions()); strategy.setExceptionIfMaximumExceeded(true); authStrategies.add(strategy); @@ -104,24 +111,24 @@ public class SecurityConfig { } @Bean - public LogoutFilter logoutFilter() { + public LogoutFilter logoutFilter(final SessionRegistry sessionRegistry) { final XnatLogoutSuccessHandler logoutSuccessHandler = new XnatLogoutSuccessHandler(); logoutSuccessHandler.setOpenXnatLogoutSuccessUrl("/"); logoutSuccessHandler.setSecuredXnatLogoutSuccessUrl("/app/template/Login.vm"); final SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler(); securityContextLogoutHandler.setInvalidateHttpSession(true); - final XnatLogoutHandler xnatLogoutHandler = new XnatLogoutHandler(); - final LogoutFilter filter = new LogoutFilter(logoutSuccessHandler, securityContextLogoutHandler, xnatLogoutHandler); + final XnatLogoutHandler xnatLogoutHandler = new XnatLogoutHandler(sessionRegistry); + final LogoutFilter filter = new LogoutFilter(logoutSuccessHandler, securityContextLogoutHandler, xnatLogoutHandler); filter.setFilterProcessesUrl("/app/action/LogoutUser"); return filter; } @Bean - public FilterSecurityInterceptorBeanPostProcessor filterSecurityInterceptorBeanPostProcessor() throws IOException { + public FilterSecurityInterceptorBeanPostProcessor filterSecurityInterceptorBeanPostProcessor(final SerializerService serializer, final SiteConfigPreferences preferences) throws IOException { final Resource resource = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/configured-urls.yaml"); try (final InputStream inputStream = resource.getInputStream()) { - final HashMap<String, ArrayList<String>> urlMap = _serializer.deserializeYaml(inputStream, TYPE_REFERENCE); - final FilterSecurityInterceptorBeanPostProcessor postProcessor = new FilterSecurityInterceptorBeanPostProcessor(); + final HashMap<String, ArrayList<String>> urlMap = serializer.deserializeYaml(inputStream, TYPE_REFERENCE); + final FilterSecurityInterceptorBeanPostProcessor postProcessor = new FilterSecurityInterceptorBeanPostProcessor(preferences); postProcessor.setOpenUrls(urlMap.get("openUrls")); postProcessor.setAdminUrls(urlMap.get("adminUrls")); return postProcessor; @@ -129,28 +136,28 @@ public class SecurityConfig { } @Bean - public TranslatingChannelProcessingFilter channelProcessingFilter() throws SiteConfigurationException { + public TranslatingChannelProcessingFilter channelProcessingFilter(final SiteConfigPreferences preferences) throws SiteConfigurationException { final ChannelDecisionManagerImpl decisionManager = new ChannelDecisionManagerImpl(); decisionManager.setChannelProcessors(Arrays.asList(new SecureChannelProcessor(), new InsecureChannelProcessor())); final TranslatingChannelProcessingFilter filter = new TranslatingChannelProcessingFilter(); filter.setChannelDecisionManager(decisionManager); - filter.setRequiredChannel(_configuration.getSecurityChannel()); + filter.setRequiredChannel(preferences.getSecurityChannel()); return filter; } @Bean - public AliasTokenAuthenticationProvider aliasTokenAuthenticationProvider() { - return new AliasTokenAuthenticationProvider(); + public AliasTokenAuthenticationProvider aliasTokenAuthenticationProvider(final AliasTokenService aliasTokenService, final XdatUserAuthService userAuthService) { + return new AliasTokenAuthenticationProvider(aliasTokenService, userAuthService); } @Bean - public DatabaseAuthenticationProviderConfigurator dbConfigurator() { - return new DatabaseAuthenticationProviderConfigurator(); + public DatabaseAuthenticationProviderConfigurator dbConfigurator(final XnatDatabaseUserDetailsService userDetailsService, final SiteConfigPreferences preferences) { + return new DatabaseAuthenticationProviderConfigurator(userDetailsService, preferences); } @Bean - public LdapAuthenticationProviderConfigurator ldapConfigurator() { - return new LdapAuthenticationProviderConfigurator(); + public LdapAuthenticationProviderConfigurator ldapConfigurator(final XdatUserAuthService service, final SiteConfigPreferences preferences) { + return new LdapAuthenticationProviderConfigurator(service, preferences); } @Bean @@ -163,54 +170,44 @@ public class SecurityConfig { return new AuthenticationProviderAggregator(providers, configuratorMap); } - @Bean(name = {"org.springframework.security.authenticationManager", "customAuthenticationManager"}) - public XnatProviderManager customAuthenticationManager(final AuthenticationProviderAggregator aggregator) { - return new XnatProviderManager(aggregator); + @Bean + @Primary + public XnatProviderManager customAuthenticationManager(final AuthenticationProviderAggregator aggregator, final XdatUserAuthService userAuthService, @SuppressWarnings("SpringJavaAutowiringInspection") final AnonymousAuthenticationProvider anonymousAuthenticationProvider, final DataSource dataSource) { + return new XnatProviderManager(aggregator, userAuthService, anonymousAuthenticationProvider, dataSource); } @Bean - public XnatAuthenticationFilter customAuthenticationFilter(final XnatProviderManager providerManager, - final AuthenticationSuccessHandler successHandler, - final AuthenticationFailureHandler failureHandler, - final SessionAuthenticationStrategy sas) { - final XnatAuthenticationFilter filter = new XnatAuthenticationFilter(); - filter.setAuthenticationManager(providerManager); - filter.setAuthenticationSuccessHandler(successHandler); - filter.setAuthenticationFailureHandler(failureHandler); - filter.setSessionAuthenticationStrategy(sas); - return filter; + public XnatAuthenticationFilter customAuthenticationFilter() { + return new XnatAuthenticationFilter(); } @Bean - public XnatBasicAuthenticationFilter customBasicAuthenticationFilter(final XnatProviderManager providerManager, - final AuthenticationEntryPoint entryPoint, - final SessionAuthenticationStrategy sas) { - final XnatBasicAuthenticationFilter filter = new XnatBasicAuthenticationFilter(providerManager, entryPoint); - filter.setSessionAuthenticationStrategy(sas); - return filter; + public XnatBasicAuthenticationFilter customBasicAuthenticationFilter(final AuthenticationManager authenticationManager, + final AuthenticationEntryPoint entryPoint) { + return new XnatBasicAuthenticationFilter(authenticationManager, entryPoint); } @Bean - public XnatExpiredPasswordFilter expiredPasswordFilter() { - final XnatExpiredPasswordFilter filter = new XnatExpiredPasswordFilter(); - filter.setChangePasswordPath("/app/template/XDATScreen_UpdateUser.vm"); - filter.setChangePasswordDestination("/app/action/ModifyPassword"); - filter.setLogoutDestination("/app/action/LogoutUser"); - filter.setLoginPath("/app/template/Login.vm"); - filter.setLoginDestination("/app/action/XDATLoginUser"); - filter.setInactiveAccountPath("/app/template/InactiveAccount.vm"); - filter.setInactiveAccountDestination("/app/action/XnatInactiveAccount"); - filter.setEmailVerificationPath("/app/template/VerifyEmail.vm"); - filter.setEmailVerificationDestination("/data/services/sendEmailVerification"); - return filter; + public XnatExpiredPasswordFilter expiredPasswordFilter(final SiteConfigPreferences preferences, final JdbcTemplate jdbcTemplate, final AliasTokenService aliasTokenService) { + return new XnatExpiredPasswordFilter(preferences, jdbcTemplate, aliasTokenService) {{ + setChangePasswordPath("/app/template/XDATScreen_UpdateUser.vm"); + setChangePasswordDestination("/app/action/ModifyPassword"); + setLogoutDestination("/app/action/LogoutUser"); + setLoginPath("/app/template/Login.vm"); + setLoginDestination("/app/action/XDATLoginUser"); + setInactiveAccountPath("/app/template/InactiveAccount.vm"); + setInactiveAccountDestination("/app/action/XnatInactiveAccount"); + setEmailVerificationPath("/app/template/VerifyEmail.vm"); + setEmailVerificationDestination("/data/services/sendEmailVerification"); + }}; } @Bean - public XnatInitCheckFilter xnatInitCheckFilter() throws IOException { + public XnatInitCheckFilter xnatInitCheckFilter(final SerializerService serializer, final XnatAppInfo appInfo) throws IOException { final Resource resource = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/initialization-urls.yaml"); try (final InputStream inputStream = resource.getInputStream()) { - final XnatInitCheckFilter filter = new XnatInitCheckFilter(); - final JsonNode paths = _serializer.deserializeYaml(inputStream); + final XnatInitCheckFilter filter = new XnatInitCheckFilter(appInfo); + final JsonNode paths = serializer.deserializeYaml(inputStream); filter.setConfigurationPath(paths.get("configPath").asText()); filter.setNonAdminErrorPath(paths.get("nonAdminErrorPath").asText()); filter.setInitializationPaths(nodeToList(paths.get("initPaths"))); @@ -220,10 +217,8 @@ public class SecurityConfig { } @Bean - public XnatDatabaseUserDetailsService customDatabaseService(final DataSource dataSource) { - final XnatDatabaseUserDetailsService service = new XnatDatabaseUserDetailsService(); - service.setDataSource(dataSource); - return service; + public XnatDatabaseUserDetailsService customDatabaseService(final XdatUserAuthService userAuthService, final DataSource dataSource) { + return new XnatDatabaseUserDetailsService(userAuthService, dataSource); } protected List<String> nodeToList(final JsonNode node) { @@ -244,12 +239,4 @@ public class SecurityConfig { private static final ResourceLoader RESOURCE_LOADER = new DefaultResourceLoader(); private static final TypeReference<HashMap<String, ArrayList<String>>> TYPE_REFERENCE = new TypeReference<HashMap<String, ArrayList<String>>>() { }; - - @Autowired - @Lazy - private InitializerSiteConfiguration _configuration; - - @Autowired - @Lazy - private SerializerService _serializer; } \ No newline at end of file diff --git a/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java b/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java index fd2a937e07410c87cfe5321f7ea64571731b0bb3..d29dd4aa7d3ba8f0bb7d6c57c43c699bfcee9a99 100644 --- a/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java +++ b/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java @@ -9,7 +9,6 @@ import org.nrg.framework.exceptions.NrgServiceRuntimeException; import org.nrg.framework.processors.XnatPluginBean; import org.nrg.xdat.servlet.XDATAjaxServlet; import org.nrg.xdat.servlet.XDATServlet; -import org.nrg.xnat.configuration.ApplicationConfig; import org.nrg.xnat.restlet.servlet.XNATRestletServlet; import org.nrg.xnat.restlet.util.UpdateExpirationCookie; import org.nrg.xnat.security.XnatSessionEventPublisher; @@ -76,7 +75,7 @@ public class XnatWebAppInitializer extends AbstractAnnotationConfigDispatcherSer @Override protected Class<?>[] getServletConfigClasses() { final List<Class<?>> configClasses = new ArrayList<>(); - configClasses.add(ApplicationConfig.class); + // configClasses.add(ApplicationConfig.class); configClasses.addAll(getPluginConfigs()); return configClasses.toArray(new Class[configClasses.size()]); } diff --git a/src/main/java/org/nrg/xnat/initialization/tasks/EncryptXnatPasswords.java b/src/main/java/org/nrg/xnat/initialization/tasks/EncryptXnatPasswords.java index f958eb6e0383b455e1002e09a5e1ab9c18ea071a..fbc9f06307285389fe59adca04a19ef67beb7b47 100644 --- a/src/main/java/org/nrg/xnat/initialization/tasks/EncryptXnatPasswords.java +++ b/src/main/java/org/nrg/xnat/initialization/tasks/EncryptXnatPasswords.java @@ -11,8 +11,8 @@ package org.nrg.xnat.initialization.tasks; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.security.authentication.encoding.ShaPasswordEncoder; @@ -26,6 +26,12 @@ import java.util.Map; @Component public class EncryptXnatPasswords extends AbstractInitializingTask { + @Autowired + public EncryptXnatPasswords(final JdbcTemplate template) { + super(); + _template = template; + } + @Override public String getTaskName() { return "Encrypt XNAT passwords"; @@ -51,6 +57,8 @@ public class EncryptXnatPasswords extends AbstractInitializingTask { } complete(); + } catch (BadSqlGrammarException e) { + logger.info("Unable to execute user table password encryption, maybe the table doesn't exist yet?", e); } catch (Exception e) { logger.error("", e); } @@ -80,7 +88,5 @@ public class EncryptXnatPasswords extends AbstractInitializingTask { private static Logger logger = LoggerFactory.getLogger(EncryptXnatPasswords.class); - @Autowired - @Lazy - private JdbcTemplate _template; + private final JdbcTemplate _template; } diff --git a/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWideAnonScript.java b/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWideAnonScript.java index eae59e036967b4467f0bb6efdc127aba7a740a4d..20ca2f3746db51109dae6c7d87b8e60ecf7ea600 100644 --- a/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWideAnonScript.java +++ b/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWideAnonScript.java @@ -8,11 +8,18 @@ import org.nrg.xnat.helpers.merge.AnonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import java.io.FileNotFoundException; + @Component public class GetSiteWideAnonScript extends AbstractInitializingTask { + @Autowired + public GetSiteWideAnonScript(final SiteConfigPreferences preferences) { + super(); + _preferences = preferences; + } + @Override public String getTaskName() { return "Get site-wide anon script"; @@ -25,7 +32,7 @@ public class GetSiteWideAnonScript extends AbstractInitializingTask { final Configuration initConfig = AnonUtils.getService().getScript(path, null); if (initConfig == null) { _log.info("Creating Script Table."); - final String siteWideScript = FileUtils.readFileToString(AnonUtils.getDefaultScript()); + final String siteWideScript = AnonUtils.getDefaultScript(); final String adminUser = _preferences.getReceivedFileUser(); if (adminUser != null) { AnonUtils.getService().setSiteWideScript(adminUser, path, siteWideScript); @@ -35,6 +42,8 @@ public class GetSiteWideAnonScript extends AbstractInitializingTask { } // there is a default site-wide script, so nothing to do here for the else. complete(); + } catch (FileNotFoundException e) { + _log.info("Couldn't find default anonymization script, waiting", e); } catch (Throwable e) { _log.error("Unable to either find or initialize script database", e); } @@ -42,7 +51,5 @@ public class GetSiteWideAnonScript extends AbstractInitializingTask { private static final Logger _log = LoggerFactory.getLogger(GetSiteWideAnonScript.class); - @Autowired - @Lazy - private SiteConfigPreferences _preferences; + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWidePETTracerList.java b/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWidePETTracerList.java index 4942dae0ab4b56555078b6d3c88c59f6cf9cf1c0..d2dd78680556b789ec4723949ca361b49e4d7fe5 100644 --- a/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWidePETTracerList.java +++ b/src/main/java/org/nrg/xnat/initialization/tasks/GetSiteWidePETTracerList.java @@ -1,17 +1,21 @@ package org.nrg.xnat.initialization.tasks; -import org.apache.commons.io.FileUtils; import org.nrg.config.entities.Configuration; -import org.nrg.xdat.security.helpers.Roles; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xft.security.UserI; import org.nrg.xnat.services.PETTracerUtils; +import org.nrg.xnat.utils.XnatUserProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class GetSiteWidePETTracerList extends AbstractInitializingTask { + @Autowired + public GetSiteWidePETTracerList(final XnatUserProvider primaryAdminUserProvider, final PETTracerUtils petTracerUtils) { + _adminUsername = primaryAdminUserProvider.getLogin(); + _petTracerUtils = petTracerUtils; + } + @Override public String getTaskName() { return "Get site-wide PET tracer list"; @@ -21,33 +25,19 @@ public class GetSiteWidePETTracerList extends AbstractInitializingTask { public void run() { try { final String path = PETTracerUtils.buildScriptPath(PETTracerUtils.ResourceScope.SITE_WIDE, ""); - final Configuration configuration = PETTracerUtils.getService().getTracerList(path, null); + final Configuration configuration = _petTracerUtils.getTracerList(path, null); if (configuration == null) { _log.info("Creating PET Tracer List."); - final String siteWide = FileUtils.readFileToString(PETTracerUtils.getDefaultTracerList()); - final UserI adminUser = getAdminUser(); - if (adminUser != null) { - PETTracerUtils.getService().setSiteWideTracerList(adminUser.getUsername(), path, siteWide); - } else { - throw new Exception("Site administrator not found."); - } + final String siteWide = PETTracerUtils.getDefaultTracerList(); + _petTracerUtils.setSiteWideTracerList(_adminUsername, path, siteWide); } - // there is a default site-wide tracer list, so nothing to do here for the else. - complete(); - } catch (Throwable e){ + } catch (Throwable e) { _log.error("Unable to either find or initialize the PET tracer list.", e); } } - private UserI getAdminUser() throws Exception { - for (String login : Users.getAllLogins()) { - final UserI user = Users.getUser(login); - if (Roles.isSiteAdmin(user)) { - return user; - } - } - return null; - } - private static final Logger _log = LoggerFactory.getLogger(GetSiteWidePETTracerList.class); + + private final String _adminUsername; + private final PETTracerUtils _petTracerUtils; } diff --git a/src/main/java/org/nrg/xnat/initialization/tasks/UpdateNewSecureDefinitions.java b/src/main/java/org/nrg/xnat/initialization/tasks/UpdateNewSecureDefinitions.java index 357ee715e6019d25c692eb9503536d4bf9e6505c..b05c6f06c8397cc0a900a927e7347fa5dd1c166d 100644 --- a/src/main/java/org/nrg/xnat/initialization/tasks/UpdateNewSecureDefinitions.java +++ b/src/main/java/org/nrg/xnat/initialization/tasks/UpdateNewSecureDefinitions.java @@ -5,11 +5,16 @@ import org.nrg.xdat.security.services.FeatureRepositoryServiceI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @Component public class UpdateNewSecureDefinitions extends AbstractInitializingTask { + @Autowired + public UpdateNewSecureDefinitions(final FeatureRepositoryServiceI featureRepositoryService) { + super(); + _featureRepositoryService = featureRepositoryService; + } + @Override public String getTaskName() { return "Update new secure definitions"; @@ -30,7 +35,5 @@ public class UpdateNewSecureDefinitions extends AbstractInitializingTask { private static final Logger _log = LoggerFactory.getLogger(UpdateNewSecureDefinitions.class); - @Autowired - @Lazy - private FeatureRepositoryServiceI _featureRepositoryService; + private final FeatureRepositoryServiceI _featureRepositoryService; } diff --git a/src/main/java/org/nrg/xnat/initialization/tasks/UpdateUserAuthTable.java b/src/main/java/org/nrg/xnat/initialization/tasks/UpdateUserAuthTable.java index fd4cde9032860bee69441b03b978c07baca325b4..379aef85cfae8af0b77569be5abf852ae918ba37 100644 --- a/src/main/java/org/nrg/xnat/initialization/tasks/UpdateUserAuthTable.java +++ b/src/main/java/org/nrg/xnat/initialization/tasks/UpdateUserAuthTable.java @@ -5,7 +5,7 @@ import org.nrg.xdat.services.XdatUserAuthService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; +import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.core.authority.AuthorityUtils; @@ -15,8 +15,22 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; +/** + * Adds users from /old xdat_user table to new user authentication table if they are not already there. New local + * database users now get added to both automatically, but this is necessary so that those who upgrade from an earlier + * version still have their users be able to log in. Password expiry times are also added so that pre-existing users + * still have their passwords expire. + */ +@SuppressWarnings("SqlDialectInspection") @Component public class UpdateUserAuthTable extends AbstractInitializingTask { + @Autowired + public UpdateUserAuthTable(final JdbcTemplate template, final XdatUserAuthService xdatUserAuthService) { + super(); + _template = template; + _xdatUserAuthService = xdatUserAuthService; + } + @Override public String getTaskName() { return "Update the user authentication table"; @@ -24,39 +38,34 @@ public class UpdateUserAuthTable extends AbstractInitializingTask { @Override public void run() { - /** - * Adds users from /old xdat_user table to new user authentication table if they are not already there. New local database users now get added to both automatically, but this is necessary - * so that those who upgrade from an earlier version will still have their users be able to log in. Password expiry times are also added so that pre-existing users still have their passwords expire. - */ - final List<XdatUserAuth> unmapped = _template.query("SELECT login, enabled FROM xdat_user WHERE login NOT IN (SELECT xdat_username FROM xhbm_xdat_user_auth)", new RowMapper<XdatUserAuth>() { - @Override - public XdatUserAuth mapRow(final ResultSet resultSet, final int i) throws SQLException { - final String login = resultSet.getString("login"); - final boolean enabled = resultSet.getInt("enabled") == 1; + try { + final List<XdatUserAuth> unmapped = _template.query("SELECT login, enabled FROM xdat_user WHERE login NOT IN (SELECT xdat_username FROM xhbm_xdat_user_auth)", new RowMapper<XdatUserAuth>() { + @Override + public XdatUserAuth mapRow(final ResultSet resultSet, final int i) throws SQLException { + final String login = resultSet.getString("login"); + final boolean enabled = resultSet.getInt("enabled") == 1; + if (_log.isDebugEnabled()) { + _log.debug("Creating new user auth object for user {}, authentication is {}", login, enabled ? "enabled" : "disabled"); + } + return new XdatUserAuth(login, XdatUserAuthService.LOCALDB, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, login, 0); + } + }); + for (XdatUserAuth userAuth : unmapped) { if (_log.isDebugEnabled()) { - _log.debug("Creating new user auth object for user {}, authentication is {}", login, enabled ? "enabled" : "disabled"); + _log.debug("Persisting user auth object for user {}", userAuth.getXdatUsername()); } - return new XdatUserAuth(login, XdatUserAuthService.LOCALDB, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, login, 0); + _xdatUserAuthService.create(userAuth); } - }); - for (XdatUserAuth userAuth : unmapped) { - if (_log.isDebugEnabled()) { - _log.debug("Persisting user auth object for user {}", userAuth.getXdatUsername()); - } - _xdatUserAuthService.create(userAuth); + _log.debug("Updating the user auth table to set password updated to the current time for local users"); + _template.execute("UPDATE xhbm_xdat_user_auth SET password_updated=current_timestamp WHERE auth_method='" + XdatUserAuthService.LOCALDB + "' AND password_updated IS NULL"); + complete(); + } catch (BadSqlGrammarException e) { + _log.info("Unable to execute user auth table update, maybe the table doesn't exist yet?", e); } - _log.debug("Updating the user auth table to set password updated to the current time for local users"); - _template.execute("UPDATE xhbm_xdat_user_auth SET password_updated=current_timestamp WHERE auth_method='" + XdatUserAuthService.LOCALDB + "' AND password_updated IS NULL"); - complete(); } private static final Logger _log = LoggerFactory.getLogger(UpdateUserAuthTable.class); - @Autowired - @Lazy - private JdbcTemplate _template; - - @Autowired - @Lazy - private XdatUserAuthService _xdatUserAuthService; + private final JdbcTemplate _template; + private final XdatUserAuthService _xdatUserAuthService; } diff --git a/src/main/java/org/nrg/xnat/restlet/actions/AutomationBasedImporter.java b/src/main/java/org/nrg/xnat/restlet/actions/AutomationBasedImporter.java index 666cf9758688e3893d9302194d1953dc16991601..6f3064a81a3e48998077d67a1745bc99fd5abb8e 100644 --- a/src/main/java/org/nrg/xnat/restlet/actions/AutomationBasedImporter.java +++ b/src/main/java/org/nrg/xnat/restlet/actions/AutomationBasedImporter.java @@ -653,7 +653,7 @@ public class AutomationBasedImporter extends ImporterHandlerA implements Callabl return; } eventService.triggerEvent(automationEvent, automationCompletionEvent); - final AutomationCompletionEventListener completionService = AutomationCompletionEventListener.getService(); + final AutomationCompletionEventListener completionService = XDAT.getContextService().getBeanSafely(AutomationCompletionEventListener.class); List<ScriptOutput> scriptOutputs = null; for (int i = 1; i < TIMEOUT_SECONDS; i++) { try { @@ -795,8 +795,7 @@ public class AutomationBasedImporter extends ImporterHandlerA implements Callabl // Do we need to handle scope differently? I don't think site configured uploads will pass through this method. // It's really only for configured resources, which should always be scoped at the project level, I think. final Scope scope = (exp != null) ? Scope.Project : (subj != null) ? Scope.Project : (proj != null ) ? Scope.Project : Scope.Site; - final String crConfig = XDAT.getConfigService().getConfigContents(CONFIG_TOOL, CONFIG_SCRIPT_PATH, scope, - proj.getId()); + final String crConfig = XDAT.getConfigService().getConfigContents(CONFIG_TOOL, CONFIG_SCRIPT_PATH, scope, proj.getId()); if (crConfig != null && crConfig.length() > 0) { try { final JSONArray jsonArray = new JSONArray(new JSONTokener(crConfig)); diff --git a/src/main/java/org/nrg/xnat/restlet/servlet/XNATRestletServlet.java b/src/main/java/org/nrg/xnat/restlet/servlet/XNATRestletServlet.java index 743892dc91173fb0e8e7aee4ccf61d594bad420a..fae852c24a6b9ba061152233ae80d22277197f0e 100644 --- a/src/main/java/org/nrg/xnat/restlet/servlet/XNATRestletServlet.java +++ b/src/main/java/org/nrg/xnat/restlet/servlet/XNATRestletServlet.java @@ -24,7 +24,7 @@ import javax.servlet.ServletException; public class XNATRestletServlet extends ServerServlet { private static final long serialVersionUID = -4149339105144231596L; - public static ServletConfig REST_CONFIG=null; + public static ServletConfig REST_CONFIG = null; private final Logger logger = LoggerFactory.getLogger(XNATRestletServlet.class); @@ -32,13 +32,17 @@ public class XNATRestletServlet extends ServerServlet { public void init() throws ServletException { super.init(); - XNATRestletServlet.REST_CONFIG=this.getServletConfig(); - - PrearcConfig prearcConfig = XDAT.getContextService().getBean(PrearcConfig.class); - try { - PrearcDatabase.initDatabase(prearcConfig.isReloadPrearcDatabaseOnApplicationStartup()); - } catch (Throwable e) { - logger.error("Unable to initialize prearchive database", e); + XNATRestletServlet.REST_CONFIG = getServletConfig(); + + final PrearcConfig prearcConfig = XDAT.getContextService().getBean(PrearcConfig.class); + if (prearcConfig != null) { + try { + PrearcDatabase.initDatabase(prearcConfig.isReloadPrearcDatabaseOnApplicationStartup()); + } catch (Throwable e) { + logger.error("Unable to initialize prearchive database", e); + } + } else { + logger.error("The prearc config wasn't found!"); } XDAT.getContextService().getBean(DicomSCPManager.class).startOrStopDicomSCPAsDictatedByConfiguration(); diff --git a/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java b/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java index 78b409aa70018a31fbd1c5bb45646f710d607ca5..2144dae6ecb6583b0a74eea5418cb7b39bb89127 100644 --- a/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java +++ b/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java @@ -12,8 +12,9 @@ package org.nrg.xnat.security; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; @@ -24,13 +25,17 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; -import javax.inject.Inject; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProcessor { + @Autowired + public FilterSecurityInterceptorBeanPostProcessor(final SiteConfigPreferences preferences) { + _preferences = preferences; + } + public void setOpenUrls(List<String> openUrls) { _openUrls.clear(); _openUrls.addAll(openUrls); @@ -48,8 +53,8 @@ public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProce } if (bean instanceof FilterSecurityInterceptor) { - FilterSecurityInterceptor interceptor = (FilterSecurityInterceptor) bean; - final ExpressionBasedFilterInvocationSecurityMetadataSource metadataSource = getMetadataSource(_service.getRequireLogin()); + final FilterSecurityInterceptor interceptor = (FilterSecurityInterceptor) bean; + final ExpressionBasedFilterInvocationSecurityMetadataSource metadataSource = getMetadataSource(_preferences.getRequireLogin()); if (_log.isDebugEnabled()) { _log.debug("Found a FilterSecurityInterceptor bean with the following metadata configuration:"); displayMetadataSource(interceptor.getSecurityMetadataSource()); @@ -109,8 +114,7 @@ public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProce private static final String ADMIN_EXPRESSION = "hasRole('ROLE_ADMIN')"; private static final String DEFAULT_EXPRESSION = "hasRole('ROLE_USER')"; - @Inject - private InitializerSiteConfiguration _service; + private final SiteConfigPreferences _preferences; private final List<String> _openUrls = new ArrayList<>(); private final List<String> _adminUrls = new ArrayList<>(); diff --git a/src/main/java/org/nrg/xnat/security/XnatAuthenticationEntryPoint.java b/src/main/java/org/nrg/xnat/security/XnatAuthenticationEntryPoint.java index 1c40b2b9f1aa27bff5000df7a4b61f55e6943f8b..ee237117ae2b0bcae2a0fa77a565637ba74b2973 100644 --- a/src/main/java/org/nrg/xnat/security/XnatAuthenticationEntryPoint.java +++ b/src/main/java/org/nrg/xnat/security/XnatAuthenticationEntryPoint.java @@ -13,8 +13,7 @@ package org.nrg.xnat.security; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nrg.config.exceptions.SiteConfigurationException; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -30,9 +29,9 @@ import java.util.regex.Pattern; public class XnatAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { - public XnatAuthenticationEntryPoint(final String loginFormUrl, final InitializerSiteConfiguration configuration) { + public XnatAuthenticationEntryPoint(final String loginFormUrl, final SiteConfigPreferences preferences) { super(loginFormUrl); - _configuration = configuration; + _preferences = preferences; } /** @@ -70,14 +69,8 @@ public class XnatAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoi } if (isDataPath(request) && !isInteractiveAgent(userAgent)) { - try { - response.setHeader("WWW-Authenticate", "Basic realm=\"" + _configuration.getSiteId() + "\""); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - } catch (SiteConfigurationException e) { - _log.error("An error occurred trying to access system resources: siteId", e); - response.setHeader("WWW-Authenticate", "Basic"); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - } + response.setHeader("WWW-Authenticate", "Basic realm=\"" + _preferences.getSiteId() + "\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } else { super.commence(request, response, authException); } @@ -156,7 +149,7 @@ public class XnatAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoi return false; } - private final InitializerSiteConfiguration _configuration; + private final SiteConfigPreferences _preferences; private static final Log _log = LogFactory.getLog(XnatAuthenticationEntryPoint.class); diff --git a/src/main/java/org/nrg/xnat/security/XnatAuthenticationFilter.java b/src/main/java/org/nrg/xnat/security/XnatAuthenticationFilter.java index dad3fd4f943d0b9ccfcc879b888f5c84b250a0e6..0809c5625101f856ef056cd908b32f33f762b7aa 100644 --- a/src/main/java/org/nrg/xnat/security/XnatAuthenticationFilter.java +++ b/src/main/java/org/nrg/xnat/security/XnatAuthenticationFilter.java @@ -19,21 +19,52 @@ import org.nrg.xdat.turbine.utils.AccessLogger; import org.nrg.xft.XFTItem; import org.nrg.xft.event.EventMetaI; import org.nrg.xft.utils.SaveItemHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; -import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; import java.util.Calendar; import java.util.Map; -public class XnatAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ +public class XnatAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + @Autowired + public void setAuthenticationManager(final AuthenticationManager authenticationManager) { + super.setAuthenticationManager(authenticationManager); + } + + @Autowired + public void setXnatProviderManager(final XnatProviderManager providerManager) { + _providerManager = providerManager; + } + + @Autowired + @Override + public void setAuthenticationSuccessHandler(final AuthenticationSuccessHandler handler) { + super.setAuthenticationSuccessHandler(handler); + } + + @Autowired + @Override + public void setAuthenticationFailureHandler(final AuthenticationFailureHandler handler) { + super.setAuthenticationFailureHandler(handler); + } + + @Autowired + @Override + public void setSessionAuthenticationStrategy(final SessionAuthenticationStrategy strategy) { + super.setSessionAuthenticationStrategy(strategy); + } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { @@ -43,17 +74,16 @@ public class XnatAuthenticationFilter extends UsernamePasswordAuthenticationFilt // If we didn't find a username if (StringUtils.isBlank(username)) { // See if there's an authorization header. - String header = request.getHeader("Authorization"); + final String header = request.getHeader("Authorization"); if (!StringUtils.isBlank(header) && header.startsWith("Basic ")) { - byte[] base64Token; try { - base64Token = header.substring(6).getBytes("UTF-8"); - String token = new String(Base64.decode(base64Token), "UTF-8"); - int delim = token.indexOf(":"); + final byte[] base64Token = header.substring(6).getBytes("UTF-8"); + final String token = new String(Base64.decode(base64Token), "UTF-8"); + final int position = token.indexOf(":"); - if (delim != -1) { - username = token.substring(0, delim); - password = token.substring(delim + 1); + if (position != -1) { + username = token.substring(0, position); + password = token.substring(position + 1); } if (_log.isDebugEnabled()) { _log.debug("Basic Authentication Authorization header found for user '" + username + "'"); @@ -66,73 +96,69 @@ public class XnatAuthenticationFilter extends UsernamePasswordAuthenticationFilt //SHOULD we be throwing an exception if the username is null? - String providerName=request.getParameter("login_method"); - UsernamePasswordAuthenticationToken authRequest; + final String providerName = request.getParameter("login_method"); + final UsernamePasswordAuthenticationToken authRequest; - if(StringUtils.isEmpty(providerName) && !StringUtils.isEmpty(username)){ - //try to guess the auth_method - String auth_method = _providerManager.retrieveAuthMethod(username); - if(StringUtils.isEmpty(auth_method)){ + if (StringUtils.isEmpty(providerName) && !StringUtils.isEmpty(username)) { + // Try to guess the auth method + final String authMethod = _providerManager.retrieveAuthMethod(username); + if (StringUtils.isEmpty(authMethod)) { throw new BadCredentialsException("Missing login_method parameter."); + } else { + authRequest = _providerManager.buildUPTokenForAuthMethod(authMethod, username, password); } - else { - authRequest=_providerManager.buildUPTokenForAuthMethod(auth_method,username,password); - } - } - else { - authRequest=_providerManager.buildUPTokenForProviderName(providerName,username,password); + } else { + authRequest = _providerManager.buildUPTokenForProviderName(providerName, username, password); } setDetails(request, authRequest); try { - Authentication auth= super.getAuthenticationManager().authenticate(authRequest); - AccessLogger.LogServiceAccess(username, AccessLogger.GetRequestIp(request), "Authentication", "SUCCESS"); - return auth; - } catch (AuthenticationException e) { - logFailedAttempt(username, request); - throw e; - } + AccessLogger.LogServiceAccess(username, AccessLogger.GetRequestIp(request), "Authentication", "SUCCESS"); + return getAuthenticationManager().authenticate(authRequest); + } catch (AuthenticationException e) { + logFailedAttempt(username, request); + throw e; + } } - public static void logFailedAttempt(String username, HttpServletRequest req){ - if (!StringUtils.isBlank(username)) { - Integer uid=retrieveUserId(username); - if(uid!=null){ - try { - XFTItem item = XFTItem.NewItem("xdat:user_login",null); - item.setProperty("xdat:user_login.user_xdat_user_id",uid); - item.setProperty("xdat:user_login.ip_address",AccessLogger.GetRequestIp(req)); + public static void logFailedAttempt(String username, HttpServletRequest req) { + if (!StringUtils.isBlank(username)) { + final Integer uid = retrieveUserId(username); + if (uid != null) { + try { + XFTItem item = XFTItem.NewItem("xdat:user_login", null); + item.setProperty("xdat:user_login.user_xdat_user_id", uid); + item.setProperty("xdat:user_login.ip_address", AccessLogger.GetRequestIp(req)); item.setProperty("xdat:user_login.login_date", Calendar.getInstance(java.util.TimeZone.getDefault()).getTime()); - SaveItemHelper.authorizedSave(item,null,true,false,(EventMetaI)null); + SaveItemHelper.authorizedSave(item, null, true, false, (EventMetaI) null); } catch (Exception exception) { _log.error(exception); - } - } - AccessLogger.LogServiceAccess(username, AccessLogger.GetRequestIp(req), "Authentication", "FAILED"); - } + } + } + AccessLogger.LogServiceAccess(username, AccessLogger.GetRequestIp(req), "Authentication", "FAILED"); + } } - - public static Integer retrieveUserId(String username){ - synchronized(checked){ - if(username==null){ - return null; - } - - if(checked.containsKey(username)){ - return checked.get(username); - } - - Integer i=Users.getUserid(username); - checked.put(username, i); - - return i; - } + + public static Integer retrieveUserId(String username) { + synchronized (checked) { + if (username == null) { + return null; + } + + if (checked.containsKey(username)) { + return checked.get(username); + } + + final Integer i = Users.getUserid(username); + checked.put(username, i); + + return i; + } } - - private static final Log _log = LogFactory.getLog(XnatAuthenticationFilter.class); + + private static final Log _log = LogFactory.getLog(XnatAuthenticationFilter.class); private static final Map<String, Integer> checked = Maps.newHashMap(); - @Inject private XnatProviderManager _providerManager; } diff --git a/src/main/java/org/nrg/xnat/security/XnatBasicAuthenticationFilter.java b/src/main/java/org/nrg/xnat/security/XnatBasicAuthenticationFilter.java index 21d71b33f900ad461a2895a80fe913647924d661..49340a9e7471ef311fadb178ebe4dcec96648f4c 100644 --- a/src/main/java/org/nrg/xnat/security/XnatBasicAuthenticationFilter.java +++ b/src/main/java/org/nrg/xnat/security/XnatBasicAuthenticationFilter.java @@ -19,8 +19,8 @@ import org.nrg.xft.XFTItem; import org.nrg.xft.event.EventUtils; import org.nrg.xft.security.UserI; import org.nrg.xft.utils.SaveItemHelper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -29,11 +29,9 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import javax.inject.Inject; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -44,19 +42,24 @@ import java.util.Date; import java.util.Map; public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { + @Autowired + public XnatBasicAuthenticationFilter(final AuthenticationManager manager, final AuthenticationEntryPoint entryPoint) { + super(manager, entryPoint); + _authenticationDetailsSource = new WebAuthenticationDetailsSource(); + } - @Inject - private XnatProviderManager _providerManager; - - private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); - private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy(); + @Autowired + public void setXnatProviderManager(final XnatProviderManager providerManager) { + _providerManager = providerManager; + } - public XnatBasicAuthenticationFilter(AuthenticationManager manager, AuthenticationEntryPoint entryPoint) { - super(manager, entryPoint); + @Autowired + public void setSessionAuthenticationStrategy(final SessionAuthenticationStrategy strategy) { + _authenticationStrategy = strategy; } private boolean authenticationIsRequired(String username) { - // Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated + // Only re-authenticate if username doesn't match SecurityContextHolder and user isn't authenticated // (see SEC-53) Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); @@ -74,7 +77,7 @@ public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { // Handle unusual condition where an AnonymousAuthenticationToken is already present // This shouldn't happen very often, as BasicProcessingFilter is meant to be earlier in the filter // chain than AnonymousAuthenticationFilter. Nevertheless, presence of both an AnonymousAuthenticationToken - // together with a BASIC authentication request header should indicate reauthentication using the + // together with a BASIC authentication request header should indicate re-authentication using the // BASIC protocol is desirable. This behaviour is also consistent with that provided by form and digest, // both of which force re-authentication if the respective header is detected (and in doing so replace // any existing AnonymousAuthenticationToken). See SEC-610. @@ -89,15 +92,15 @@ public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { if ((header != null) && header.startsWith("Basic ")) { byte[] base64Token = header.substring(6).getBytes("UTF-8"); - String token = new String(Base64.decode(base64Token), getCredentialsCharset(request)); + String token = new String(Base64.decode(base64Token), getCredentialsCharset(request)); String username = ""; String password = ""; - int delim = token.indexOf(":"); + int position = token.indexOf(":"); - if (delim != -1) { - username = token.substring(0, delim); - password = token.substring(delim + 1); + if (position != -1) { + username = token.substring(0, position); + password = token.substring(position + 1); } if (debug) { @@ -105,16 +108,15 @@ public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { } if (authenticationIsRequired(username)) { - UsernamePasswordAuthenticationToken authRequest = - _providerManager.buildUPTokenForAuthMethod(_providerManager.retrieveAuthMethod(username), username, password); - authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + UsernamePasswordAuthenticationToken authRequest = _providerManager.buildUPTokenForAuthMethod(_providerManager.retrieveAuthMethod(username), username, password); + authRequest.setDetails(_authenticationDetailsSource.buildDetails(request)); Authentication authResult; try { authResult = getAuthenticationManager().authenticate(authRequest); - sessionStrategy.onAuthentication(authResult, request, response); + _authenticationStrategy.onAuthentication(authResult, request, response); } catch (AuthenticationException failed) { @@ -160,9 +162,10 @@ public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { lock = locks.get(user.getID()); } + //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (lock) { - Date today = Calendar.getInstance(java.util.TimeZone.getDefault()).getTime(); - XFTItem item = XFTItem.NewItem("xdat:user_login", user); + Date today = Calendar.getInstance(java.util.TimeZone.getDefault()).getTime(); + XFTItem item = XFTItem.NewItem("xdat:user_login", user); item.setProperty("xdat:user_login.user_xdat_user_id", user.getID()); item.setProperty("xdat:user_login.login_date", today); item.setProperty("xdat:user_login.ip_address", AccessLogger.GetRequestIp(request)); @@ -178,14 +181,7 @@ public class XnatBasicAuthenticationFilter extends BasicAuthenticationFilter { super.onSuccessfulAuthentication(request, response, authResult); } - /** - * The session handling strategy which will be invoked immediately after an authentication request is successfully - * processed by the <tt>AuthenticationManager</tt>. Used, for example, to handle changing of the session identifier - * to prevent session fixation attacks. - * - * @param sessionStrategy the implementation to use. If not set a null implementation is used. - */ - public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionStrategy) { - this.sessionStrategy = sessionStrategy; - } + private final WebAuthenticationDetailsSource _authenticationDetailsSource; + private XnatProviderManager _providerManager; + private SessionAuthenticationStrategy _authenticationStrategy; } diff --git a/src/main/java/org/nrg/xnat/security/XnatExpiredPasswordFilter.java b/src/main/java/org/nrg/xnat/security/XnatExpiredPasswordFilter.java index e6be0dbdef9544ab1f999892726e515a0ace8227..3db8387c66b81d8981b5a66a267c6f707b1e93d6 100644 --- a/src/main/java/org/nrg/xnat/security/XnatExpiredPasswordFilter.java +++ b/src/main/java/org/nrg/xnat/security/XnatExpiredPasswordFilter.java @@ -12,12 +12,12 @@ package org.nrg.xnat.security; import org.apache.commons.lang3.StringUtils; import org.nrg.config.exceptions.SiteConfigurationException; -import org.nrg.framework.services.ContextService; +import org.nrg.framework.exceptions.NrgServiceError; import org.nrg.xdat.XDAT; import org.nrg.xdat.entities.AliasToken; import org.nrg.xdat.entities.UserRole; import org.nrg.xdat.om.ArcArchivespecification; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.security.helpers.Roles; import org.nrg.xdat.services.AliasTokenService; import org.nrg.xdat.services.XdatUserAuthService; @@ -25,58 +25,50 @@ import org.nrg.xdat.turbine.utils.TurbineUtils; import org.nrg.xft.security.UserI; import org.nrg.xnat.turbine.utils.ArcSpecManager; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.crypto.codec.Base64; import org.springframework.web.filter.GenericFilterBean; -import javax.inject.Inject; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.sql.DataSource; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.sql.ResultSet; import java.sql.SQLException; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; @SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"}) public class XnatExpiredPasswordFilter extends GenericFilterBean { - private String changePasswordPath = ""; - private String changePasswordDestination = ""; - private String logoutDestination = ""; - private String loginPath = ""; - private String loginDestination = ""; - private String inactiveAccountPath; - private String inactiveAccountDestination; - private String emailVerificationDestination; - private String emailVerificationPath; - private boolean passwordExpirationDirtied = true; - private boolean passwordExpirationDisabled; - private boolean passwordExpirationInterval; - private String passwordExpirationSetting; + @Autowired + public XnatExpiredPasswordFilter(final SiteConfigPreferences preferences, final JdbcTemplate jdbcTemplate, final AliasTokenService aliasTokenService) { + super(); + _preferences = preferences; + _aliasTokenService = aliasTokenService; + _jdbcTemplate = jdbcTemplate; + } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { - final HttpServletRequest request = (HttpServletRequest) req; - final HttpServletResponse response = (HttpServletResponse) res; - UserI user = XDAT.getUserDetails(); - Object passwordExpired = request.getSession().getAttribute("expired"); + final HttpServletRequest request = (HttpServletRequest) req; + final HttpServletResponse response = (HttpServletResponse) res; + UserI user = XDAT.getUserDetails(); + Object passwordExpired = request.getSession().getAttribute("expired"); // MIGRATION: Need to remove arcspec. ArcArchivespecification _arcSpec = ArcSpecManager.GetInstance(); - final String referer = request.getHeader("Referer"); + final String referer = request.getHeader("Referer"); if (request.getSession() != null && request.getSession().getAttribute("forcePasswordChange") != null && (Boolean) request.getSession().getAttribute("forcePasswordChange")) { try { String refererPath = null; - String uri = new URI(request.getRequestURI()).getPath(); + String uri = new URI(request.getRequestURI()).getPath(); if (!StringUtils.isBlank(referer)) { refererPath = new URI(referer).getPath(); } @@ -106,14 +98,14 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { if (header != null && header.startsWith("Basic ")) { //For users that authenticated using basic authentication, check whether their password is expired, and if so give them a 403 and a message that they need to change their password. - String token = new String(Base64.decode(header.substring(6).getBytes("UTF-8")), "UTF-8"); + String token = new String(Base64.decode(header.substring(6).getBytes("UTF-8")), "UTF-8"); String username = ""; - int delim = token.indexOf(":"); + int delim = token.indexOf(":"); if (delim != -1) { username = token.substring(0, delim); } if (AliasToken.isAliasFormat(username)) { - AliasToken alias = getAliasTokenService().locateToken(username); + AliasToken alias = _aliasTokenService.locateToken(username); if (alias == null) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "Your security token has expired. Please try again after updating your session."); return; @@ -122,7 +114,7 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { } // Check whether the user is connected to an active role for non_expiring. try { - List<Integer> roles = (new JdbcTemplate(_dataSource)).query("SELECT COUNT(*) FROM xhbm_user_role where username = ? and role = ? and enabled = 't'", new String[] {username, UserRole.ROLE_NON_EXPIRING}, new RowMapper<Integer>() { + List<Integer> roles = _jdbcTemplate.query("SELECT COUNT(*) FROM xhbm_user_role where username = ? and role = ? and enabled = 't'", new String[]{username, UserRole.ROLE_NON_EXPIRING}, new RowMapper<Integer>() { public Integer mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getInt(1); } @@ -183,7 +175,7 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { chain.doFilter(req, res); } else if (user.isEnabled()) { boolean isExpired = checkForExpiredPassword(user); - boolean requireSalted = useSiteConfigPrefs? XDAT.getSiteConfigPreferences().getRequireSaltedPasswords() : _initializerPreferences.getRequireSaltedPasswords(); + boolean requireSalted = useSiteConfigPrefs ? _preferences.getRequireSaltedPasswords() : _preferences.getRequireSaltedPasswords(); if ((!isUserNonExpiring(user) && isExpired) || (requireSalted && user.getSalt() == null)) { request.getSession().setAttribute("expired", isExpired); response.sendRedirect(TurbineUtils.GetFullServerPath() + changePasswordPath); @@ -254,6 +246,11 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { this.passwordExpirationDirtied = passwordExpirationDirtied; } + public void refreshFromSiteConfig() { + useSiteConfigPrefs = true; + passwordExpirationDirtied = true; + } + private boolean checkForExpiredPassword(final UserI user) { return checkForExpiredPassword(user.getUsername()); } @@ -264,14 +261,14 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { return false; } if (isPasswordExpirationInterval()) { - List<Boolean> expired = (new JdbcTemplate(_dataSource)).query("SELECT ((now()-password_updated)> (Interval '" + passwordExpirationSetting + "')) AS expired FROM xhbm_xdat_user_auth WHERE auth_user = ? AND auth_method = 'localdb'", new String[] {username}, new RowMapper<Boolean>() { + List<Boolean> expired = _jdbcTemplate.query("SELECT ((now()-password_updated)> (Interval '" + passwordExpirationSetting + "')) AS expired FROM xhbm_xdat_user_auth WHERE auth_user = ? AND auth_method = 'localdb'", new String[]{username}, new RowMapper<Boolean>() { public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getBoolean(1); } }); return expired.get(0); } else { - List<Boolean> expired = (new JdbcTemplate(_dataSource)).query("SELECT (to_date('" + new SimpleDateFormat("MM/dd/yyyy").format(new Date(Long.parseLong(passwordExpirationSetting))) + "', 'MM/DD/YYYY') BETWEEN password_updated AND now()) AS expired FROM xhbm_xdat_user_auth WHERE auth_user = ? AND auth_method = 'localdb'", new String[] {username}, new RowMapper<Boolean>() { + List<Boolean> expired = _jdbcTemplate.query("SELECT (to_date('" + new SimpleDateFormat("MM/dd/yyyy").format(new Date(Long.parseLong(passwordExpirationSetting))) + "', 'MM/DD/YYYY') BETWEEN password_updated AND now()) AS expired FROM xhbm_xdat_user_auth WHERE auth_user = ? AND auth_method = 'localdb'", new String[]{username}, new RowMapper<Boolean>() { public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getBoolean(1); } @@ -288,34 +285,33 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { if (!passwordExpirationDirtied) { return passwordExpirationDisabled; } - if(useSiteConfigPrefs){ - final String type = XDAT.getSiteConfigPreferences().getPasswordExpirationType(); + if (useSiteConfigPrefs) { + final String type = _preferences.getPasswordExpirationType(); if (StringUtils.isBlank(type)) { passwordExpirationDisabled = true; } else if (type.equals("Interval")) { passwordExpirationInterval = true; - passwordExpirationSetting = XDAT.getSiteConfigPreferences().getPasswordExpirationInterval(); + passwordExpirationSetting = _preferences.getPasswordExpirationInterval(); passwordExpirationDisabled = passwordExpirationSetting.equals("0"); } else if (type.equals("Date")) { passwordExpirationInterval = false; - passwordExpirationSetting = Long.toString((new Date(XDAT.getSiteConfigPreferences().getPasswordExpirationDate())).getTime()); + passwordExpirationSetting = convertDateToLongString(_preferences.getPasswordExpirationDate()); passwordExpirationDisabled = passwordExpirationSetting.equals("0"); } else { passwordExpirationDisabled = true; } - } - else{ - final String type = _initializerPreferences.getPasswordExpirationType(); + } else { + final String type = _preferences.getPasswordExpirationType(); if (StringUtils.isBlank(type)) { passwordExpirationDisabled = true; } else if (type.equals("Interval")) { passwordExpirationInterval = true; - passwordExpirationSetting = _initializerPreferences.getPasswordExpirationInterval(); - passwordExpirationDisabled = StringUtils.equals(passwordExpirationSetting,"0"); + passwordExpirationSetting = _preferences.getPasswordExpirationInterval(); + passwordExpirationDisabled = StringUtils.equals(passwordExpirationSetting, "0"); } else if (type.equals("Date")) { passwordExpirationInterval = false; - passwordExpirationSetting = Long.toString((new Date(_initializerPreferences.getPasswordExpirationDate())).getTime()); - passwordExpirationDisabled = StringUtils.equals(passwordExpirationSetting,"0"); + passwordExpirationSetting = convertDateToLongString(_preferences.getPasswordExpirationDate()); + passwordExpirationDisabled = StringUtils.equals(passwordExpirationSetting, "0"); } else { passwordExpirationDisabled = true; } @@ -325,6 +321,14 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { return passwordExpirationDisabled; } + private String convertDateToLongString(final String date) throws SiteConfigurationException { + try { + return Long.toString(FORMATTER.parse(date).getTime()); + } catch (ParseException e) { + throw new SiteConfigurationException(NrgServiceError.ConfigurationError, "The password expiration date \"" + date + "\" is in an invalid format. This should use the format: " + FORMATTER.toString(), e); + } + } + private boolean isPasswordExpirationInterval() { return passwordExpirationInterval; } @@ -347,32 +351,25 @@ public class XnatExpiredPasswordFilter extends GenericFilterBean { } } - // We have to do this because the filter must be created in the root context, but the token service must be created - // in the application context. We use the context service to cheat across these boundaries. - private AliasTokenService getAliasTokenService() { - if (_aliasTokenService == null) { - _aliasTokenService = _contextService.getBean(AliasTokenService.class); - } - return _aliasTokenService; - } - - public void refreshFromSiteConfig(){ - useSiteConfigPrefs = true; - passwordExpirationDirtied = true; - } + private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a"); private boolean useSiteConfigPrefs = false; - @Autowired - @Lazy - private InitializerSiteConfiguration _initializerPreferences; - - @Autowired - @Lazy - private ContextService _contextService; - - @Inject - private DataSource _dataSource; + private String changePasswordPath = ""; + private String changePasswordDestination = ""; + private String logoutDestination = ""; + private String loginPath = ""; + private String loginDestination = ""; + private String inactiveAccountPath; + private String inactiveAccountDestination; + private String emailVerificationDestination; + private String emailVerificationPath; + private boolean passwordExpirationDirtied = true; + private boolean passwordExpirationDisabled; + private boolean passwordExpirationInterval; + private String passwordExpirationSetting; - private AliasTokenService _aliasTokenService; + private final SiteConfigPreferences _preferences; + private final JdbcTemplate _jdbcTemplate; + private final AliasTokenService _aliasTokenService; } diff --git a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java index 034c36c51d915a38c084bc2f138d06f2752482ac..8bc71dca80b2a2d09e5efa09a1de514e967a4de8 100644 --- a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java +++ b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java @@ -17,9 +17,9 @@ import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.utils.XnatHttpUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.filter.GenericFilterBean; -import javax.inject.Inject; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -32,6 +32,11 @@ import java.util.List; import java.util.regex.Pattern; public class XnatInitCheckFilter extends GenericFilterBean { + @Autowired + public XnatInitCheckFilter(final XnatAppInfo appInfo) { + super(); + _appInfo = appInfo; + } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { @@ -136,8 +141,7 @@ public class XnatInitCheckFilter extends GenericFilterBean { private static Logger _log = LoggerFactory.getLogger(XnatInitCheckFilter.class); - @Inject - private XnatAppInfo _appInfo; + private final XnatAppInfo _appInfo; private String _configurationPath; private String _nonAdminErrorPath; diff --git a/src/main/java/org/nrg/xnat/security/XnatLdapContextMapper.java b/src/main/java/org/nrg/xnat/security/XnatLdapContextMapper.java index 73ab1f2855f3e8335a0d45332a6f24fa81fe5d1a..7ff5be8e9b3c1d70bba730205571e8d0d30e9fee 100644 --- a/src/main/java/org/nrg/xnat/security/XnatLdapContextMapper.java +++ b/src/main/java/org/nrg/xnat/security/XnatLdapContextMapper.java @@ -17,18 +17,17 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.ldap.userdetails.UserDetailsContextMapper; -import javax.inject.Inject; import java.util.Collection; public class XnatLdapContextMapper implements UserDetailsContextMapper { - public XnatLdapContextMapper() { - super(); - _authMethodId = ""; + public XnatLdapContextMapper(final XdatUserAuthService service) { + this(service, ""); } - public XnatLdapContextMapper(String authMethodId) { + public XnatLdapContextMapper(final XdatUserAuthService service, final String authMethodId) { super(); + _service = service; _authMethodId = authMethodId; } @@ -43,8 +42,7 @@ public class XnatLdapContextMapper implements UserDetailsContextMapper { throw new UnsupportedOperationException("LdapUserDetailsMapper only supports reading from a context."); } - @Inject - private XdatUserAuthService _service; + private final XdatUserAuthService _service; private final String _authMethodId; } \ No newline at end of file diff --git a/src/main/java/org/nrg/xnat/security/XnatLogoutHandler.java b/src/main/java/org/nrg/xnat/security/XnatLogoutHandler.java index e51fd586287fd1ada6cb97326ef3f8f00e5fa475..a5a86af44191de4207e86064ff50fedb6b0e5b46 100644 --- a/src/main/java/org/nrg/xnat/security/XnatLogoutHandler.java +++ b/src/main/java/org/nrg/xnat/security/XnatLogoutHandler.java @@ -10,17 +10,23 @@ */ package org.nrg.xnat.security; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class XnatLogoutHandler extends SecurityContextLogoutHandler implements LogoutHandler { + @Autowired + public XnatLogoutHandler(final SessionRegistry registry) { + super(); + _registry = registry; + } + @Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { super.logout(request, response, authentication); @@ -35,7 +41,6 @@ public class XnatLogoutHandler extends SecurityContextLogoutHandler implements L } - @Inject - private SessionRegistry _registry; + private final SessionRegistry _registry; } diff --git a/src/main/java/org/nrg/xnat/security/XnatProviderManager.java b/src/main/java/org/nrg/xnat/security/XnatProviderManager.java index faca2363f135c38f9beed5c69d82ed3d441bb643..3ca88bb0b39ac9d2a477374650ede4125e795d39 100644 --- a/src/main/java/org/nrg/xnat/security/XnatProviderManager.java +++ b/src/main/java/org/nrg/xnat/security/XnatProviderManager.java @@ -18,12 +18,10 @@ import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; import org.hibernate.exception.DataException; import org.nrg.config.exceptions.SiteConfigurationException; -import org.nrg.framework.services.ContextService; import org.nrg.xdat.XDAT; import org.nrg.xdat.entities.AliasToken; import org.nrg.xdat.entities.UserAuthI; import org.nrg.xdat.entities.XdatUserAuth; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.security.helpers.Users; import org.nrg.xdat.services.XdatUserAuthService; @@ -37,10 +35,6 @@ import org.nrg.xnat.security.provider.XnatDatabaseAuthenticationProvider; import org.nrg.xnat.security.provider.XnatLdapAuthenticationProvider; import org.nrg.xnat.security.tokens.XnatDatabaseUsernamePasswordAuthenticationToken; import org.nrg.xnat.security.tokens.XnatLdapUsernamePasswordAuthenticationToken; -import org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -48,28 +42,30 @@ import org.springframework.security.authentication.*; import org.springframework.security.core.*; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import javax.inject.Inject; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; public class XnatProviderManager extends ProviderManager { - public XnatProviderManager(final List<AuthenticationProvider> providers) { + public XnatProviderManager(final List<AuthenticationProvider> providers, final XdatUserAuthService userAuthService, final AnonymousAuthenticationProvider anonymousAuthenticationProvider, final DataSource dataSource) { super(providers); + _userAuthService = userAuthService; + _anonymousAuthenticationProvider = anonymousAuthenticationProvider; + _dataSource = dataSource; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - Class<? extends Authentication> toTest = authentication.getClass(); - AuthenticationException lastException = null; - Authentication result = null; - List<AuthenticationProvider> providers = new ArrayList<>(); + Class<? extends Authentication> toTest = authentication.getClass(); + AuthenticationException lastException = null; + Authentication result = null; + List<AuthenticationProvider> providers = new ArrayList<>(); // HACK: This is a hack to work around open XNAT auth issue. If this is a bare un/pw auth token, use anon auth. if (authentication.getClass() == UsernamePasswordAuthenticationToken.class && authentication.getName().equalsIgnoreCase("guest")) { - providers.add(getAnonymousAuthenticationProvider()); - authentication = new AnonymousAuthenticationToken(getAnonymousAuthenticationProvider().getKey(), authentication.getPrincipal(), Collections.<GrantedAuthority> singletonList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))); + providers.add(_anonymousAuthenticationProvider); + authentication = new AnonymousAuthenticationToken(_anonymousAuthenticationProvider.getKey(), authentication.getPrincipal(), Collections.<GrantedAuthority>singletonList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))); } else { for (AuthenticationProvider candidate : getProviders()) { if (!candidate.supports(toTest)) { @@ -89,7 +85,7 @@ public class XnatProviderManager extends ProviderManager { if (((XnatDatabaseAuthenticationProvider) candidate).isPlainText()) { String username = authentication.getPrincipal().toString(); @SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"}) - final Boolean encrypted = new JdbcTemplate(_dataSource).query("SELECT primary_password_encrypt<>0 OR (primary_password_encrypt IS NULL AND CHAR_LENGTH(primary_password)=64) FROM xdat_user WHERE login=? LIMIT 1", new String[] {username}, new RowMapper<Boolean>() { + final Boolean encrypted = new JdbcTemplate(_dataSource).query("SELECT primary_password_encrypt<>0 OR (primary_password_encrypt IS NULL AND CHAR_LENGTH(primary_password)=64) FROM xdat_user WHERE login=? LIMIT 1", new String[]{username}, new RowMapper<Boolean>() { public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getBoolean(1); } @@ -142,26 +138,22 @@ public class XnatProviderManager extends ProviderManager { ((CredentialsContainer) result).eraseCredentials(); } - eventPublisher.publishAuthenticationSuccess(authentication); + _eventPublisher.publishAuthenticationSuccess(authentication); return result; } else { // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) { - lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", - new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}")); + final String message = messages.getMessage("providerManager.providerNotFound", new Object[]{toTest.getName()}, "No authentication provider found for {0}"); + lastException = new ProviderNotFoundException(message); } - eventPublisher.publishAuthenticationFailure(lastException, authentication); + _eventPublisher.publishAuthenticationFailure(lastException, authentication); throw lastException; } } - private AnonymousAuthenticationProvider getAnonymousAuthenticationProvider() { - return _contextService.getBean(AnonymousAuthenticationProvider.class); - } - public XdatUserAuth getUserByAuth(Authentication authentication) { if (authentication == null) { return null; @@ -179,12 +171,12 @@ public class XnatProviderManager extends ProviderManager { provider = ((XnatLdapUsernamePasswordAuthenticationToken) authentication).getProviderId(); method = XdatUserAuthService.LDAP; } else { - provider = XnatDatabaseUserDetailsService.DB_PROVIDER; + provider = ""; method = XdatUserAuthService.LOCALDB; } try { - return getUserAuthService().getUserByNameAndAuth(u, method, provider); + return _userAuthService.getUserByNameAndAuth(u, method, provider); } catch (DataException exception) { _log.error("An error occurred trying to retrieve the auth method", exception); throw new RuntimeException("An error occurred trying to validate the given information. Please check your username and password. If this problem persists, please contact your system administrator."); @@ -205,7 +197,7 @@ public class XnatProviderManager extends ProviderManager { String auth = cached_methods.get(username); if (auth == null) { try { - List<XdatUserAuth> userAuths = getUserAuthService().getUsersByName(username); + List<XdatUserAuth> userAuths = _userAuthService.getUsersByName(username); if (userAuths.size() == 1) { auth = userAuths.get(0).getAuthMethod(); cached_methods.put(username.intern(), auth.intern()); @@ -230,13 +222,6 @@ public class XnatProviderManager extends ProviderManager { return auth; } - private XdatUserAuthService getUserAuthService() { - if (_userAuthService == null) { - _userAuthService = _contextService.getBean(XdatUserAuthService.class); - } - return _userAuthService; - } - private static UsernamePasswordAuthenticationToken buildUPToken(XnatAuthenticationProvider provider, String username, String password) { if (provider instanceof XnatLdapAuthenticationProvider) { return new XnatLdapUsernamePasswordAuthenticationToken(username, password, provider.getProviderId()); @@ -390,19 +375,9 @@ public class XnatProviderManager extends ProviderManager { protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - @Inject - private DataSource _dataSource; - - @Autowired - @Qualifier("rootContextService") - @Lazy - private ContextService _contextService; - - @Autowired - @Lazy - private InitializerSiteConfiguration _preferences; - - private XdatUserAuthService _userAuthService; + private final AuthenticationEventPublisher _eventPublisher = new AuthenticationAttemptEventPublisher(this); - private final AuthenticationEventPublisher eventPublisher = new AuthenticationAttemptEventPublisher(this); + private final XdatUserAuthService _userAuthService; + private final AnonymousAuthenticationProvider _anonymousAuthenticationProvider; + private final DataSource _dataSource; } diff --git a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java index 5fec5247ff826c996dd060ee30cd9168bf66855b..a9a6cde795a6f83878ec7578c798574c112dbf58 100644 --- a/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java +++ b/src/main/java/org/nrg/xnat/security/XnatSessionEventPublisher.java @@ -15,6 +15,7 @@ import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xft.security.UserI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.authentication.AnonymousAuthenticationToken; @@ -25,7 +26,6 @@ import org.springframework.security.web.session.HttpSessionCreatedEvent; import org.springframework.security.web.session.HttpSessionDestroyedEvent; import org.springframework.web.context.support.WebApplicationContextUtils; -import javax.inject.Inject; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -46,6 +46,7 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo * * @param event HttpSessionEvent passed in by the container */ + @Override public void sessionCreated(HttpSessionEvent event) { HttpSession session = event.getSession(); HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(session); @@ -69,6 +70,7 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo * * @param event The HttpSessionEvent pass in by the container */ + @Override public void sessionDestroyed(final HttpSessionEvent event) { final String sessionId = event.getSession().getId(); final Date today = Calendar.getInstance(TimeZone.getDefault()).getTime(); @@ -115,12 +117,16 @@ public class XnatSessionEventPublisher implements HttpSessionListener, ServletCo } } + @Autowired + public void setJdbcTemplate(final JdbcTemplate template) { + _template = template; + } + private ApplicationContext getContext(ServletContext servletContext) { return WebApplicationContextUtils.findWebApplicationContext(servletContext); // contextAttribute in xnat's case will always be "org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc"); } private static final Logger _log = LoggerFactory.getLogger(XnatSessionEventPublisher.class); - @Inject private JdbcTemplate _template; } \ No newline at end of file diff --git a/src/main/java/org/nrg/xnat/security/alias/AliasTokenAuthenticationProvider.java b/src/main/java/org/nrg/xnat/security/alias/AliasTokenAuthenticationProvider.java index e8a9a051dfac89496088429d4da8aeab0f8a7550..e0de6d27d59cc18d65af8055b4225d9fdcb010d8 100644 --- a/src/main/java/org/nrg/xnat/security/alias/AliasTokenAuthenticationProvider.java +++ b/src/main/java/org/nrg/xnat/security/alias/AliasTokenAuthenticationProvider.java @@ -11,17 +11,14 @@ package org.nrg.xnat.security.alias; import org.apache.commons.lang3.StringUtils; -import org.nrg.framework.services.ContextService; import org.nrg.xdat.entities.AliasToken; import org.nrg.xdat.security.helpers.Users; import org.nrg.xdat.services.AliasTokenService; import org.nrg.xdat.services.XdatUserAuthService; -import org.nrg.xdat.services.impl.hibernate.HibernateAliasTokenService; import org.nrg.xft.security.UserI; import org.nrg.xnat.security.provider.XnatAuthenticationProvider; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -32,31 +29,27 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider implements XnatAuthenticationProvider { - - public AliasTokenAuthenticationProvider() { - this("token"); - } - - public AliasTokenAuthenticationProvider(final String name) { - _name = name; + @Autowired + public AliasTokenAuthenticationProvider(final AliasTokenService aliasTokenService, final XdatUserAuthService userAuthService) { + super(); + _aliasTokenService = aliasTokenService; + _userAuthService = userAuthService; } /** - * Performs authentication with the same contract as {@link - * org.springframework.security.authentication.AuthenticationManager#authenticate(org.springframework.security.core.Authentication)}. + * Performs authentication with the same contract as {@link AuthenticationManager#authenticate(Authentication)}. * * @param authentication the authentication request object. * @return a fully authenticated object including credentials. May return <code>null</code> if the - * <code>AuthenticationProvider</code> is unable to support authentication of the passed - * <code>Authentication</code> object. In such a case, the next <code>AuthenticationProvider</code> that - * supports the presented <code>Authentication</code> class will be tried. - * @throws org.springframework.security.core.AuthenticationException - * if authentication fails. + * <code>AuthenticationProvider</code> is unable to support authentication of the passed + * <code>Authentication</code> object. In such a case, the next <code>AuthenticationProvider</code> that + * supports the presented <code>Authentication</code> class will be tried. + * @throws AuthenticationException if authentication fails. */ @Override public Authentication authenticate(final Authentication authentication) throws AuthenticationException { - final String alias = (String) authentication.getPrincipal(); - final AliasToken token = getAliasTokenService().locateToken(alias); + final String alias = (String) authentication.getPrincipal(); + final AliasToken token = _aliasTokenService.locateToken(alias); if (token == null) { throw new BadCredentialsException("No valid alias token found for alias: " + alias); } @@ -79,7 +72,7 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent * * @param authentication DOCUMENT ME! * @return <code>true</code> if the implementation can more closely evaluate the <code>Authentication</code> class - * presented + * presented */ @Override public boolean supports(final Class<?> authentication) { @@ -99,16 +92,12 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent @Override public String getName() { - return StringUtils.isBlank(_name) ? getClass().toString() : _name; + return XdatUserAuthService.TOKEN; } @Override public String getProviderId() { - return _providerId; - } - - public void setProviderId(final String id) { - _providerId = id; + return XdatUserAuthService.TOKEN; } @Override @@ -134,9 +123,9 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent final UserI xdatUserDetails = (UserI) userDetails; Users.validateUserLogin(xdatUserDetails); - String alias = ((AliasTokenAuthenticationToken) authentication).getAlias(); + String alias = ((AliasTokenAuthenticationToken) authentication).getAlias(); String secret = ((AliasTokenAuthenticationToken) authentication).getSecret(); - String userId = getAliasTokenService().validateToken(alias, secret); + String userId = _aliasTokenService.validateToken(alias, secret); if (StringUtils.isBlank(userId) || !userId.equals(userDetails.getUsername())) { throw new BadCredentialsException("The submitted alias token was invalid: " + alias); } @@ -164,14 +153,13 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent * @param authentication The authentication request, which subclasses <em>may</em> need to perform a binding-based * retrieval of the <code>UserDetails</code> * @return the user information (never <code>null</code> - instead an exception should the thrown) - * @throws org.springframework.security.core.AuthenticationException - * if the credentials could not be validated (generally a - * <code>BadCredentialsException</code>, an <code>AuthenticationServiceException</code> or - * <code>UsernameNotFoundException</code>) + * @throws AuthenticationException If the credentials could not be validated (generally a + * <code>BadCredentialsException</code>, an <code>AuthenticationServiceException</code> or + * <code>UsernameNotFoundException</code>) */ @Override protected UserDetails retrieveUser(final String username, final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { - AliasToken token = getAliasTokenService().locateToken(username); + AliasToken token = _aliasTokenService.locateToken(username); if (token == null) { throw new UsernameNotFoundException("Unable to locate token with alias: " + username); } @@ -180,32 +168,9 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent * The hack is to return the user details for the most recent successful login of the user, as that is likely the provider that was used. * Not perfect, but better than just hard-coding to localdb provider (cause then it won't work for a token created by an LDAP-authenticated user). */ - return getUserAuthService().getUserDetailsByUsernameAndMostRecentSuccessfulLogin(token.getXdatUserId()); - } - - private XdatUserAuthService getUserAuthService() { - if (_userAuthService == null) { - _userAuthService = _contextService.getBean(XdatUserAuthService.class); - } - return _userAuthService; - } - - private AliasTokenService getAliasTokenService() { - if (_aliasTokenService == null) { - _aliasTokenService = _contextService.getBean(HibernateAliasTokenService.class); - } - return _aliasTokenService; + return _userAuthService.getUserDetailsByUsernameAndMostRecentSuccessfulLogin(token.getXdatUserId()); } - @Autowired - @Qualifier("rootContextService") - @Lazy - private ContextService _contextService; - - private AliasTokenService _aliasTokenService; - - private XdatUserAuthService _userAuthService; - - private final String _name; - private String _providerId; + private final AliasTokenService _aliasTokenService; + private final XdatUserAuthService _userAuthService; } diff --git a/src/main/java/org/nrg/xnat/security/config/DatabaseAuthenticationProviderConfigurator.java b/src/main/java/org/nrg/xnat/security/config/DatabaseAuthenticationProviderConfigurator.java index 0857caa31dba50c47e834af3cc7d217a7c3ab4d1..0b306e52346e53bdbcb28f175182e02eb2c3e3f4 100644 --- a/src/main/java/org/nrg/xnat/security/config/DatabaseAuthenticationProviderConfigurator.java +++ b/src/main/java/org/nrg/xnat/security/config/DatabaseAuthenticationProviderConfigurator.java @@ -10,11 +10,10 @@ */ package org.nrg.xnat.security.config; -import org.nrg.xdat.preferences.InitializerSiteConfiguration; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xnat.security.provider.XnatDatabaseAuthenticationProvider; import org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.ReflectionSaltSource; import org.springframework.security.authentication.encoding.ShaPasswordEncoder; @@ -24,7 +23,11 @@ import java.util.List; import java.util.Map; public class DatabaseAuthenticationProviderConfigurator extends AbstractAuthenticationProviderConfigurator { - public DatabaseAuthenticationProviderConfigurator() { + @Autowired + public DatabaseAuthenticationProviderConfigurator(final XnatDatabaseUserDetailsService userDetailsService, final SiteConfigPreferences preferences) { + super(); + _userDetailsService = userDetailsService; + _preferences = preferences; setConfiguratorId("db"); } @@ -36,7 +39,7 @@ public class DatabaseAuthenticationProviderConfigurator extends AbstractAuthenti saltSource.setUserPropertyToUse("salt"); XnatDatabaseAuthenticationProvider sha2DatabaseAuthProvider = new XnatDatabaseAuthenticationProvider(_preferences.getEmailVerification()); - sha2DatabaseAuthProvider.setUserDetailsService(_detailsService); + sha2DatabaseAuthProvider.setUserDetailsService(_userDetailsService); sha2DatabaseAuthProvider.setPasswordEncoder(new ShaPasswordEncoder(256)); sha2DatabaseAuthProvider.setName(name); sha2DatabaseAuthProvider.setProviderId(id); @@ -51,10 +54,6 @@ public class DatabaseAuthenticationProviderConfigurator extends AbstractAuthenti return getAuthenticationProviders(id, name); } - @Autowired - @Lazy - private XnatDatabaseUserDetailsService _detailsService; - - @Autowired - private InitializerSiteConfiguration _preferences; + private final XnatDatabaseUserDetailsService _userDetailsService; + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/security/config/LdapAuthenticationProviderConfigurator.java b/src/main/java/org/nrg/xnat/security/config/LdapAuthenticationProviderConfigurator.java index a23300a67337716d01073f5c1c0cc419cc5799ab..851f87ef2c27d02f505e9676212dc24bce2586a5 100644 --- a/src/main/java/org/nrg/xnat/security/config/LdapAuthenticationProviderConfigurator.java +++ b/src/main/java/org/nrg/xnat/security/config/LdapAuthenticationProviderConfigurator.java @@ -19,7 +19,6 @@ import org.nrg.xnat.security.XnatLdapAuthoritiesPopulator; import org.nrg.xnat.security.XnatLdapUserDetailsMapper; import org.nrg.xnat.security.provider.XnatLdapAuthenticationProvider; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.ldap.DefaultSpringSecurityContextSource; import org.springframework.security.ldap.authentication.BindAuthenticator; @@ -30,8 +29,12 @@ import java.util.List; import java.util.Map; public class LdapAuthenticationProviderConfigurator extends AbstractAuthenticationProviderConfigurator { - public LdapAuthenticationProviderConfigurator() { + @Autowired + public LdapAuthenticationProviderConfigurator(final XdatUserAuthService userAuthService, final SiteConfigPreferences preferences) { + super(); setConfiguratorId("ldap"); + _userAuthService = userAuthService; + _preferences = preferences; } @Override @@ -69,11 +72,6 @@ public class LdapAuthenticationProviderConfigurator extends AbstractAuthenticati private static final Log _log = LogFactory.getLog(LdapAuthenticationProviderConfigurator.class); - @Autowired - @Lazy - private XdatUserAuthService _userAuthService; - - @Autowired - @Lazy - private SiteConfigPreferences _preferences; + private final XdatUserAuthService _userAuthService; + private final SiteConfigPreferences _preferences; } diff --git a/src/main/java/org/nrg/xnat/security/provider/XnatAuthenticationProvider.java b/src/main/java/org/nrg/xnat/security/provider/XnatAuthenticationProvider.java index a54351af2f89f895d6f871b44b5236734f810942..76535627b587c9ba154ae4e1a71195b4fb29cfca 100644 --- a/src/main/java/org/nrg/xnat/security/provider/XnatAuthenticationProvider.java +++ b/src/main/java/org/nrg/xnat/security/provider/XnatAuthenticationProvider.java @@ -18,26 +18,26 @@ public interface XnatAuthenticationProvider extends AuthenticationProvider { * the authentication method. * @return The display name for the XNAT authentication provider. */ - abstract public String getName(); + String getName(); /** * Gets the provider ID for the XNAT authentication provider. This is used to map the properties associated with the * provider instance. * @return The provider ID for the XNAT authentication provider. */ - abstract public String getProviderId(); + String getProviderId(); /** * Indicates whether the provider should be visible to and selectable by users. <b>false</b> usually indicates an * internal authentication provider, e.g. token authentication. * @return <b>true</b> if the provider should be visible to and usable by users. */ - abstract public boolean isVisible(); + boolean isVisible(); /** * Indicates the authentication method associated with this provider. This is used to locate the provider based on * the user's selected authentication method. * @return The authentication method for this provider. */ - abstract public String getAuthMethod(); + String getAuthMethod(); } diff --git a/src/main/java/org/nrg/xnat/security/userdetailsservices/XnatDatabaseUserDetailsService.java b/src/main/java/org/nrg/xnat/security/userdetailsservices/XnatDatabaseUserDetailsService.java index a69154c7563957ec68e133e0ebd17eca50c73c01..49e7c290f4257ddfc67f671b51a214c28c77b6f8 100644 --- a/src/main/java/org/nrg/xnat/security/userdetailsservices/XnatDatabaseUserDetailsService.java +++ b/src/main/java/org/nrg/xnat/security/userdetailsservices/XnatDatabaseUserDetailsService.java @@ -8,47 +8,37 @@ */ package org.nrg.xnat.security.userdetailsservices; -import org.nrg.framework.services.ContextService; import org.nrg.xdat.services.XdatUserAuthService; import org.nrg.xnat.security.PasswordExpiredException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; import org.springframework.dao.DataAccessException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; -public class XnatDatabaseUserDetailsService extends JdbcDaoImpl implements UserDetailsService { +import javax.sql.DataSource; - // MIGRATION: This needs to go away and be replaced by a standard property for an XNAT user details service. - public static final String DB_PROVIDER = ""; +public class XnatDatabaseUserDetailsService extends JdbcDaoImpl implements UserDetailsService { + @Autowired + public XnatDatabaseUserDetailsService(final XdatUserAuthService userAuthService, final DataSource dataSource) { + super(); + setDataSource(dataSource); + _userAuthService = userAuthService; + } @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException, PasswordExpiredException { - UserDetails user = getXdatUserAuthService().getUserDetailsByNameAndAuth(username, XdatUserAuthService.LOCALDB, DB_PROVIDER); + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException, DataAccessException, PasswordExpiredException { + final UserDetails user = _userAuthService.getUserDetailsByNameAndAuth(username, XdatUserAuthService.LOCALDB, ""); if (_log.isDebugEnabled()) { _log.debug("Loaded user {} by username from user-auth service.", user.getUsername()); } return user; } - private XdatUserAuthService getXdatUserAuthService() { - if (_xdatUserAuthService == null) { - _xdatUserAuthService = _contextService.getBean(XdatUserAuthService.class); - } - return _xdatUserAuthService; - } - private static final Logger _log = LoggerFactory.getLogger(XnatDatabaseUserDetailsService.class); - @Autowired - @Qualifier("rootContextService") - @Lazy - private ContextService _contextService; - - private XdatUserAuthService _xdatUserAuthService; + private final XdatUserAuthService _userAuthService; } diff --git a/src/main/java/org/nrg/xnat/services/PETTracerUtils.java b/src/main/java/org/nrg/xnat/services/PETTracerUtils.java index b3d9be6a57d5b468958232c5e1e1b294062f3502..3a1ab2a552646b24d020f8946b13427628ec1c6c 100644 --- a/src/main/java/org/nrg/xnat/services/PETTracerUtils.java +++ b/src/main/java/org/nrg/xnat/services/PETTracerUtils.java @@ -1,39 +1,35 @@ -package org.nrg.xnat.services;/* +/* * org.nrg.xnat.services.PETTracerUtils.java * XNAT http://www.xnat.org - * Copyright (c) 2013, Washington University School of Medicine + * Copyright (c) 2016, Washington University School of Medicine * All Rights Reserved * * Released under the Simplified BSD. - * - * Created 8/7/14 12:50 PM */ +package org.nrg.xnat.services; +import org.apache.commons.io.IOUtils; import org.nrg.config.entities.Configuration; import org.nrg.config.exceptions.ConfigServiceException; import org.nrg.config.services.ConfigService; import org.nrg.framework.constants.Scope; -import org.nrg.xft.XFT; +import org.nrg.framework.utilities.BasicXnatResourceLocator; import org.nrg.xnat.helpers.editscript.DicomEdit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; -import javax.inject.Inject; -import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; @Service public class PETTracerUtils { - public PETTracerUtils() throws Exception { - if (_instance != null) { - throw new Exception("The PETTracerUtils service is already initialized, try calling getInstance() instead."); - } - _instance = this; - } - - public static PETTracerUtils getService() { - return _instance; + @Autowired + public PETTracerUtils(final ConfigService configService) { + _configService = configService; } public Configuration getTracerList(final String path, final Long project) { @@ -60,13 +56,15 @@ public class PETTracerUtils { _configService.replaceConfig(login, "", TOOL_NAME, path, tracerList); } - public static File getDefaultTracerList() throws FileNotFoundException { - final File def = new File(XFT.GetConfDir(), DEFAULT_TRACER_LIST); - if (def.exists()) { - return def; - } else { - throw new FileNotFoundException("Default tracer list: " + DEFAULT_TRACER_LIST + " not found in " + XFT.GetConfDir()); + public static String getDefaultTracerList() throws IOException { + final StringBuilder tracers = new StringBuilder(); + final List<Resource> resources = BasicXnatResourceLocator.getResources(DEFAULT_TRACER_LIST); + for (final Resource resource : resources) { + try (final InputStream input = resource.getInputStream()) { + tracers.append(IOUtils.readLines(input, "UTF-8")); + } } + return tracers.toString(); } // flat out stolen from DicomEdit.java @@ -90,10 +88,7 @@ public class PETTracerUtils { private static final String TOOL_NAME = "tracers"; - private static final String DEFAULT_TRACER_LIST = "PET-tracers.txt"; - - private static PETTracerUtils _instance; + private static final String DEFAULT_TRACER_LIST = "classpath*:META-INF/xnat/defaults/**/PET-tracers.txt"; - @Inject - private ConfigService _configService; + private final ConfigService _configService; } diff --git a/src/main/java/org/nrg/xnat/services/XnatAppInfo.java b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java index 9ccbfc658e57740c8855d39affef4707536a07cb..827be957c50c6c960d776b71269018fb0063f3b7 100644 --- a/src/main/java/org/nrg/xnat/services/XnatAppInfo.java +++ b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java @@ -1,6 +1,5 @@ package org.nrg.xnat.services; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; @@ -27,7 +26,8 @@ public class XnatAppInfo { public static final String MINUTES = "minutes"; public static final String SECONDS = "seconds"; - public XnatAppInfo(final ServletContext context) throws IOException { + @Inject + public XnatAppInfo(final ServletContext context, final JdbcTemplate template) throws IOException { try (final InputStream input = context.getResourceAsStream("/META-INF/MANIFEST.MF")) { final Manifest manifest = new Manifest(input); final Attributes attributes = manifest.getMainAttributes(); @@ -59,6 +59,7 @@ public class XnatAppInfo { } } } + _template = template; } /** @@ -175,8 +176,7 @@ public class XnatAppInfo { private static final List<String> PRIMARY_MANIFEST_ATTRIBUTES = Arrays.asList("Build-Number", "Build-Date", "Implementation-Version", "Implementation-Sha"); - @Inject - private JdbcTemplate _template; + private final JdbcTemplate _template; private final Date _startTime = new Date(); private final Properties _properties = new Properties(); diff --git a/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java b/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java index cbc893b87a20a9876ffd26d848415b5f55772ea1..8ff70059079273182d332b8653dc1363773fe785 100644 --- a/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java +++ b/src/main/java/org/nrg/xnat/utils/XnatUserProvider.java @@ -10,7 +10,11 @@ */ package org.nrg.xnat.utils; +import org.nrg.framework.exceptions.NrgServiceError; +import org.nrg.framework.exceptions.NrgServiceRuntimeException; import org.nrg.xdat.security.helpers.Users; +import org.nrg.xdat.security.user.exceptions.UserInitException; +import org.nrg.xdat.security.user.exceptions.UserNotFoundException; import org.nrg.xft.security.UserI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,28 +22,42 @@ import org.springframework.stereotype.Component; import javax.inject.Provider; +/** + * Defines the default user for XNAT services. + */ @Component public class XnatUserProvider implements Provider<UserI> { public XnatUserProvider(final String login) { _login = login; } - /* - * (non-Javadoc) - * @see javax.inject.Provider#get() + /** + * {@inheritDoc} */ + @Override public UserI get() { if (null == user) { try { user = Users.getUser(_login); - } catch (Throwable t) { - _logger.error("Unable to retrieve user " + _login, t); - return null; + } catch (UserInitException e) { + throw new NrgServiceRuntimeException(NrgServiceError.UserServiceError, "User object for name " + _login + " could not be initialized."); + } catch (UserNotFoundException e) { + throw new NrgServiceRuntimeException(NrgServiceError.UserNotFoundError, "User with name " + _login + " could not be found."); } } return user; } + /** + * Returns the configured login name for the default user. This can be used when only the username is required, + * since this is a more lightweight operation. + * + * @return The configured user login name. + */ + public String getLogin() { + return _login; + } + private final Logger _logger = LoggerFactory.getLogger(XnatUserProvider.class); private final String _login; private UserI user = null; diff --git a/src/main/resources/META-INF/xnat/defaults/PET-tracers.txt b/src/main/resources/META-INF/xnat/defaults/PET-tracers.txt new file mode 100644 index 0000000000000000000000000000000000000000..832b798619160148040c126675021f71d58fcf38 --- /dev/null +++ b/src/main/resources/META-INF/xnat/defaults/PET-tracers.txt @@ -0,0 +1,2 @@ +PIB +FDG diff --git a/src/main/resources/META-INF/xnat/defaults/id.das b/src/main/resources/META-INF/xnat/defaults/id.das new file mode 100644 index 0000000000000000000000000000000000000000..e211f1bf0ea7fc8b39502f175707ca0f055f5ac1 --- /dev/null +++ b/src/main/resources/META-INF/xnat/defaults/id.das @@ -0,0 +1,4 @@ +project = "Unassigned" : (0008,1030) := (0008,1030) +(0008,1030) := project +(0010,0010) := subject +(0010,0020) := session diff --git a/src/main/resources/org/nrg/xnat/messages/system.properties b/src/main/resources/org/nrg/xnat/messages/system.properties new file mode 100644 index 0000000000000000000000000000000000000000..ac767a1b37d162c6d10680abccb590f4c3aec25a --- /dev/null +++ b/src/main/resources/org/nrg/xnat/messages/system.properties @@ -0,0 +1 @@ +providerManager.providerNotFound=No authentication provider found for {0} \ No newline at end of file