From 770a32421513a19f165093d33c8cabd25f44e0e4 Mon Sep 17 00:00:00 2001 From: "Mark M. Florida" <mflorida@gmail.com> Date: Fri, 13 May 2016 18:08:50 -0500 Subject: [PATCH] Getting everything synched up. --- .../exceptions/InitializationException.java | 11 + .../nrg/xapi/rest/settings/SiteConfigApi.java | 75 ++-- .../xnat/configuration/ApplicationConfig.java | 9 +- .../nrg/xnat/initialization/RootConfig.java | 10 +- .../xnat/security/XnatInitCheckFilter.java | 78 +++-- .../org/nrg/xnat/services/XnatAppInfo.java | 110 ++++++ .../modules/screens/Configuration.java | 38 -- .../turbine/modules/screens/EditArcSpecs.java | 164 --------- .../xnat/turbine/utils/ArcSpecManager.java | 103 +++--- .../webapp/WEB-INF/conf/xnat-security.xml | 103 +++--- .../xnat-templates/screens/Configuration.vm | 142 -------- .../xnat-templates/screens/EditArcSpecs.vm | 331 ------------------ .../screens/configuration/anonymization.vm | 71 ---- .../screens/configuration/applets.vm | 57 --- .../screens/configuration/dicomReceiver.vm | 74 ---- .../screens/configuration/features.vm | 112 ------ .../screens/configuration/fileSystem.vm | 80 ----- .../screens/configuration/mockRestConfig.vm | 44 --- .../screens/configuration/notifications.vm | 122 ------- .../screens/configuration/petTracers.vm | 51 --- .../screens/configuration/registration.vm | 62 ---- .../screens/configuration/scanTypeMapping.vm | 56 --- .../screens/configuration/security.vm | 184 ---------- .../configuration/seriesImportFilter.vm | 94 ----- .../screens/configuration/siteInfo.vm | 208 ----------- 25 files changed, 345 insertions(+), 2044 deletions(-) create mode 100644 src/main/java/org/nrg/xapi/exceptions/InitializationException.java create mode 100644 src/main/java/org/nrg/xnat/services/XnatAppInfo.java delete mode 100644 src/main/java/org/nrg/xnat/turbine/modules/screens/Configuration.java delete mode 100644 src/main/java/org/nrg/xnat/turbine/modules/screens/EditArcSpecs.java delete mode 100755 src/main/webapp/xnat-templates/screens/Configuration.vm delete mode 100644 src/main/webapp/xnat-templates/screens/EditArcSpecs.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/anonymization.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/applets.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/dicomReceiver.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/features.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/fileSystem.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/mockRestConfig.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/notifications.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/petTracers.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/registration.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/scanTypeMapping.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/security.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/seriesImportFilter.vm delete mode 100644 src/main/webapp/xnat-templates/screens/configuration/siteInfo.vm diff --git a/src/main/java/org/nrg/xapi/exceptions/InitializationException.java b/src/main/java/org/nrg/xapi/exceptions/InitializationException.java new file mode 100644 index 00000000..b33955e8 --- /dev/null +++ b/src/main/java/org/nrg/xapi/exceptions/InitializationException.java @@ -0,0 +1,11 @@ +package org.nrg.xapi.exceptions; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class InitializationException extends Exception { + public InitializationException(final Throwable throwable) { + super(throwable); + } +} 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 fcdad8eb..6d38437d 100644 --- a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java +++ b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java @@ -2,10 +2,15 @@ package org.nrg.xapi.rest.settings; import com.google.common.base.Joiner; import io.swagger.annotations.*; +import org.apache.commons.lang3.StringUtils; import org.nrg.framework.annotations.XapiRestController; import org.nrg.prefs.exceptions.InvalidPreferenceName; +import org.nrg.xapi.exceptions.InitializationException; import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xdat.rest.AbstractXnatRestApi; +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; @@ -18,12 +23,11 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.jar.Attributes; -import java.util.jar.Manifest; @Api(description = "Site Configuration Management API") @XapiRestController @@ -37,36 +41,32 @@ public class SiteConfigApi extends AbstractXnatRestApi { _log.debug("User " + getSessionUser().getUsername() + " requested the application build information."); } - if (_properties.size() == 0) { - final Attributes attributes = _manifest.getMainAttributes(); - _properties.setProperty("buildNumber", attributes.getValue("Build-Number")); - _properties.setProperty("buildDate", attributes.getValue("Build-Date")); - _properties.setProperty("version", attributes.getValue("Implementation-Version")); - _properties.setProperty("commit", attributes.getValue("Implementation-Sha")); - if (_log.isDebugEnabled()) { - _log.debug("Initialized application build information:\n * Version: {}\n * Build number: {}\n * Build Date: {}\n * Commit: {}", - _properties.getProperty("version"), - _properties.getProperty("buildNumber"), - _properties.getProperty("buildDate"), - _properties.getProperty("commit")); - } - } - - return new ResponseEntity<>(_properties, HttpStatus.OK); + return new ResponseEntity<>(_appInfo.getSystemProperties(), HttpStatus.OK); } - @ApiOperation(value = "Returns the full map of site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = SiteConfigPreferences.class) + @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}) - public ResponseEntity<SiteConfigPreferences> getAllSiteConfigProperties() { + public ResponseEntity<Map<String, Object>> getAllSiteConfigProperties(final HttpServletRequest request) { final HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); } + final String username = getSessionUser().getUsername(); if (_log.isDebugEnabled()) { - _log.debug("User " + getSessionUser().getUsername() + " requested the site configuration."); + _log.debug("User " + username + " requested the site configuration."); + } + + final Map<String, Object> preferences = _preferences.getPreferenceMap(); + + if (!_appInfo.isInitialized()) { + if (_log.isInfoEnabled()) { + _log.info("The site is being initialized by user {}. Setting default values from context.", username); + } + preferences.put("siteUrl", XnatHttpUtils.getServerRoot(request)); } - return new ResponseEntity<>(_preferences, HttpStatus.OK); + + return new ResponseEntity<>(preferences, HttpStatus.OK); } @ApiOperation(value = "Returns a map of the selected site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = String.class, responseContainer = "Map") @@ -110,8 +110,8 @@ public class SiteConfigApi extends AbstractXnatRestApi { @ApiOperation(value = "Sets a map of site configuration properties.", notes = "Sets the site configuration properties specified in the map.", response = Void.class) @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = "batch", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST}) - public ResponseEntity<Void> setBatchSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) { - HttpStatus status = isPermitted(); + public ResponseEntity<Void> setBatchSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) throws InitializationException { + final HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); } @@ -132,14 +132,18 @@ public class SiteConfigApi extends AbstractXnatRestApi { } } + if (properties.containsKey("initialized") && StringUtils.equals("true", properties.get("initialized"))) { + initialize(); + } + return new ResponseEntity<>(HttpStatus.OK); } @ApiOperation(value = "Sets a single site configuration property.", notes = "Sets the site configuration property specified in the URL to the value set in the body.", response = Void.class) @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")}) @RequestMapping(value = {"/{property}"}, consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST}) - public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @PathVariable("property") final String property, @RequestBody final String value) { - HttpStatus status = isPermitted(); + public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @PathVariable("property") final String property, @RequestBody final String value) throws InitializationException { + final HttpStatus status = isPermitted(); if (status != null) { return new ResponseEntity<>(status); } @@ -155,9 +159,24 @@ public class SiteConfigApi extends AbstractXnatRestApi { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } + if (StringUtils.equals("initialized", property) && StringUtils.equals("true", value)) { + initialize(); + } + return new ResponseEntity<>(HttpStatus.OK); } + private void initialize() throws InitializationException { + // In the case where the application hasn't yet been initialized, this operation should mean that the system is + // being initialized from the set-up page. In that case, we need to propagate a few properties to the arc-spec + // persistence to support + try { + ArcSpecManager.initialize(getSessionUser()); + } catch (Exception e) { + throw new InitializationException(e); + } + } + private static final Logger _log = LoggerFactory.getLogger(SiteConfigApi.class); @Autowired @@ -166,7 +185,5 @@ public class SiteConfigApi extends AbstractXnatRestApi { @Autowired @Lazy - private Manifest _manifest; - - private Properties _properties = new Properties(); + private XnatAppInfo _appInfo; } diff --git a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java index 0a2d8fd0..74b582bf 100644 --- a/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java +++ b/src/main/java/org/nrg/xnat/configuration/ApplicationConfig.java @@ -14,6 +14,7 @@ import org.nrg.xdat.services.impl.ThemeServiceImpl; import org.nrg.xnat.initialization.InitializingTasksExecutor; import org.nrg.xnat.restlet.XnatRestletExtensions; import org.nrg.xnat.restlet.actions.importer.ImporterHandlerPackages; +import org.nrg.xnat.services.PETTracerUtils; import org.nrg.xnat.utils.XnatUserProvider; import org.springframework.context.annotation.*; @@ -29,11 +30,10 @@ import java.util.List; "org.nrg.prefs.repositories", "org.nrg.xdat.daos", "org.nrg.xdat.services.impl.hibernate", "org.nrg.xft.daos", "org.nrg.xft.event.listeners", "org.nrg.xft.services", "org.nrg.xnat.configuration", "org.nrg.xnat.daos", "org.nrg.xnat.event.listeners", "org.nrg.xnat.helpers.merge", "org.nrg.xnat.initialization.tasks", - "org.nrg.xnat.services", "org.nrg.xnat.services.impl.hibernate", "org.nrg.xnat.spawner.repositories"}) + "org.nrg.xnat.services.impl.hibernate", "org.nrg.xnat.spawner.repositories"}) @Import({FeaturesConfig.class, ReactorConfig.class}) @ImportResource("WEB-INF/conf/mq-context.xml") public class ApplicationConfig { - @Bean public ThemeService themeService() { return new ThemeServiceImpl(); @@ -55,6 +55,11 @@ public class ApplicationConfig { return new SiteConfigPreferences(); } + @Bean + public PETTracerUtils petTracerUtils() throws Exception { + return new PETTracerUtils(); + } + @Bean public UserManagementServiceI userManagementService() { // TODO: This should be made to use a preference setting. diff --git a/src/main/java/org/nrg/xnat/initialization/RootConfig.java b/src/main/java/org/nrg/xnat/initialization/RootConfig.java index cb878fda..79de8d9a 100644 --- a/src/main/java/org/nrg/xnat/initialization/RootConfig.java +++ b/src/main/java/org/nrg/xnat/initialization/RootConfig.java @@ -14,7 +14,9 @@ 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; +import org.nrg.xnat.services.XnatAppInfo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -38,17 +40,15 @@ import java.util.jar.Manifest; * configuration preferences. * * <b>NOTE:</b> If you are adding code to this class, please be sure you know what you're doing! Most configuration code - * for standard XNAT components should be added in {@link org.nrg.xnat.configuration.ApplicationConfig} + * for standard XNAT components should be added in the {@link ApplicationConfig application configuration class}. */ @Configuration @Import({PropertiesConfig.class, DatabaseConfig.class}) @ImportResource("WEB-INF/conf/xnat-security.xml") public class RootConfig { @Bean - public Manifest applicationManifest(final ServletContext context) throws IOException { - try (final InputStream input = context.getResourceAsStream("/META-INF/MANIFEST.MF")) { - return new Manifest(input); - } + public XnatAppInfo appInfo(final ServletContext context) throws IOException { + return new XnatAppInfo(context); } @Bean diff --git a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java index 1960e057..5c3c0ea0 100644 --- a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java +++ b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java @@ -13,8 +13,10 @@ package org.nrg.xnat.security; import org.nrg.xdat.XDAT; import org.nrg.xdat.security.helpers.Roles; import org.nrg.xft.security.UserI; +import org.nrg.xnat.services.XnatAppInfo; import org.nrg.xnat.utils.XnatHttpUtils; -import org.springframework.jdbc.core.JdbcTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.web.filter.GenericFilterBean; import javax.inject.Inject; @@ -27,27 +29,27 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; public class XnatInitCheckFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { - final HttpServletRequest request = (HttpServletRequest) req; + final HttpServletRequest request = (HttpServletRequest) req; final HttpServletResponse response = (HttpServletResponse) res; - // In this case, the count of siteUrl is a proxy for whether the system has been initialized. - @SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"}) - final boolean initialized = _template.queryForObject("select count(*) from xhbm_preference p, xhbm_tool t where t.tool_id = 'siteConfig' and p.tool = t.id and p.name = 'siteUrl';", Integer.class) > 0; - if (initialized) { - // If the site URL has already been set, do not redirect. + if (_appInfo.isInitialized()) { + // If the site URL has already been set, do not redirect and save the fact that we're initialized. chain.doFilter(req, res); } else { - final UserI user = XDAT.getUserDetails(); - final String uri = request.getRequestURI(); + // We're going to use the user for logging. + final UserI user = XDAT.getUserDetails(); + + final String uri = request.getRequestURI(); if (user == null) { String header = request.getHeader("Authorization"); - if (header != null && header.startsWith("Basic ") && !uri.contains(_initializationPath)) { + if (header != null && header.startsWith("Basic ") && !isInitializerPath(uri)) { // Users that authenticated using basic authentication receive an error message informing // them that the system is not yet initialized. response.sendError(HttpServletResponse.SC_FORBIDDEN, "Site has not yet been configured."); @@ -57,25 +59,34 @@ public class XnatInitCheckFilter extends GenericFilterBean { final String referer = request.getHeader("Referer"); - if (uri.contains(_initializationPath) || uri.endsWith(_configurationPath) || uri.endsWith(_nonAdminErrorPath) || isExemptedPath(uri)) { + if (isInitializerPath(uri) || + _configurationPathPattern.matcher(uri).matches() || + _nonAdminErrorPathPattern.matcher(uri).matches() || + isExemptedPath(uri)) { //If you're already on the configuration page, error page, or expired password page, continue on without redirect. chain.doFilter(req, res); - } else if (referer != null && (referer.endsWith(_configurationPath) || referer.endsWith(_nonAdminErrorPath) || isExemptedPath(referer)) && !uri.contains("/app/template") && !uri.contains("/app/screen") && !uri.endsWith(".vm") && !uri.equals("/")) { + } else if (referer != null && (_configurationPathPattern.matcher(referer).matches() || _nonAdminErrorPathPattern.matcher(referer).matches() || isExemptedPath(referer)) && !uri.contains("/app/template") && !uri.contains("/app/screen") && !uri.endsWith(".vm") && !uri.equals("/")) { //If you're on a request within the configuration page (or error page or expired password page), continue on without redirect. This checks that the referer is the configuration page and that // the request is not for another page (preventing the user from navigating away from the Configuration page via the menu bar). chain.doFilter(req, res); } else { - if(user == null) { - // user not authenticated, let another filter handle the redirect - // (NB: I tried putting this check up with the basic auth check, - // but you get this weird redirect with 2 login pages on the same screen. Seems to work here). + if (user == null) { + // user not authenticated, let another filter handle the redirect + // (NB: I tried putting this check up with the basic auth check, + // but you get this weird redirect with 2 login pages on the same screen. Seems to work here). chain.doFilter(req, res); } else { final String serverPath = XnatHttpUtils.getServerRoot(request); if (Roles.isSiteAdmin(user)) { + if (_log.isWarnEnabled()) { + _log.warn("Admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _configurationPath); + } //Otherwise, if the user has administrative permissions, direct the user to the configuration page. response.sendRedirect(serverPath + _configurationPath); } else { + if (_log.isWarnEnabled()) { + _log.warn("Non-admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _nonAdminErrorPath); + } //The system is not initialized but the user does not have administrative permissions. Direct the user to an error page. response.sendRedirect(serverPath + _nonAdminErrorPath); } @@ -84,16 +95,20 @@ public class XnatInitCheckFilter extends GenericFilterBean { } } - public void setInitializationPath(final String initializationPath) { - _initializationPath = initializationPath; + public void setInitializationPaths(final List<String> initializationPaths) { + for (final String initializationPath : initializationPaths) { + _initializationPathPatterns.add(Pattern.compile("^https*://.*" + initializationPath + ".*$")); + } } public void setConfigurationPath(String configurationPath) { _configurationPath = configurationPath; + _configurationPathPattern = Pattern.compile("^https*://.*" + configurationPath + "/*"); } public void setNonAdminErrorPath(String nonAdminErrorPath) { _nonAdminErrorPath = nonAdminErrorPath; + _nonAdminErrorPathPattern = Pattern.compile("^https*://.*" + nonAdminErrorPath + "/*"); } public void setExemptedPaths(List<String> exemptedPaths) { @@ -101,20 +116,35 @@ public class XnatInitCheckFilter extends GenericFilterBean { _exemptedPaths.addAll(exemptedPaths); } - private boolean isExemptedPath(String path) { + private boolean isExemptedPath(final String path) { for (final String exemptedPath : _exemptedPaths) { - if (path.endsWith(exemptedPath)) { + if (path.split("\\?")[0].endsWith(exemptedPath)) { return true; } } return false; } + private boolean isInitializerPath(final String uri) { + for (final Pattern initializationPathPattern : _initializationPathPatterns) { + if (initializationPathPattern.matcher(uri).matches()) { + return true; + } + } + return false; + } + + private static Logger _log = LoggerFactory.getLogger(XnatInitCheckFilter.class); + @Inject - private JdbcTemplate _template; + private XnatAppInfo _appInfo; + + private String _configurationPath; + private String _nonAdminErrorPath; + private Pattern _configurationPathPattern; + private Pattern _nonAdminErrorPathPattern; + + private List<Pattern> _initializationPathPatterns = new ArrayList<>(); - private String _initializationPath = ""; - private String _configurationPath = ""; - private String _nonAdminErrorPath = ""; private final List<String> _exemptedPaths = new ArrayList<>(); } diff --git a/src/main/java/org/nrg/xnat/services/XnatAppInfo.java b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java new file mode 100644 index 00000000..2b6326ca --- /dev/null +++ b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java @@ -0,0 +1,110 @@ +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; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.servlet.ServletContext; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +@Component +public class XnatAppInfo { + public XnatAppInfo(final ServletContext context) throws IOException { + try (final InputStream input = context.getResourceAsStream("/META-INF/MANIFEST.MF")) { + final Manifest manifest = new Manifest(input); + final Attributes attributes = manifest.getMainAttributes(); + _properties.setProperty("buildNumber", attributes.getValue("Build-Number")); + _properties.setProperty("buildDate", attributes.getValue("Build-Date")); + _properties.setProperty("version", attributes.getValue("Implementation-Version")); + _properties.setProperty("commit", attributes.getValue("Implementation-Sha")); + if (_log.isDebugEnabled()) { + _log.debug("Initialized application build information:\n * Version: {}\n * Build number: {}\n * Build Date: {}\n * Commit: {}", + _properties.getProperty("version"), + _properties.getProperty("buildNumber"), + _properties.getProperty("buildDate"), + _properties.getProperty("commit")); + } + for (final Object key : attributes.keySet()) { + final String name = key.toString(); + if (!PRIMARY_MANIFEST_ATTRIBUTES.contains(name)) { + _properties.setProperty(name, attributes.getValue(name)); + } + } + final Map<String, Attributes> entries = manifest.getEntries(); + for (final String key : entries.keySet()) { + final Map<String, String> keyedAttributes = new HashMap<>(); + _attributes.put(key, keyedAttributes); + final Attributes entry = entries.get(key); + for (final Object subkey : entry.keySet()) { + final String property = (String) subkey; + keyedAttributes.put(property, attributes.getValue(property)); + } + } + } + } + + /** + * Indicates whether the XNAT system has been initialized yet. + * @return Returns true if the system has been initialized, false otherwise. + */ + public boolean isInitialized() { + if (!_initialized) { + // The value for siteUrl is a proxy for whether the system has been initialized: siteUrl can NOT be blank, + // so if it is this hasn't been initialized. + //noinspection SqlDialectInspection,SqlNoDataSourceInspection + _initialized = StringUtils.isNotBlank(_template.queryForObject("select value from xhbm_preference p, xhbm_tool t where t.tool_id = 'siteConfig' and p.tool = t.id and p.name = 'siteUrl';", String.class)); + if (_log.isInfoEnabled()) { + _log.info("The site was not flagged as initialized, but a valid siteUrl setting was found. Flagging as initialized."); + } + } + return _initialized; + } + + /** + * Returns the primary XNAT system properties extracted from the installed application's manifest file. These + * properties are guaranteed to include the following: + * + * <ul> + * <li>version</li> + * <li>buildNumber</li> + * <li>buildDate</li> + * <li>commit</li> + * </ul> + * + * There may be other properties available in the system properties and even more available through the {@link + * #getSystemAttributes()} method. + * + * @return The primary system properties. + */ + public Properties getSystemProperties() { + return new Properties(_properties); + } + + /** + * Returns extended XNAT system attributes. + * + * @return The XNAT system attributes. + */ + public Map<String, Map<String, String>> getSystemAttributes() { + return new HashMap<>(_attributes); + } + + private static final Logger _log = LoggerFactory.getLogger(XnatAppInfo.class); + + private static final List<String> PRIMARY_MANIFEST_ATTRIBUTES = Arrays.asList("Build-Number", "Build-Date", "Implementation-Version", "Implementation-Sha"); + + @Inject + private JdbcTemplate _template; + + private final Properties _properties = new Properties(); + private final Map<String, Map<String, String>> _attributes = new HashMap<>(); + private boolean _initialized = false; +} + diff --git a/src/main/java/org/nrg/xnat/turbine/modules/screens/Configuration.java b/src/main/java/org/nrg/xnat/turbine/modules/screens/Configuration.java deleted file mode 100644 index 6db80177..00000000 --- a/src/main/java/org/nrg/xnat/turbine/modules/screens/Configuration.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * org.nrg.xnat.turbine.modules.screens.Configuration - * XNAT http://www.xnat.org - * Copyright (c) 2014, Washington University School of Medicine - * All Rights Reserved - * - * Released under the Simplified BSD. - * - * Last modified 7/10/13 9:04 PM - */ -package org.nrg.xnat.turbine.modules.screens; - -import org.apache.turbine.util.RunData; -import org.apache.velocity.context.Context; -import org.nrg.xdat.om.ArcArchivespecification; -import org.nrg.xdat.security.helpers.Features; -import org.nrg.xdat.turbine.modules.screens.AdminScreen; -import org.nrg.xdat.turbine.utils.TurbineUtils; -import org.nrg.xnat.turbine.utils.ArcSpecManager; - -public class Configuration extends AdminScreen { - @Override - protected void doBuildTemplate(RunData data, Context context) throws Exception { - ArcArchivespecification arcSpec = ArcSpecManager.GetInstance(); - if (arcSpec == null) { - arcSpec = ArcSpecManager.initialize(TurbineUtils.getUser(data)); - } - if (!ArcSpecManager.HasPersisted()) { - context.put("initialize", true); - } else { - context.put("initialize", false); - } - context.put("arc", arcSpec); - setDefaultTabs("siteInfo", "fileSystem", "registration", "notifications", "anonymization", "applet", "dicomReceiver"); - cacheTabs(context, "configuration"); - context.put("features", Features.getAllFeatures()); - } -} diff --git a/src/main/java/org/nrg/xnat/turbine/modules/screens/EditArcSpecs.java b/src/main/java/org/nrg/xnat/turbine/modules/screens/EditArcSpecs.java deleted file mode 100644 index d7eb5893..00000000 --- a/src/main/java/org/nrg/xnat/turbine/modules/screens/EditArcSpecs.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * org.nrg.xnat.turbine.modules.screens.EditArcSpecs - * XNAT http://www.xnat.org - * Copyright (c) 2014, Washington University School of Medicine - * All Rights Reserved - * - * Released under the Simplified BSD. - * - * Last modified 7/10/13 9:04 PM - */ -package org.nrg.xnat.turbine.modules.screens; - -import java.util.List; - -import org.apache.turbine.util.RunData; -import org.apache.velocity.context.Context; -import org.nrg.mail.api.NotificationType; -import org.nrg.notify.api.CategoryScope; -import org.nrg.notify.entities.Category; -import org.nrg.notify.entities.Definition; -import org.nrg.notify.entities.Subscription; -import org.nrg.notify.services.NotificationService; -import org.nrg.xdat.XDAT; -import org.nrg.xdat.model.ArcArchivespecificationNotificationTypeI; -import org.nrg.xdat.om.ArcArchivespecification; -import org.nrg.xdat.om.ArcArchivespecificationNotificationType; -import org.nrg.xdat.security.helpers.Users; -import org.nrg.xdat.turbine.modules.screens.AdminScreen; -import org.nrg.xdat.turbine.utils.TurbineUtils; -import org.nrg.xft.security.UserI; -import org.nrg.xnat.turbine.utils.ArcSpecManager; - -public class EditArcSpecs extends AdminScreen { - - /* (non-Javadoc) - * @see org.apache.turbine.modules.screens.VelocitySecureScreen#doBuildTemplate(org.apache.turbine.util.RunData, org.apache.velocity.context.Context) - */ - @Override - protected void doBuildTemplate(RunData data, Context context) throws Exception { - ArcArchivespecification arcSpec = ArcSpecManager.GetInstance(); - if (arcSpec==null){ - arcSpec = ArcSpecManager.initialize((UserI) TurbineUtils.getUser(data)); - } - - checkNotifications(arcSpec); - - context.put("idLabelMap", NotificationType.getIdLabelMap()); - context.put("arc", arcSpec); - } - - /** - * Checks whether site-side notifications exist and initializes them if not. - * - * @param arcSpec The archive specification object. - * @throws Exception - */ - private void checkNotifications(ArcArchivespecification arcSpec) throws Exception { - // Check whether any notification types already exist and clear them if so. - clearArcSpecNotifications(arcSpec); - - for (NotificationType type : NotificationType.values()) { - Definition definition = retrieveSiteEventDefinition(type); - List<Subscription> subscriptions = getNotificationService().getSubscriptionService().getSubscriptionsForDefinition(definition); - - ArcArchivespecificationNotificationTypeI typeObj = new ArcArchivespecificationNotificationType(); - typeObj.setNotificationType(type.id()); - if (subscriptions == null || subscriptions.size() == 0) { - typeObj.setEmailAddresses(getSiteAdminAccount(arcSpec) + " <" + arcSpec.getSiteAdminEmail() + ">"); - } else { - StringBuilder buffer = new StringBuilder(); - boolean isFirst = true; - for (Subscription subscription : subscriptions) { - if (isFirst) { - isFirst = false; - } else { - buffer.append(", "); -} - buffer.append(subscription.getSubscriber()); - } - typeObj.setEmailAddresses(buffer.toString()); - } - arcSpec.addNotificationTypes_notificationType(typeObj); - } - } - - /** - * @param arcSpec - */ - private void clearArcSpecNotifications(ArcArchivespecification arcSpec) { - List<ArcArchivespecificationNotificationTypeI> notificationTypes; - while ((notificationTypes = arcSpec.getNotificationTypes_notificationType()) != null && notificationTypes.size() > 0) { - arcSpec.removeNotificationTypes_notificationType(0); - } - } - - /** - * @param type The type for which the definition and its associated category should be created or retrieved. - * @return The existing or newly created definition. - */ - private Definition retrieveSiteEventDefinition(NotificationType type) { - Category category = getNotificationService().getCategoryService().getCategoryByScopeAndEvent(CategoryScope.Site, type.toString()); - if (category == null) { - category = initializeSiteEventCategory(type.toString()); - } - List<Definition> definitions = getNotificationService().getDefinitionService().getDefinitionsForCategory(category); - Definition definition; - if (definitions == null || definitions.size() == 0) { - definition = initializeSiteEventDefinition(category); - } else { - definition = definitions.get(0); - } - return definition; - } - - /** - * Gets the notification service instance. - * - * @return The notification service instance. - */ - private NotificationService getNotificationService() { - if (_notificationService == null) { - _notificationService = XDAT.getNotificationService(); - } - return _notificationService; - } - - /** - * @param event The event for which a category should be created. - * @return The newly created category object. - */ - private Category initializeSiteEventCategory(String event) { - Category category = getNotificationService().getCategoryService().newEntity(); - category.setScope(CategoryScope.Site); - category.setEvent(event); - getNotificationService().getCategoryService().create(category); - return category; - } - - - /** - * @param category The category for which a definition should be created. - * @return The newly created definition object. - */ - private Definition initializeSiteEventDefinition(Category category) { - Definition definition = getNotificationService().getDefinitionService().newEntity(); - definition.setCategory(category); - getNotificationService().getDefinitionService().create(definition); - return definition; - } - - /** - * @param arcSpec - * @return - */ - private String getSiteAdminAccount(ArcArchivespecification arcSpec) { - List<UserI> users = Users.getUsersByEmail(arcSpec.getSiteAdminEmail()); - if (users == null || users.size() == 0) { - throw new RuntimeException("Can't find anything for the site admin email account! It must be associated with a user account: " + arcSpec.getSiteAdminEmail()); - } - return users.get(0).getLogin(); - } - - private NotificationService _notificationService; -} diff --git a/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java b/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java index c39e1289..17c17ad8 100644 --- a/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java +++ b/src/main/java/org/nrg/xnat/turbine/utils/ArcSpecManager.java @@ -10,15 +10,12 @@ */ package org.nrg.xnat.turbine.utils; +import org.apache.commons.lang3.StringUtils; import org.nrg.xdat.XDAT; import org.nrg.xdat.om.ArcArchivespecification; -import org.nrg.xdat.turbine.utils.AdminUtils; -import org.nrg.xft.XFT; +import org.nrg.xdat.preferences.SiteConfigPreferences; import org.nrg.xft.event.EventDetails; -import org.nrg.xft.exception.ElementNotFoundException; -import org.nrg.xft.exception.FieldNotFoundException; -import org.nrg.xft.exception.InvalidValueException; -import org.nrg.xft.exception.XFTInitException; +import org.nrg.xft.event.EventUtils; import org.nrg.xft.security.UserI; import org.nrg.xft.utils.SaveItemHelper; import org.nrg.xnat.helpers.prearchive.PrearcConfig; @@ -31,6 +28,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Map; /** * @author timo @@ -39,16 +37,14 @@ import java.util.ArrayList; public class ArcSpecManager { private static final Logger logger = LoggerFactory.getLogger(ArcSpecManager.class); private static ArcArchivespecification arcSpec = null; - private static boolean _hasPersisted = false; - public synchronized static ArcArchivespecification GetFreshInstance() { + public synchronized static ArcArchivespecification GetFreshInstance() { ArcArchivespecification arcSpec = null; logger.warn("Getting Fresh ArcSpec..."); ArrayList<ArcArchivespecification> allSpecs = ArcArchivespecification.getAllArcArchivespecifications(null,false); if (allSpecs.size()>0) { arcSpec = allSpecs.get(0); - _hasPersisted = true; - } + } return arcSpec; } @@ -216,56 +212,60 @@ public class ArcSpecManager { return arcSpec; } - public synchronized static Boolean HasPersisted() { - return _hasPersisted; - } - public synchronized static void Reset(){ arcSpec=null; } - public synchronized static ArcArchivespecification initialize(UserI user) throws XFTInitException, ElementNotFoundException, FieldNotFoundException, InvalidValueException { + public synchronized static ArcArchivespecification initialize(final UserI user) throws Exception { arcSpec = new ArcArchivespecification(user); - if (XDAT.getSiteConfigPreferences().getAdminEmail()!=null && !XDAT.getSiteConfigPreferences().getAdminEmail().equals("")) { - arcSpec.setSiteAdminEmail(XDAT.getSiteConfigPreferences().getAdminEmail()); + final SiteConfigPreferences preferences = XDAT.getSiteConfigPreferences(); + if (StringUtils.isNotBlank(preferences.getAdminEmail())) { + arcSpec.setSiteAdminEmail(preferences.getAdminEmail()); } - if (XDAT.getSiteConfigPreferences().getSiteUrl()!=null && !XDAT.getSiteConfigPreferences().getSiteUrl().equals("")) { - arcSpec.setSiteUrl(XDAT.getSiteConfigPreferences().getSiteUrl()); + if (StringUtils.isNotBlank(preferences.getSiteId())) { + arcSpec.setSiteId(preferences.getSiteId()); } -// if (XFT.GetAdminEmailHost()!=null && !XFT.GetAdminEmailHost().equals("")) { -// arcSpec.setSmtpHost(XFT.GetAdminEmailHost()); -// } -// -// arcSpec.setEnableNewRegistrations(XDAT.getSiteConfigPreferences().getUserRegistration()); -// -// arcSpec.setRequireLogin(XDAT.getSiteConfigPreferences().getRequireLogin()); -// if (XDAT.getSiteConfigPreferences().getAdminEmail()!=null && !XDAT.getSiteConfigPreferences().getAdminEmail().equals("")) { -// arcSpec.setProperty("globalPaths/pipelinePath", XDAT.getSiteConfigPreferences().getAdminEmail()); -// } -// -// if (XFT.GetArchiveRootPath()!=null && !XFT.GetArchiveRootPath().equals("")) { -// arcSpec.setProperty("globalPaths/archivePath", XFT.GetArchiveRootPath()); -// } -// -// if (XFT.GetPrearchivePath()!=null && !XFT.GetPrearchivePath().equals("")) { -// arcSpec.setProperty("globalPaths/prearchivePath", XFT.GetPrearchivePath()); -// } -// -// if (XDAT.getSiteConfigPreferences().getCachePath()!=null && !XDAT.getSiteConfigPreferences().getCachePath().equals("")) { -// arcSpec.setProperty("globalPaths/cachePath", XDAT.getSiteConfigPreferences().getCachePath()); -// } -// -// if (XFT.getFtpPath()!=null && !XFT.getFtpPath().equals("")) { -// arcSpec.setProperty("globalPaths/ftpPath", XFT.getFtpPath()); -// } -// -// if (XFT.getBuildPath()!=null && !XFT.getBuildPath().equals("")) { -// arcSpec.setProperty("globalPaths/buildPath", XFT.getBuildPath()); -// } -// arcSpec.setEnableCsrfToken(XFT.GetEnableCsrfToken()); - + if (StringUtils.isNotBlank(preferences.getSiteUrl())) { + arcSpec.setSiteUrl(preferences.getSiteUrl()); + } + + final Map<String, String> smtpServer = preferences.getSmtpServer(); + if (smtpServer != null && smtpServer.containsKey("host")) { + arcSpec.setSmtpHost(smtpServer.get("host")); + } + + arcSpec.setEnableNewRegistrations(preferences.getUserRegistration()); + + arcSpec.setRequireLogin(preferences.getRequireLogin()); + if (StringUtils.isNotBlank(preferences.getAdminEmail())) { + arcSpec.setProperty("globalPaths/pipelinePath", preferences.getPipelinePath()); + } + + if (StringUtils.isNotBlank(preferences.getArchivePath())) { + arcSpec.setProperty("globalPaths/archivePath", preferences.getArchivePath()); + } + + if (StringUtils.isNotBlank(preferences.getPrearchivePath())) { + arcSpec.setProperty("globalPaths/prearchivePath", preferences.getPrearchivePath()); + } + + if (StringUtils.isNotBlank(preferences.getCachePath())) { + arcSpec.setProperty("globalPaths/cachePath", preferences.getCachePath()); + } + + if (StringUtils.isNotBlank(preferences.getFtpPath())) { + arcSpec.setProperty("globalPaths/ftpPath", preferences.getFtpPath()); + } + + if (StringUtils.isNotBlank(preferences.getBuildPath())) { + arcSpec.setProperty("globalPaths/buildPath", preferences.getBuildPath()); + } + + arcSpec.setEnableCsrfToken(preferences.getEnableCsrfToken()); + + save(arcSpec, user, EventUtils.newEventInstance(EventUtils.CATEGORY.SIDE_ADMIN, EventUtils.TYPE.PROCESS, "Initialized archive specifications.")); return arcSpec; } @@ -280,6 +280,5 @@ public class ArcSpecManager { public static synchronized void save(ArcArchivespecification arcSpec, UserI user, EventDetails event) throws Exception { SaveItemHelper.unauthorizedSave(arcSpec, user, false, false, event); ArcSpecManager.Reset(); - _hasPersisted = true; } } diff --git a/src/main/webapp/WEB-INF/conf/xnat-security.xml b/src/main/webapp/WEB-INF/conf/xnat-security.xml index 5ec44a3b..bbd738c2 100644 --- a/src/main/webapp/WEB-INF/conf/xnat-security.xml +++ b/src/main/webapp/WEB-INF/conf/xnat-security.xml @@ -12,16 +12,18 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> - <context:property-placeholder location="WEB-INF/conf/services.properties,WEB-INF/conf/services-custom.properties" ignore-resource-not-found="true" ignore-unresolvable="true" /> + <context:property-placeholder location="WEB-INF/conf/services.properties,WEB-INF/conf/services-custom.properties" + ignore-resource-not-found="true" ignore-unresolvable="true"/> - <context:annotation-config /> + <context:annotation-config/> <util:list id="decisionVoters"> <ref bean="roleVoter"/> <ref bean="authenticatedVoter"/> </util:list> - <bean class="org.springframework.security.access.vote.UnanimousBased" id="unanimousBased" c:decisionVoters-ref="decisionVoters"/> + <bean class="org.springframework.security.access.vote.UnanimousBased" id="unanimousBased" + c:decisionVoters-ref="decisionVoters"/> <bean class="org.springframework.security.access.vote.RoleVoter" id="roleVoter" p:rolePrefix="ROLE_"/> @@ -30,11 +32,12 @@ <bean class="org.nrg.xnat.security.OnXnatLogin" id="logUserLogin"/> <bean class="org.nrg.xnat.security.XnatUrlAuthenticationFailureHandler" id="authFailure"> - <constructor-arg value="/app/template/Login.vm?failed=true" /> - <constructor-arg value="/app/template/PostRegister.vm" /> - </bean> + <constructor-arg value="/app/template/Login.vm?failed=true"/> + <constructor-arg value="/app/template/PostRegister.vm"/> + </bean> - <bean id="loginUrlAuthenticationEntryPoint" class="org.nrg.xnat.security.XnatAuthenticationEntryPoint" c:loginFormUrl="/app/template/Login.vm"> + <bean id="loginUrlAuthenticationEntryPoint" class="org.nrg.xnat.security.XnatAuthenticationEntryPoint" + c:loginFormUrl="/app/template/Login.vm"> <property name="dataPaths"> <list value-type="java.lang.String"> <value>/data/**</value> @@ -52,27 +55,32 @@ </property> </bean> - <bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter" c:sessionRegistry-ref="sessionRegistry" c:expiredUrl="/app/template/Login.vm" /> - <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" /> - <bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy"> - <constructor-arg name="sessionRegistry" ref="sessionRegistry" /> + <bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter" + c:sessionRegistry-ref="sessionRegistry" c:expiredUrl="/app/template/Login.vm"/> + <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/> + <bean id="sas" + class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy"> + <constructor-arg name="sessionRegistry" ref="sessionRegistry"/> <property name="maximumSessions" value="${security.sessions.concurrent_max}"/> <property name="exceptionIfMaximumExceeded" value="true"/> </bean> - <bean id="xnatLogoutSuccessHandler" class="org.nrg.xnat.security.XnatLogoutSuccessHandler" p:openXnatLogoutSuccessUrl="/" p:securedXnatLogoutSuccessUrl="/app/template/Login.vm"/> + <bean id="xnatLogoutSuccessHandler" class="org.nrg.xnat.security.XnatLogoutSuccessHandler" + p:openXnatLogoutSuccessUrl="/" p:securedXnatLogoutSuccessUrl="/app/template/Login.vm"/> <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> - <constructor-arg name="logoutSuccessHandler" ref="xnatLogoutSuccessHandler" type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler"/> + <constructor-arg name="logoutSuccessHandler" ref="xnatLogoutSuccessHandler" + type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler"/> <constructor-arg name="handlers"> <list> <ref bean="xnatLogoutHandler"/> <ref bean="securityContextLogoutHandler"/> </list> </constructor-arg> - <property name="filterProcessesUrl" value="/app/action/LogoutUser" /> + <property name="filterProcessesUrl" value="/app/action/LogoutUser"/> + </bean> + <bean id="securityContextLogoutHandler" + class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"> + <property name="invalidateHttpSession" value="true"/> </bean> - <bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"> - <property name="invalidateHttpSession" value="true" /> - </bean> <bean id="xnatLogoutHandler" class="org.nrg.xnat.security.XnatLogoutHandler"/> <security:http auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint"> @@ -80,13 +88,13 @@ <security:custom-filter position="CHANNEL_FILTER" ref="channelProcessingFilter"/> <security:custom-filter before="FORM_LOGIN_FILTER" ref="customAuthenticationFilter"/> <security:custom-filter after="BASIC_AUTH_FILTER" ref="customBasicAuthenticationFilter"/> - <security:custom-filter before="REMEMBER_ME_FILTER" ref="xnatInitCheckFilter"/> - <security:custom-filter after="SECURITY_CONTEXT_FILTER" ref="expiredPasswordFilter"/> - <security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> - <security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter" /> + <security:custom-filter before="REMEMBER_ME_FILTER" ref="xnatInitCheckFilter"/> + <security:custom-filter after="SECURITY_CONTEXT_FILTER" ref="expiredPasswordFilter"/> + <security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter"/> + <security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter"/> <security:session-management session-authentication-strategy-ref="sas"/> <security:headers> - <security:frame-options policy="SAMEORIGIN" /> + <security:frame-options policy="SAMEORIGIN"/> <security:hsts disabled="true"/> </security:headers> </security:http> @@ -162,7 +170,7 @@ </property> </bean> </property> - <property name="requiredChannel" value="${security.channel}" /> + <property name="requiredChannel" value="${security.channel}"/> </bean> <bean id="servicesProperties" class="org.nrg.xnat.security.config.PropertyAggregator"> @@ -174,10 +182,13 @@ </constructor-arg> </bean> - <bean id="aliasTokenAuthProvider" class="org.nrg.xnat.security.alias.AliasTokenAuthenticationProvider" p:name="token"/> + <bean id="aliasTokenAuthProvider" class="org.nrg.xnat.security.alias.AliasTokenAuthenticationProvider" + p:name="token"/> - <bean id="databaseAuthenticationProviderConfigurator" class="org.nrg.xnat.security.config.DatabaseAuthenticationProviderConfigurator" p:configuratorId="db"/> - <bean id="ldapAuthenticationProviderConfigurator" class="org.nrg.xnat.security.config.LdapAuthenticationProviderConfigurator" p:configuratorId="ldap"/> + <bean id="databaseAuthenticationProviderConfigurator" + class="org.nrg.xnat.security.config.DatabaseAuthenticationProviderConfigurator" p:configuratorId="db"/> + <bean id="ldapAuthenticationProviderConfigurator" + class="org.nrg.xnat.security.config.LdapAuthenticationProviderConfigurator" p:configuratorId="ldap"/> <bean id="providerAggregator" class="org.nrg.xnat.security.config.AuthenticationProviderAggregator"> <constructor-arg name="standaloneProviders"> @@ -186,7 +197,8 @@ </list> </constructor-arg> <constructor-arg name="configurators"> - <map key-type="java.lang.String" value-type="org.nrg.xnat.security.config.AuthenticationProviderConfigurator"> + <map key-type="java.lang.String" + value-type="org.nrg.xnat.security.config.AuthenticationProviderConfigurator"> <entry key="db" value-ref="databaseAuthenticationProviderConfigurator"/> <entry key="ldap" value-ref="ldapAuthenticationProviderConfigurator"/> </map> @@ -194,21 +206,23 @@ <constructor-arg name="properties" ref="servicesProperties"/> </bean> - <bean id="customAuthenticationManager" name="org.springframework.security.authenticationManager" class="org.nrg.xnat.security.XnatProviderManager" - c:providers-ref="providerAggregator" c:properties-ref="servicesProperties" /> + <bean id="customAuthenticationManager" name="org.springframework.security.authenticationManager" + class="org.nrg.xnat.security.XnatProviderManager" + c:providers-ref="providerAggregator" c:properties-ref="servicesProperties"/> <bean id="customAuthenticationFilter" class="org.nrg.xnat.security.XnatAuthenticationFilter"> - <property name="authenticationManager" ref="customAuthenticationManager" /> - <property name="authenticationSuccessHandler" ref="logUserLogin" /> - <property name="authenticationFailureHandler" ref="authFailure" /> - <property name="sessionAuthenticationStrategy" ref="sas" /> + <property name="authenticationManager" ref="customAuthenticationManager"/> + <property name="authenticationSuccessHandler" ref="logUserLogin"/> + <property name="authenticationFailureHandler" ref="authFailure"/> + <property name="sessionAuthenticationStrategy" ref="sas"/> </bean> - <bean id="customBasicAuthenticationFilter" class="org.nrg.xnat.security.XnatBasicAuthenticationFilter" c:manager-ref="customAuthenticationManager" c:entryPoint-ref="loginUrlAuthenticationEntryPoint"> - <property name="sessionAuthenticationStrategy" ref="sas" /> + <bean id="customBasicAuthenticationFilter" class="org.nrg.xnat.security.XnatBasicAuthenticationFilter" + c:manager-ref="customAuthenticationManager" c:entryPoint-ref="loginUrlAuthenticationEntryPoint"> + <property name="sessionAuthenticationStrategy" ref="sas"/> </bean> - <bean id="expiredPasswordFilter" class="org.nrg.xnat.security.XnatExpiredPasswordFilter"> + <bean id="expiredPasswordFilter" class="org.nrg.xnat.security.XnatExpiredPasswordFilter"> <property name="changePasswordPath" value="/app/template/XDATScreen_UpdateUser.vm"/> <property name="changePasswordDestination" value="/app/action/ModifyPassword"/> <property name="logoutDestination" value="/app/action/LogoutUser"/> @@ -219,10 +233,13 @@ <property name="emailVerificationPath" value="/app/template/VerifyEmail.vm"/> <property name="emailVerificationDestination" value="/data/services/sendEmailVerification"/> </bean> - - <bean id="xnatInitCheckFilter" class="org.nrg.xnat.security.XnatInitCheckFilter"> - <property name="initializationPath" value="/services/settings/initialize"/> - <!--<property name="configurationPath" value="/app/template/Configuration.vm"/>--> + + <bean id="xnatInitCheckFilter" class="org.nrg.xnat.security.XnatInitCheckFilter"> + <property name="initializationPaths"> + <list value-type="java.lang.String"> + <value>/xapi/siteConfig/batch</value> + </list> + </property> <property name="configurationPath" value="/setup"/> <property name="nonAdminErrorPath" value="/app/template/Unconfigured.vm"/> <property name="exemptedPaths"> @@ -230,11 +247,13 @@ <value>/app/template/XDATScreen_UpdateUser.vm</value> <value>/app/action/ModifyPassword</value> <value>/app/template/Login.vm</value> + <value>/style/app.css</value> <value>/login</value> </list> </property> </bean> - - <bean id="customDatabaseService" class="org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService" p:dataSource-ref="dataSource"/> + + <bean id="customDatabaseService" class="org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService" + p:dataSource-ref="dataSource"/> </beans> diff --git a/src/main/webapp/xnat-templates/screens/Configuration.vm b/src/main/webapp/xnat-templates/screens/Configuration.vm deleted file mode 100755 index f5dc001e..00000000 --- a/src/main/webapp/xnat-templates/screens/Configuration.vm +++ /dev/null @@ -1,142 +0,0 @@ -#* @vtlvariable name="user" type="org.nrg.xft.security.UserI" *# -#* @vtlvariable name="turbineUtils" type="org.nrg.xdat.turbine.utils.TurbineUtils" *# -#* @vtlvariable name="siteConfig" type="java.util.Properties" *# -#* @vtlvariable name="content" type="org.apache.turbine.services.pull.tools.ContentTool" *# -#* @vtlvariable name="data" type="org.apache.turbine.util.RunData" *# -#* @vtlvariable name="tabs" type="java.util.List<java.util.Properties>" *# -#* @vtlvariable name="initialize" type="java.lang.Boolean" *# -<!-- Start Configuration page, source file is plugin-resources/webapp/xnat-templates/screens/Configuration.vm --> -<style type="text/css"> - #configuration_tabs_module { width: 940px; } - #configurationTabs { width: 940px !important; } - #configurationTabs.yui-navset.wrangled ul.yui-nav { height: 28px !important ; } - #configurationTabs .flipper_box .flippers a.flipper { height: 26px ; } -</style> -<script type="text/javascript"> - jq(function(){ - jq('body').addClass('administer configuration no_left_bar'); - }); -</script> -##<script type="text/javascript" src="$content.getURI("scripts/tabWrangler/tabWrangler.js")"></script> -<div class="yui-skin-sam"> -##<div id="tp_fm" style="display:none"></div> - <div class="edit_header1">Configuration</div><br/> - -#if($turbineUtils.isSiteAdmin($user)) - <script type="text/javascript" src="$content.getURI("scripts/yui/build/resize/resize-beta-min.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/yui/build/layout/layout-beta-min.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/search/tabManager.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/search/saveSearch.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/search/dataTableSearch.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/search/dataTableStoredSearch.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/yui/xnat_loader.js")"></script> - <script type="text/javascript" src="$content.getURI("scripts/project/settingsTabMgmt.js")"></script> - - <!-- BEGIN TABS AND CONTENT DISPLAY: Taken from xnat_projectData_summary_tabs.vm --> -## <style>span.spacer {height:12px;width:1px;}</style> - <div id="configuration_tabs_module" style="display:none"> - <div id="configurationTabs" class="yui-navset"> - - <ul class="yui-nav"> - <li class="selected"><a href="#siteInfo"><em>Site Information<span class="spacer"></span></em></a></li> - <li><a href="#security"><em>Security<span class="spacer"></span></em></a> </li> - <li><a href="#fileSystem"><em>File System<span class="spacer"></span></em></a></li> - <li><a href="#features"><em>Features<span class="spacer"></span></em></a></li> - <li><a href="#registration"><em>Registration<span class="spacer"></span></em></a></li> - <li><a href="#notifications"><em>Notifications<span class="spacer"></span></em></a></li> - <li><a href="#anonymization"><em>Anonymization<span class="spacer"></span></em></a></li> - <li><a href="#applets"><em>Applets<span class="spacer"></span></em></a></li> - <li><a href="#seriesImportFilter"><em>Series Import Filter<span class="spacer"></span></em></a></li> - <li><a href="#petTracers"><em>PET Tracers<span class="spacer"></span></em></a></li> - <li><a href="#dicomReceiver"><em>DICOM<span class="spacer"></span></em></a></li> - <li><a href="#scanTypeMapping"><em>Scan Type Mapping<span class="spacer"></span></em></a></li> - #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.show-mock-rest-config", "false"))) - <li><a href="#mockRestConfig"><em>Mock REST Calls<span class="spacer"></span></em></a></li> - #end - #if(!$initialize) - #foreach($tab in $tabs) - <li><a href="#$tab.getProperty("divName")"><em>$tab.getProperty("title")<span class="spacer"></span></em></a></li> - #end - #end - </ul> - <div class="yui-content"> - <div id="siteInfo"> - #parse('screens/configuration/siteInfo.vm') - </div> - <div id="security"> - #parse('screens/configuration/security.vm') - </div> - <div id="fileSystem"> - #parse('screens/configuration/fileSystem.vm') - </div> - <div id="features"> - #parse('screens/configuration/features.vm') - </div> - <div id="registration"> - #parse('screens/configuration/registration.vm') - </div> - <div id="notifications"> - <p>#parse('screens/configuration/notifications.vm') - </div> - <div id="anonymization"> - #parse('screens/configuration/anonymization.vm') - </div> - <div id="applets"> - #parse('screens/configuration/applets.vm') - </div> - <div id="seriesImportFilter"> - #parse('screens/configuration/seriesImportFilter.vm') - </div> - <div id="petTracers"> - #parse('screens/configuration/petTracers.vm') - </div> - <div id="dicomReceiver"> - #parse('screens/configuration/dicomReceiver.vm') - </div> - <div id="scanTypeMappingDefault"> - #parse('screens/configuration/scanTypeMapping.vm') - </div> - #if($turbineUtils.toBoolean($siteConfig.getProperty("UI.show-mock-rest-config", "false"))) - <div id="mockRestConfig"> - #parse('screens/configuration/mockRestConfig.vm') - </div> - #end - #if(!$initialize) - #foreach($tab in $tabs) - <div id="$tab.getProperty("divName")"> - #set($path = "screens/configuration/${tab.getProperty('fileName')}") - #parse($path) - </div> - #end - #end - </div> - </div> - </div> - <script type="text/javascript"> - window.initializing = #if(!$initialize) false #else true #end; - configurationTabManagerInit(); - - jq(function(){ - var mgmt_container = '.mgmt_container'; - jq('body').on('input propertychange',mgmt_container+' input[type="text"], '+mgmt_container+' textarea', function() { - var __this_container = jq(this).closest(mgmt_container); - __this_container.find('input.reset').prop('disabled',false); - }); - }); - - </script> - <!-- END TABS AND CONTENT DISPLAY: Taken from xnat_projectData_summary_tabs.vm --> -#else - <div id="congratsContainer" class="container" style="width:98%;margin:5px;background-color:#ff99cc;"> - <div id="congratsBody" class="containerBody"> - <div class="containerItem edit_header2" style="white-space:normal;line-height:18px;">Security Warning</div> - <div class="containerItem" style="white-space:normal;">You do not have administrator access and can't access this page.</div> - </div> - </div> -#end - <script type="text/javascript"> - jq(window).load(function(){ - wrangleTabs('#configurationTabs'); - }); - </script> -<!-- End Configuration page, source file is plugin-resources/webapp/xnat-templates/screens/Configuration.vm --> diff --git a/src/main/webapp/xnat-templates/screens/EditArcSpecs.vm b/src/main/webapp/xnat-templates/screens/EditArcSpecs.vm deleted file mode 100644 index b427501d..00000000 --- a/src/main/webapp/xnat-templates/screens/EditArcSpecs.vm +++ /dev/null @@ -1,331 +0,0 @@ -#set ($template = $data.getTemplateInfo()) -$!template.setLayoutTemplate("NoMenu.vm") -#if($turbineUtils.isSiteAdmin($user)) -<form name="form1" method="post" action="$link.setAction("SetArcSpecs")"> -<table> - <TR> - <TD COLSPAN=2> - <DIV class="edit_header1">Please configure the default settings for your website.</DIV> - <DIV >This edit page is also available through the Administration > More... section of the website, and can be modified at a later date.<b> All fields are required (unless otherwise specified)</b>.</DIV> - </TD> - </TR> - <TR> - <TD COLSPAN=2> - - </TD> - </TR> - <INPUT TYPE="hidden" NAME="arc:ArchiveSpecification/arc_archivespecification_id" VALUE="$!arc.getProperty("arc_archivespecification_id")"/> - <INPUT TYPE="hidden" NAME="arc:ArchiveSpecification/globalPaths/arc_pathinfo_id" VALUE="$!pathInfo.getProperty("arc_pathinfo_id")"/> - <TR> - <TD valign="top"> - <DIV class="withThinBorder withColor" style="width:400"> - <TABLE> - <TR> - <TD colspan="2"><h4>Site Information</h4></TD> - </TR> - <TR> - <TH align="left">Site ID</TH> - <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/site_id" VALUE="$!arc.getSiteId()" ONCHANGE="this.value=stringCamelCaps(this.value);"/></TD> - </TR> - <TR> - <TD colspan="2"> The id used to refer to this site (also used to generate database ids). No spaces or non-alphanumeric characters. It should be a short, one-word name or acronym which describes your site. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">Site URL</TH> - <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/site_url" VALUE="$!arc.getSiteUrl()"/> </TD> - </TR> - <TR> - <TD colspan="2">The address you want visible to users in emails, and other external links. This should be a functional address (i.e. if the user pasted this address in their web browser, they should come to the site). localhost only works if the web browser is located on the same machine. You are required to guarantee that this address is functional for reaching the site. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> -+ <TH align="left">SMTP Host (Server)</TH> -+ <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/smtp_host" VALUE="$!arc.getSmtpHost()"/></TD> - </TR> - <TR> - <TD colspan="2"> SMTP Server used to send emails generated by the system. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">Site Admin Email Address</TH> - <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/site_admin_email" VALUE="$!arc.getSiteAdminEmail()"/> </TD> - </TR> - <TR> - <TD colspan="2">The administrative email account (which will receive frequent emails). The number of emails can be configured on the Administration > More > Email Settings dialog. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left" colspan="2">Notifications</TH> - </TR> - <TR> - <TD colspan="2">You can specify subscribers for notification by username or email address. If by email address, the email address must belong to a valid system user. You can specify multiple users by separating the usernames or email addresses with a comma. - </TD> - </TR> -#foreach ($notificationType in $arc.getNotificationTypes_notificationType()) - <tr> - <th align="left">$idLabelMap.get($notificationType.getNotificationType()):</th> - <td> - #set ($zeroBasedVelocityCount = $velocityCount - 1) - <input size="40" type="text" name="arc:ArchiveSpecification/notification_types/notification_type[$zeroBasedVelocityCount]/email_addresses" value="$!notificationType.getEmailAddresses()"/> - <input type="hidden" name="arc:ArchiveSpecification/notification_types/notification_type[$zeroBasedVelocityCount]/notification_type" value="$notificationType.getNotificationType()"/></td> - <input type="hidden" name="arc:ArchiveSpecification/notification_types/notification_type[$zeroBasedVelocityCount]/arc_archivespecification_notification_type_id" value="$!notificationType.getArcArchivespecificationNotificationTypeId()"/> - </td> - </tr> -#end - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - </TABLE> - </DIV> - </TD> - <TD valign="top"> - <DIV class="withThinBorder withColor"> - <TABLE> - <TR> - <TD colspan="2"><h4>User/Registration Settings</h4></TD> - </TR> - <TR> - <TH align="left">Enable CSRF Token? (MOVE ME! EditArcSpecs.vm)</TH> - <TD> - #xdatBooleanRadio("arc:ArchiveSpecification/enable_csrf_token" $arc.getItem() true $vr) - </TD> - </TR> - <TR> - <TD colspan="2">If true, FINISH ME!!! - </TD> - </TR> - - - <TR> - <TH align="left">Enable CSRF Token? (MOVE ME! EditArcSpecs.vm)</TH> - <TD> - #xdatBooleanRadio("arc:ArchiveSpecification/enable_csrf_token" $arc.getItem() true $vr) - </TD> - </TR> - <TR> - <TD colspan="2">If true, FINISH ME!!! - </TD> - </TR> - - - <TR> - <TH align="left">Require Login?</TH> - <TD> - #xdatBooleanRadio("arc:ArchiveSpecification/require_login" $arc.getItem() true $vr) - </TD> - </TR> - <TR> - <TD colspan="2">If true, then only registered users will be able to access your site. If false, anyone visiting your site will automatically be logged in as 'guest' with access to public data. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">Auto-enable User Accounts?</TH> - <TD> - #xdatBooleanRadio("arc:ArchiveSpecification/enable_new_registrations" $arc.getItem() false $vr) - </TD> - </TR> - <TR> - <TD colspan="2">If true, user accounts will be enabled automatically when the user registers. Users will be able to access the site and any 'public' $displayManager.getPluralDisplayNameForProject().toLowerCase() immediately. If false, the site adminstrator will be required to manually enable user accounts. Either way the administrator receives an email notification when a user registers. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - </TABLE> - </DIV> - </TD> - </TR> - <TR> - <TD colspan="2"> </TD> - </TR> - #set($pathInfo = $arc.getGlobalpaths()) - <TR> - <TD colspan="2"> - <DIV class="withThinBorder withColor"> - <TABLE> - <TR> - <TD colspan="2"><h4>File System Configuration</h4></TD> - </TR> - <TR> - <TH align="left" nowrap>Archive Location</TH><TD>Location where files are permanently archived.</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/archivePath" VALUE="$!pathInfo.getArchivepath()"/> - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - - <TR> - <TH align="left" nowrap>Pre-archive Location</TH><TD>Location where files are temporarily stored before they are archived.</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/prearchivePath" VALUE="$!pathInfo.getPrearchivepath()"/> </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - - <TR> - <TH align="left" nowrap>Cache Location</TH><TD>Location where deleted files are copied to (to prevent accidental deletion of files).</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/cachePath" VALUE="$!pathInfo.getCachepath()"/> </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - - <TR> - <TH align="left" nowrap>Build Location</TH><TD>Directory where temporarily processing information should be stored. This folder should exist, but not have any files or sub-directories in it.</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/buildPath" VALUE="$!pathInfo.getBuildpath()"/> </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - - <TR> - <TH align="left" nowrap>FTP Location</TH><TD> Directory where FTP Server will store files. This folder should exist, but not have any files or sub-directories in it. (Use and installation of the XNAT FTP Server is optional, but this field must be set).</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/ftpPath" VALUE="$!pathInfo.getFtppath()"/></TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - - <TR> - <TH align="left" nowrap>Pipeline Installation Location</TH><TD>Location of XNAT Pipeline engine. By default, the pipeline engine is already installed in XNAT_HOME/pipeline. This location should be matched here. Change this to a different setting only if you have re-installed the Pipeline engine in another location.</TD> - </TR> - <TR> - <TD colspan="2"><INPUT TYPE="text" SIZE="100" NAME="arc:ArchiveSpecification/globalPaths/pipelinePath" VALUE="$!pathInfo.getPipelinepath()"/> </TD> - </TR> - </TABLE> - </DIV> - </TD> - </TR> - - <TR> - <TD COLSPAN=2> - - </TD> - </TR> - - <TR> - <TD colspan="2"> - <DIV class="withThinBorder withColor"> - <TABLE> - <TR> - <TD colspan="2"><div class="WARNING"><b>Note to XNAT 1.4 users:</b></br> As of XNAT 1.5, DicomServer has been replaced by an internal DICOM receiver and does not need to be installed and configured separately.</div></TD> - </TR> - <TR> - <TD colspan="2"></br><h4>DICOM Receiver (C-STORE SCP) Configuration</h4></TD> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">Port number</TH> - <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/dcm/dcm_Port" VALUE="$!arc.getDcm_dcmPort()"/> </TD> - </TR> - <TR> - <TD colspan="2">This is the port number to which C-STORE SCUs (scanners and other clients sending data) should connect. It is also the port that the SCP listens to, unless a different port has been configured using the <code>DICOM.port</code> property in WEB-INF/conf/DICOM-SCP.properties. See the <a href="http://www.xnat.org/DICOM+C-STORE+SCP">XNAT documentation</a> for detailed information about advanced configuration of the DICOM SCP. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">DICOM AE Title</TH> - <TD><INPUT size="30" TYPE="text" NAME="arc:ArchiveSpecification/dcm/dcm_ae" VALUE="$!arc.getDcm_dcmAe()"/> </TD> - </TR> - <TR> - <TD colspan="2">This is the SCP Application Entity (AE) title. - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - <TR> - <TH align="left">Applet Link </TH> - <TD> - #xdatBooleanRadio("arc:ArchiveSpecification/dcm/applet_link" $arc.getItem() false $vr) - </TD> - </TR> - <TR> - <TD colspan="2">Should a prominent link to the applet show up on the left bar of the index page? - </TD> - </TR> - <TR> - <TD colspan="2" style="line-height:4px"> </TD> - </TR> - </TABLE> - </DIV> - </TD> - </TR> - - <TR> - <TD COLSPAN=2> - - </TD> - </TR> - <TR> - <TD COLSPAN="2" align="center"> - <INPUT TYPE="submit" value="Save" name="eventSubmit_doPerform"/> - </TD> - </TR> -</table> -</form> -<SCRIPT language="javascript"> -function stringCamelCaps(val) -{ - var temp = stringTrim(val); - temp = temp.replace(/[&]/," "); - temp = temp.replace(/[?]/," "); - temp = temp.replace(/[<]/," "); - temp = temp.replace(/[>]/," "); - temp = temp.replace(/[(]/," "); - temp = temp.replace(/[)]/," "); - var newVal = ''; - temp = temp.split(' '); - for(var c=0; c < temp.length; c++) { - if (c==0) - newVal += temp[c].substring(0,1) + -temp[c].substring(1,temp[c].length); - else - newVal += temp[c].substring(0,1).toUpperCase() + -temp[c].substring(1,temp[c].length); - } - - return newVal; -} - -function stringTrim(str) -{ - return str.replace(/^\s*|\s*$/g,""); -} -</SCRIPT> -#else -<DIV class="warning">WARNING: The default settings of this server have not been set. Please log in using an 'Administrator' account, like admin, and adjust the default settings.</DIV> -#end \ No newline at end of file diff --git a/src/main/webapp/xnat-templates/screens/configuration/anonymization.vm b/src/main/webapp/xnat-templates/screens/configuration/anonymization.vm deleted file mode 100644 index 2c1d7663..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/anonymization.vm +++ /dev/null @@ -1,71 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: Anonymization --> -<div class="mgmt_container"> - <div id="anonymization_mgmt_div" class="row"> - <p> - This is the site-wide anonymization script applied to all incoming and archiving DICOM resources. This script - can also be supplemented by anonymization operations specified at the $displayManager.getSingularDisplayNameForProject().toLowerCase() level. - </p> - <p> - Note that if the site-wide anonymization is enabled, even with an empty script, it will add a deidentification - method status entry to DICOM headers. To allow DICOM files to be imported without any changes, disable site-wide - anonymization. - </p> - <p> - <label for="anonEnabled" style="width: 290px;">Site-wide Anonymization Enabled</label> - <input type="checkbox" id="anonEnabled"/> - </p> - <p><label for="anonScript">Script:</label></p> - <textarea id="anonScript" name="anonScript" rows="20" cols="80"></textarea> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="anonymization_save_button" onclick="window.anonymizationManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="anonymization_reset_button" onclick="window.anonymizationManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - var anonScript = jq('#anonScript'); - var anonEnabled = jq('#anonEnabled'); - - function toggleControlsOnAnonEnabled() { - var enabled = anonEnabled.is(':checked'); - anonScript.prop('disabled', !enabled); - } - - function dirty() { - // Add check for class manager, since setting the initial value of the radio button - // will cause the dirty() function to be called, at which point the manager is null. - if (window.anonymizationManager && !window.anonymizationManager.wasDirty()) { - window.anonymizationManager.dirtyForm(); - } - toggleControlsOnAnonEnabled(); - } - - anonScript.bind('input propertychange', dirty); - anonEnabled.change(dirty); - - function configurationAnonymizationTabChange(obj) { - if(obj.newValue.get("href")=="#anonymization") { - if(window.anonymizationManager==undefined) { - window.anonymizationManager = new SettingsTabManager('anonymization_mgmt_div', 'anonymization'); - } - toggleControlsOnAnonEnabled(); - } - } - - function addAnonymizationMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#anonymization") { - if(window.anonymizationManager==undefined) { - window.anonymizationManager = new SettingsTabManager('anonymization_mgmt_div', 'anonymization'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationAnonymizationTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addAnonymizationMgmtMonitor); - putConfigurationControls('anonymization', ['anonScript', 'anonEnabled']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/applets.vm b/src/main/webapp/xnat-templates/screens/configuration/applets.vm deleted file mode 100644 index cfd705cd..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/applets.vm +++ /dev/null @@ -1,57 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: Applet --> -<div class="mgmt_container"> - <div id="applet_mgmt_div" class="row"> - <p> - This is the site-wide applet settings script applied to the Upload Applet. - </p> - - <p> - <label for="enableProjectAppletScript">Project-Specific Applet Scripts?</label> - <input type="checkbox" id="enableProjectAppletScript" name="enableProjectAppletScript" onchange="window.appletManager.dirtyForm();" disabled /> - <small>The site-wide applet settings script can be supplemented by applet settings specified at the - $displayManager.getSingularDisplayNameForProject().toLowerCase() level if this setting is enabled.</small> - </p> - - <p><label for="appletScript"><b>Script:</b></label></p> - <textarea id="appletScript" name="appletScript" rows="20" cols="80" disabled></textarea> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="applet_save_button" onclick="window.appletManager.saveTabSettings();" /> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="applet_reset_button" onclick="window.appletManager.resetForm();" disabled/> - </div> -</div> - -<script type="text/javascript"> - - function dirtyIfClean() { - if (!window.appletManager.wasDirty()) { - window.appletManager.dirtyForm(); - } - } - - $('#enableProjectAppletScript').bind('input propertychange', dirtyIfClean); - $('#appletScript').bind('input propertychange', dirtyIfClean); - - function configurationAppletTabChange(obj) { - if(obj.newValue.get("href")=="#applets") { - if(window.appletManager==undefined) { - window.appletManager = new SettingsTabManager('applet_mgmt_div', 'applet'); - } - } - } - - function addAppletMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#applets") { - if(window.appletManager==undefined) { - window.appletManager = new SettingsTabManager('applet_mgmt_div', 'applet'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationAppletTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addAppletMgmtMonitor); - putConfigurationControls('applet', ['enableProjectAppletScript', 'appletScript']); - -</script> \ No newline at end of file diff --git a/src/main/webapp/xnat-templates/screens/configuration/dicomReceiver.vm b/src/main/webapp/xnat-templates/screens/configuration/dicomReceiver.vm deleted file mode 100644 index 18c594a0..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/dicomReceiver.vm +++ /dev/null @@ -1,74 +0,0 @@ -<!-- Title: DICOM --> -<div class="mgmt_container"> - <div id="dicom_petmr"></div> - <div id="dicom_receiver_mgmt_div"> - <p> - <label for="separatePETMR"><b>Separate PET-MR?</b></label> - <select id="separatePETMR" name="separatePETMR" onchange="XNAT.app.PETMR.update();" disabled> - <option value="">(SELECT)</option> - <option value="petmr">Create as PET/MR session</option> - <option value="pet">Create as PET session</option> - <option value="separate">Separate into PET and MR sessions</option> - </select> - <small>Should data generated by PET-MR scanners be created as a single PET/MR imaging session, created as a single PET imaging session, or separated into PET and MR sessions?</small> - <small> - <span style="color:red;font-weight:bold;">Caution:</span> Changes to this setting will take effect immediately. Once PET/MR sessions have been split into separate PET and MR sessions, the XNAT - system provides no direct means to reintegrate them into a single PET/MR session. You will usually need to resubmit the data to the system if you require a PET/MR session - after the data have been split into separate sessions. Note that you can also configure this setting at the individual project level, so you may want to limit the session - split settings to that level. - </small> - </p> - - <p> - <label for="enableDicomReceiver"><b>DICOM receiver Enabled?</b></label> <input type="checkbox" id="enableDicomReceiver" onchange="window.dicomReceiverManager.dirtyForm();" disabled /> - <small>Should the DICOM receiver listen for connections?</small> - <small><span style="color:red;font-weight:bold;">Caution:</span> Changes to this setting will take effect immediately. Before disabling the receiver, verify that there are no transmissions currently in progress.</small> - </p> - - <p>The rest of this configuration comes from <i>WEB-INF/conf/dicom-import-context.xml</i> and is not currently editable here. See the XNAT documentation for detailed information about configuration of the DICOM SCP.</p> - - <p> - <b>Port Number:</b> <span id="dcmPortLabel"></span><input type="hidden" id="dcmPort"/> - <small>This is the port number to which C-STORE SCUs (scanners and other clients sending data) should connect.</small> - </p> - - <p> - <b>DICOM AE Title(s):</b> <span id="dcmAeLabel"></span><input type="hidden" id="dcmAe"/> - <small>These are the SCP Application Entity (AE) title(s).</small> - </p> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="dicomReceiver_save_button" onclick="window.dicomReceiverManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="dicomReceiver_reset_button" onclick="window.dicomReceiverManager.resetForm();" disabled/> - </div> -</div> - -<script type="text/javascript" src="$content.getURI("scripts/config/MultiValueConfig.js")"></script> - -<script type="text/javascript"> -XNAT.app.PETMR = new MultiValueConfig("#separatePETMR", "/data/config/separatePETMR/config"); - -function configurationDicomReceiverTabChange(obj) { - if(obj.newValue.get("href")=="#dicomReceiver") { - if(window.dicomReceiverManager==undefined) { - XNAT.app.PETMR.init(); - window.dicomReceiverManager = new SettingsTabManager('dicom_receiver_mgmt_div', 'dicomReceiver'); - } - } -} - -function addDicomReceiverMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#dicomReceiver") { - if(window.dicomReceiverManager==undefined) { - XNAT.app.PETMR.init(); - window.dicomReceiverManager = new SettingsTabManager('dicom_receiver_mgmt_div', 'dicomReceiver'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationDicomReceiverTabChange); - } -} - -YAHOO.util.Event.onDOMReady(addDicomReceiverMgmtMonitor); -putConfigurationControls('dicomReceiver', ['dcmPort', 'dcmAe', 'enableDicomReceiver']); - -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/features.vm b/src/main/webapp/xnat-templates/screens/configuration/features.vm deleted file mode 100644 index 0c2968ca..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/features.vm +++ /dev/null @@ -1,112 +0,0 @@ -<!-- Title: Features --> -<style type="text/css"> - #features-controls th.featureEnabled, - #features-controls th.featureBanned { - min-width: 80px; - } - #features-controls td label { - width: auto; - } -</style> -<div class="mgmt_container"> - <div id="features_mgmt_div" class="row"> - These features are currently supported by your XNAT Server. As a site administrator, you can 'ban' any of these features - so that the features they represent will be concealed on the site. Or, you can mark features as 'on by default' so that the features will be enabled for all users - unless blocked for specific groups. Features membership is also configurable on a per project/group level. - </div> - - <div id="features_grp_config_div" class="row"> - <a href='$content.getURI("/app/template/ManageGroupTypeFeatures.vm")'>Advanced</a> - </div> - - <table id="features-controls" class="xnat-table features"> - <thead> - <tr class="header"> - <th class="featureName">Name</th> - <th class="featureDesc">Description</th> - <th class="featureEnabled">On By Default</th> - <th class="featureBanned">Banned</th> - </tr> - </thead> - <tbody> - #foreach($feature in $features) - <tr class="featureItem highlight" id=""> - <td class="featureName" nowrap>$feature.getName()</td> - <td class="featureDesc">$feature.getDescription()</td> - <td class="featureEnabled checkbox"> - <label> - <input type="checkbox" - class='featureToggle' - id="$feature.getKey()_enabled" - onchange='return manageEnable(this);' - data-feature="$feature.getKey()" - #if($feature.isOnByDefault()) checked #end - #if($feature.isBanned()) disabled #end > - </label> - </td> - <td class="featureBanned checkbox"> - <label> - <input type="checkbox" - class='featureToggle' - id="$feature.getKey()_banned" - onchange='return manageBanned(this);' - data-feature="$feature.getKey()" - #if($feature.isBanned()) checked #end > - </label> - </td> - </tr> - #end - </tbody> - </table> - -</div> - -<script> -function manageEnable(check){ - var key=$(check).attr("data-feature"); - - YAHOO.util.Connect.asyncRequest('POST',serverRoot+"/REST/services/features?XNAT_CSRF=" + csrfToken, - {success : featureSuccess, failure : featureFailure, cache : false, scope : check}, - "{'key':'" + key + "','enabled':" + check.checked + "}", - check); - - $("input.featureToggle").attr("disabled", true); -} -function manageBanned(check){ - var key=$(check).attr("data-feature"); - - YAHOO.util.Connect.asyncRequest('POST',serverRoot+"/REST/services/features?XNAT_CSRF=" + csrfToken, - {success : featureSuccess, failure : featureFailure, cache : false, scope : check}, - "{'key':'" + key + "','banned':" + check.checked + "}", - check); - - $("input.featureToggle").attr("disabled", true); - - if(check.checked){ - $("#"+key+"_enabled").removeClass("featureToggle"); - }else{ - $("#"+key+"_enabled").addClass("featureToggle"); - } -} -function featureSuccess(res){ - if(this.id.endsWith("_banned")){ - var key=$(this).attr("data-feature"); - if(this.checked){ - $("#"+key+"_enabled").removeClass("featureToggle"); - }else{ - $("#"+key+"_enabled").addClass("featureToggle"); - } - } - - $("input.featureToggle").removeAttr("disabled"); -} -function featureFailure(res){ - if(this.checked){ - this.checked=false; - }else{ - this.checked=true; - } - - $("input.featureToggle").removeAttr("disabled"); -} -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/fileSystem.vm b/src/main/webapp/xnat-templates/screens/configuration/fileSystem.vm deleted file mode 100644 index 8a0a983e..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/fileSystem.vm +++ /dev/null @@ -1,80 +0,0 @@ -<!-- Title: File System --> -<div class="mgmt_container"> - - <div id="file_system_mgmt_div"> - - <p> - <label for="archivePath">Archive Location</label> - <input size="50" type="text" id="archivePath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Location where files are permanently archived.</small> - </p> - - <p> - <label for="checksums" style="width:auto;">Checksums</label> - <input type="checkbox" id="checksums" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Indicates whether checksums should be calculated for each image file as it's archived. Activating this provides greater assurance of data integrity, but may add significant overhead to the archive process.</small> - </p> - - <p> - <label for="prearchivePath">Pre-archive Location</label> - <input size="50" type="text" id="prearchivePath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Location where files are temporarily stored before they are archived.</small> - </p> - - <p> - <label for="cachePath">Cache Location</label> - <input size="50" type="text" id="cachePath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Location where deleted files are copied to (to prevent accidental deletion of files).</small> - </p> - - <p> - <label for="buildPath">Build Location</label> - <input size="50" type="text" id="buildPath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Directory where temporarily processing information should be stored. This folder should exist, but not have any files or sub-directories in it.</small> - </p> - - <p> - <label for="ftpPath">FTP Location</label> - <input size="50" type="text" id="ftpPath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Directory where FTP Server will store files. This folder should exist, but not have any files or sub-directories in it. (Use and installation of the XNAT FTP Server is optional, but this field must be set).</small> - </p> - - <p> - <label for="pipelinePath">Pipeline Installation Location</label> - <input size="50" type="text" id="pipelinePath" onchange="window.fileSystemManager.dirtyForm();" disabled/> - <small>Location of XNAT Pipeline engine. By default, the pipeline engine is already installed in XNAT_HOME/pipeline. This location should be matched here. Change this to a different setting only if you have re-installed the Pipeline engine in another location.</small> - </p> - - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="fileSystem_save_button" onclick="window.fileSystemManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="fileSystem_reset_button" onclick="window.fileSystemManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - - - function configurationFileSystemTabChange(obj) { - if(obj.newValue.get("href")=="#fileSystem") { - if(window.fileSystemManager==undefined) { - window.fileSystemManager = new SettingsTabManager('file_system_mgmt_div', 'fileSystem'); - } - } - } - - function addFileSystemMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#fileSystem") { - if(window.fileSystemManager==undefined) { - window.fileSystemManager = new SettingsTabManager('file_system_mgmt_div', 'fileSystem'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationFileSystemTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addFileSystemMgmtMonitor); - putConfigurationControls('fileSystem', ['archivePath', 'checksums', 'prearchivePath', 'cachePath', 'buildPath', 'ftpPath', 'pipelinePath']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/mockRestConfig.vm b/src/main/webapp/xnat-templates/screens/configuration/mockRestConfig.vm deleted file mode 100644 index 28c165fd..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/mockRestConfig.vm +++ /dev/null @@ -1,44 +0,0 @@ -<!-- Title: Mock REST Calls --> -<script type="text/javascript"> - var hasDirtied = false; -</script> -<div class="mgmt_container"> - <div id="mockRestConfig_mgmt_div"> - <p> - This manages mock REST call URLs and return values. Currently you can configure this by - specifying the desired URL, a pipe or OR character ('|'), and the resulting value to be - returned as JSON. This version supports <i>no</i> parameter substitution or wild-carding, - i.e. the result will be returned literally and parameters in the REST URL will be ignored. - </p> - <p><label for="restMockCallMap">Map:</label></p> - <textarea id="restMockCallMap" name="restMockCallMap" rows="20" cols="80" onkeypress="if (!hasDirtied) { window.mockRestConfigManager.dirtyForm(); hasDirtied = true; }" disabled></textarea> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="mockRestConfig_save_button" onclick="window.mockRestConfigManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="mockRestConfig_reset_button" onclick="window.mockRestConfigManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> -function configurationRestMockCallConfigTabChange(obj) { - if(obj.newValue.get("href")=="#mockRestConfig") { - if(window.mockRestConfigManager==undefined) { - window.mockRestConfigManager = new SettingsTabManager('mockRestConfig_mgmt_div', 'mockRestConfig'); - } - } -} - -function addRestMockCallConfigMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#mockRestConfig") { - if(window.mockRestConfigManager==undefined) { - window.mockRestConfigManager = new SettingsTabManager('mockRestConfig_mgmt_div', 'mockRestConfig'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationRestMockCallConfigTabChange); - } -} - -YAHOO.util.Event.onDOMReady(addRestMockCallConfigMgmtMonitor); - putConfigurationControls('mockRestConfig', ['restMockCallMap']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/notifications.vm b/src/main/webapp/xnat-templates/screens/configuration/notifications.vm deleted file mode 100644 index 99a97ae4..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/notifications.vm +++ /dev/null @@ -1,122 +0,0 @@ -<!-- Title: Notifications --> -<div class="mgmt_container"> - - <div id="notifications_mgmt_div"> - - <p>Turn on Site-wide Alert Message? This will display a custom message on the login page for all users for a specified time.</p> - <div class="row"> - <table width="100%"> - <tr> - <td width="200"><label for="siteWideAlertStatus">Enable Alert Message</label></td> - <td> - <input type="radio" value="0" name="siteWideAlertStatus" onchange="window.notificationsManager.dirtyForm()" checked> Off<br/> - <input type="radio" value="1" name="siteWideAlertStatus" onchange="window.notificationsManager.dirtyForm()"> On (Login Page Only)<br/> - <input type="radio" value="2" name="siteWideAlertStatus" onchange="window.notificationsManager.dirtyForm()"> On (Login and Site Header)<br/> - </td> - </tr> - <tr> - <td> - <label for="siteWideAlertMessage">Alert Message</label> - </td> - <td> - <textarea name="siteWideAlertMessage" id="siteWideAlertMessage" rows="4" onchange="window.notificationsManager.dirtyForm()">Your message goes here...</textarea> - </td> - </tr> - <tr> - <td> - <label for="siteWideAlertType">Alert Type (Default: "Alert")</label> - </td> - <td> - <span class="icon icon-xs icon-alert" id="siteWideAlertTypePreview"></span> - <select name="siteWideAlertType" id="siteWideAlertType" onchange="window.notificationsManager.dirtyForm()"> - <option value="message">Message</option> - <option value="alert" selected>Alert</option> - <option value="error">Error</option> - </select> - </td> - </tr> - </table> - <script> - $(document).ready(function(){ - $("select[name=siteWideAlertType]").on("change",function(){ - var alertType = $(this).val(); - $("#siteWideAlertTypePreview").prop("class","icon icon-xs icon-"+alertType); - }); - }); - </script> - </div> - - <p>Specify subscribers for notification by username or email address. - If by email address, the email address must belong to a valid system user. - You can specify multiple users by separating the usernames or email addresses with a comma.</p> - - <div class="row"> - <table style="margin-left:50px;"> - <tr> - <th align="left"><label for="error">Errors:</label></th> - <td><input size="40" type="text" id="error" name="error" onchange="window.notificationsManager.dirtyForm();" disabled /></td> - </tr> - <tr> - <th align="left"><label for="issue">Issues:</label></th> - <td><input size="40" type="text" id="issue" name="issue" onchange="window.notificationsManager.dirtyForm();" disabled /></td> - </tr> - <tr> - <th align="left"><label for="newUser">New Users:</label></th> - <td><input size="40" type="text" id="newUser" name="newUser" onchange="window.notificationsManager.dirtyForm();" disabled /></td> - </tr> - <tr> - <th align="left"><label for="update">Updates:</label></th> - <td><input size="40" type="text" id="update" name="update" onchange="window.notificationsManager.dirtyForm();" disabled /></td> - </tr> - </table> - </div> - - <p> - <label for="emailAllowNonuserSubscribers">Allow non-user subscribers?</label> - <input type="checkbox" id="emailAllowNonuserSubscribers" name="emailAllowNonuserSubscribers" onchange="window.siteInfoManager.dirtyForm();" /> - <small> - Indicates whether this site should restrict email addresses for site notifications to addresses that are - associated with valid active users of the XNAT installation? If turned on, the site is more secure from - exploitation as a spam relay, but restricts the addresses that can be used when alerting administrators - to system events. - </small> - </p> - - <p> - <label for="smtp.enabled">Enable any SMTP services?</label> - <input type="checkbox" id="smtp.enabled" name="smtp.enabled" onchange="window.siteInfoManager.dirtyForm();" /> - <small> - Indicates whether this site should attempt to use smtp services. Disabling will prevent XNAT from attempting to send emails. - </small> - </p> - - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="notifications_save_button" onclick="window.notificationsManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="notifications_reset_button" onclick="window.notificationsManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - function configurationNotificationsTabChange(obj) { - if(obj.newValue.get("href")=="#notifications") { - if(window.notificationsManager==undefined) { - window.notificationsManager = new SettingsTabManager('notifications_mgmt_div', 'notifications'); - } - } - } - - function addNotificationsMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#notifications") { - if(window.notificationsManager==undefined) { - window.notificationsManager = new SettingsTabManager('notifications_mgmt_div', 'notifications'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationNotificationsTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addNotificationsMgmtMonitor); - putConfigurationControls('notifications', ['siteWideAlertStatus','siteWideAlertMessage','siteWideAlertType','error', 'issue', 'newUser', 'update', 'emailAllowNonuserSubscribers','smtp.enabled']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/petTracers.vm b/src/main/webapp/xnat-templates/screens/configuration/petTracers.vm deleted file mode 100644 index 45c2518d..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/petTracers.vm +++ /dev/null @@ -1,51 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: PET Tracers --> -<div class="mgmt_container"> - <div id="tracers_mgmt_div" class="row"> - <p> - This is the site-wide list of PET tracers. List entries should be separated by whitespace. This list can also be replaced - at the $displayManager.getSingularDisplayNameForProject().toLowerCase() level. - </p> - <p><label for="tracerList">Tracers:</label></p> - <textarea id="tracerList" name="tracerList" rows="20" cols="80"></textarea> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="tracers_save_button" onclick="window.petTracerManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="tracers_reset_button" onclick="window.petTracerManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - var tracerList = jq('#tracerList'); - - function dirty() { - if (window.petTracerManager && !window.petTracerManager.wasDirty()) { - window.petTracerManager.dirtyForm(); - } - } - - tracerList.bind('input propertychange', dirty); - - function configurationTracerTabChange(obj) { - if(obj.newValue.get("href")=="#petTracers") { - if(window.petTracerManager==undefined) { - window.petTracerManager = new SettingsTabManager('tracers_mgmt_div', 'tracers'); - } - } - } - - function addTracerMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#petTracers") { - if(window.petTracerManager==undefined) { - window.petTracerManager = new SettingsTabManager('tracers_mgmt_div', 'tracers'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationTracerTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addTracerMgmtMonitor); - putConfigurationControls('tracers', ['tracerList']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/registration.vm b/src/main/webapp/xnat-templates/screens/configuration/registration.vm deleted file mode 100644 index 56260f58..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/registration.vm +++ /dev/null @@ -1,62 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: Registration --> -<div class="mgmt_container"> - - <div id="registration_mgmt_div"> - - <p> - <label for="requireLogin">Require Login?</label> - <input type="checkbox" id="requireLogin" onchange="window.registrationManager.dirtyForm();" disabled /> - <small>If true, then only registered users will be able to access your site. If false, anyone visiting - your site will automatically be logged in as 'guest' with access to public data.</small> - </p> - - <p> - <label for="enableNewRegistrations">Auto-enable User Accounts?</label> - <input type="checkbox" id="enableNewRegistrations" onchange="window.registrationManager.dirtyForm();" disabled /> - <small>If true, user accounts will be enabled automatically when the user registers. Users will be able to access the site and any 'public' - $displayManager.getPluralDisplayNameForProject().toLowerCase() immediately. If false, the site administrator will be required to manually - enable user accounts. Either way the administrator receives an email notification when a user registers.</small> - </p> - - <p> - <label for="emailVerification">User Email Verification?</label> - <input type="checkbox" id="emailVerification" onchange="window.registrationManager.dirtyForm();" disabled /> - <small>If true, users will receive an email after registering for an account and must click a link in the email to verify their - email address before they are able to use their account. If false, no verification emails will be sent and users will not be - required to verify their email before using their account. Either way the administrator receives an email notification when a - user registers.</small> - </p> - - </div> - - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="registration_save_button" onclick="window.registrationManager.saveTabSettings();"/> - <input type="button" class="reset resetButton" value="Reset" name="eventSubmit_doReset" id="registration_reset_button" onclick="window.registrationManager.resetForm();" disabled/> - </div> - -</div> - - -<script type="text/javascript"> -function configurationRegistrationTabChange(obj) { - if(obj.newValue.get("href")=="#registration") { - if(window.registrationManager==undefined) { - window.registrationManager = new SettingsTabManager('registration_mgmt_div', 'registration'); - } - } -} - -function addRegistrationMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#registration") { - if(window.registrationManager==undefined) { - window.registrationManager = new SettingsTabManager('registration_mgmt_div', 'registration'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationRegistrationTabChange); - } -} - -YAHOO.util.Event.onDOMReady(addRegistrationMgmtMonitor); - putConfigurationControls('registration', ['requireLogin', 'enableNewRegistrations', 'emailVerification']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/scanTypeMapping.vm b/src/main/webapp/xnat-templates/screens/configuration/scanTypeMapping.vm deleted file mode 100644 index 206ac52c..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/scanTypeMapping.vm +++ /dev/null @@ -1,56 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: Scan Type Mapping --> -<div class="mgmt_container"> - <div id="scanTypeMapping_mgmt_div" class="row"> - <p> - This is the site level setting for scan type mapping. It will apply to all $displayManager.getPluralDisplayNameForProject().toLowerCase() that - do not specifically choose a setting. - </p> - <TABLE cellpadding="5" cellspacing="0"> - <TR> - <TD NOWRAP><input id="yes_scan_type_mapping" type="radio" name="scanTypeMapping" value="true" checked="checked" onchange="dirty()"/> YES</TD> - <TD>Incoming scans will have their type attribute set based on historical scan type mapping data.</TD> - </TR> - <TR> - <TD NOWRAP><input id="no_scan_type_mapping" type="radio" name="scanTypeMapping" value="false" onchange="dirty()"/> NO</TD> - <TD>Incoming scans will have their type attribute set to be identical to their series description.</TD> - </TR> - </TABLE> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="scanTypeMapping_save_button" onclick="window.scanTypeMappingManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="scanTypeMapping_reset_button" onclick="window.scanTypeMappingManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - function dirty() { - if (window.scanTypeMappingManager && !window.scanTypeMappingManager.wasDirty()) { - window.scanTypeMappingManager.dirtyForm(); - } - } - - function configurationScanTypeMappingTabChange(obj) { - if(obj.newValue.get("href")=="#scanTypeMapping") { - if(window.scanTypeMappingManager==undefined) { - window.scanTypeMappingManager = new SettingsTabManager('scanTypeMapping_mgmt_div', 'scanTypeMapping'); - var asdfasg = 2; - } - } - } - - function addScanTypeMappingMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#scanTypeMappingDefault") { - if(window.scanTypeMappingManager==undefined) { - window.scanTypeMappingManager = new SettingsTabManager('scanTypeMapping_mgmt_div', 'scanTypeMapping'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationScanTypeMappingTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addScanTypeMappingMgmtMonitor); - putConfigurationControls('scanTypeMapping', ['scanTypeMapping']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/security.vm b/src/main/webapp/xnat-templates/screens/configuration/security.vm deleted file mode 100644 index 3f1eddbe..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/security.vm +++ /dev/null @@ -1,184 +0,0 @@ -<!-- Title: Security --> -<div class="mgmt_container"> - - <div id="security_mgmt_div"> - - <script> - - function makeDirty(){ - if (window.securityManager) { - window.securityManager.dirtyForm(); - } - } - - function changePasswordExpirationType(){ - makeDirty(); - // using double underscores for jQuery object vars - var __interval_span = jq('#passwordExpirationIntervalSpan'); - var __date_span = jq('#passwordExpirationDateSpan'); - if (jq('input[name="passwordExpirationType"]:checked').val() == 'Interval'){ - __interval_span.show(); - __date_span.hide(); - } else { - __interval_span.hide(); - __date_span.show(); - } - } - - function validatePasswordExpiration() { - makeDirty(); - // using double underscores for jQuery object vars - var __interval = jq('#passwordExpirationInterval'); - var __date = jq('#passwordExpirationDate'); - var use_interval = true; - var valid_date = true ; - var check_date ; - if (jq('input[name="passwordExpirationType"]:checked').val() === 'Interval'){ - if (!__interval.val()) { - __interval.val('0'); - } - } - else { - // check the value of the Expiration Date input using US format - check_date = XNAT.app.checkDateInput(__date,'us'); - valid_date = check_date.valid ; - use_interval = false ; - } - if (use_interval && !__interval.val().match(/^\d+$/)) { - xModalMessage('Note','The password expiration interval must consist only of digits.','OK',{action:function(){__interval.val('').focus()}}); - return false ; - } - else if (!valid_date){ - return false ; - } - else { - if (!__date.val() || __date.val() == '__/__/____' || __date.val() == ' / / ') { - // is it better to put in zeros or 01/01/1970? - // answer: 01/01/1970 - then it won't freak out if using the interval - __date.val('01/01/1970'); - window.securityManager.saveTabSettings(); - } - else { - window.securityManager.saveTabSettings(); - } - } - } - - </script> - - <p> - <label for="enableCsrfToken">Enable CSRF Token?</label> - <input type="checkbox" id="enableCsrfToken" onchange="makeDirty();" /> - <small>Should this site require the use of a token to prevent CSRF attacks on POST, PUT, and DELETEs?</small> - <br/> - <label for="enableCsrfEmail">Enable CSRF Email Alerts?</label> - <input type="checkbox" id="enableCsrfEmail" onchange="makeDirty();" /> - <small>Should this site send an email to the site admin whenever a CSRF attack is attempted?</small> - </p> - - <p> - <label for="restrictUserListAccessToAdmins" style="width: 290px;">Restrict user list access to site administrators?</label> - <input type="checkbox" id="restrictUserListAccessToAdmins" onchange="makeDirty();" /> - <small> - Should this site restrict access to the list of system users to site administrators only? If turned on, - the site is more secure, but this restricts project owners from being able to administer users in their - projects directly. - </small> - </p> - - <p> - <label for="UI.allow-non-admin-project-creation" style="width: 290px;">Allow non-administrators to create projects?</label> - <input type="checkbox" id="UI.allow-non-admin-project-creation" onchange="makeDirty();" /> - <small> - Should this site allow non-administrator users to create new projects? If turned on, the site is more secure, but this - can make it more difficult for regular users to create new projects for their research efforts. - </small> - </p> - - <p> - <label for="requireSaltedPasswords" style="width: 290px;">Require passwords to be salted?</label> - <input type="checkbox" id="requireSaltedPasswords" onchange="makeDirty();" /> - <small> - Should this site require that all stored user passwords have been salted? If turned on, the site will - store passwords more securely, but some users may be prompted to change their current passwords so - that they can be updated. - </small> - </p> - - <div class="row"> - ## yeah, it's a table. so sue me. - <table style="display:inline-block;" cellspacing=0 cellpadding=0> - <tr> - <td style="white-space:nowrap;vertical-align:top;padding-right:20px;"> - <label for="passwordExpiration" style="width:auto;white-space:nowrap;">Password Expiration</label> - </td> - <td style="white-space:nowrap;vertical-align:top;padding-right:10px;"> - <input type="radio" name="passwordExpirationType" id="passwordExpirationTypeInterval" value="Interval" onchange="changePasswordExpirationType();" checked="checked"> - <label for="passwordExpirationTypeInterval" style="width:50px;"> Interval</label> - <br/> - <input type="radio" name="passwordExpirationType" id="passwordExpirationTypeDate" value="Date" onchange="changePasswordExpirationType();"> - <label for="passwordExpirationTypeDate" style="width:50px;"> Date</label> - </td> - <td style="vertical-align:top;"> - <span id="passwordExpirationIntervalSpan"> - <input size="30" type="text" id="passwordExpirationInterval" onchange="makeDirty();"/> - <small>The maximum duration (in days) that a user's password will function before it is considered to have expired and must be changed. Set as 0 to disable password expiration.</small> - </span> - <span id="passwordExpirationDateSpan" style="display: none;"> - <span class="datepicker single us today" data-value="" data-validate="onblur" data-input-id="passwordExpirationDate" data-input-name="passwordExpirationDate"></span> - <script type="text/javascript"> - jq(function(){ - var __datepicker = jq('#passwordExpirationDateSpan').find('.datepicker'); - XNAT.app.datePicker.init(__datepicker); - ##insertCalendar(document.getElementById("passwordExpirationDate"), "Password Expiration Date"); - ##jq('#cal_passwordExpirationDate').style.verticalAlign='bottom'; - jq('#passwordExpirationDateSpan').on('change focus','#passwordExpirationDate',function(){makeDirty()}); - jq('#passwordExpirationDateSpan').on('click','a.selector, a.today',function(){makeDirty()}); - }); - </script> - ##<input type="text" id="passwordExpirationDate" name="passwordExpirationDate" onchange="window.securityManager.dirtyForm();" onblur="validateExpirationDate()"/> - ##<script type="text/javascript">insertCalendar(document.getElementById("passwordExpirationDate"), "Password Expiration Date"); jq('#cal_passwordExpirationDate').style.verticalAlign='bottom';</script> - <small>All passwords created or set before this date will be considered to have expired and must be changed. - Useful in circumstances when mass changes in password policy are put into effect. - Dates should be formatted MM/DD/YYYY.</small> - </span> - <style>#cal_passwordExpirationDate, #passwordExpirationDate { vertical-align: bottom }</style> - </td> - </tr> - </table> - - </div> - - - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="security_save_button" onclick="validatePasswordExpiration();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="security_reset_button" onclick="window.securityManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - function configurationSecurityTabChange(obj) { - if(obj.newValue.get("href")=="#security") { - if(window.securityManager==undefined) { - window.securityManager = new SettingsTabManager('security_mgmt_div', 'security'); - } - } - } - - function addSecurityMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#security") { - if(window.securityManager==undefined) { - window.securityManager = new SettingsTabManager('security_mgmt_div', 'security'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationSecurityTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addSecurityMgmtMonitor); - putConfigurationControls('security', ['enableCsrfToken', 'enableCsrfEmail', 'restrictUserListAccessToAdmins', 'UI.allow-non-admin-project-creation', 'requireSaltedPasswords', 'passwordExpirationType', 'passwordExpirationInterval', 'passwordExpirationDate']); - -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/seriesImportFilter.vm b/src/main/webapp/xnat-templates/screens/configuration/seriesImportFilter.vm deleted file mode 100644 index 625e34ae..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/seriesImportFilter.vm +++ /dev/null @@ -1,94 +0,0 @@ -#* @vtlvariable name="displayManager" type="org.nrg.xdat.display.DisplayManager" *# -<!-- Title: Series Import Filter --> -<div class="mgmt_container"> - <div id="seriesImportFilter_mgmt_div" class="row"> - <p> - This is the site-wide series import filter applied to all incoming and archiving DICOM resources. This - filter can also be supplemented by series import filters specified at the project level. - </p> - <p> - <label for="seriesImportFilterEnabled" style="vertical-align: top;">Enable Filter:</label> - <span style="display: inline-block; vertical-align: top;"> - <input type="checkbox" name="seriesImportFilterEnabled" id="seriesImportFilterEnabled" /> - </span><br/> - <label for="seriesImportFilterMode" style="vertical-align: top;">Filter Mode:</label> - <span style="display: inline-block; vertical-align: top;"> - <select name="seriesImportFilterMode" id="seriesImportFilterMode" disabled> - <option value="whitelist">Whitelist</option> - <option value="blacklist">Blacklist</option> - <option value="modalityMap">Modality Map</option> - </select> - </span><br/> - <small> - Creating a whitelist means that <i>only</i> DICOM series with a series description that matches one of - series filter patterns will be considered by XNAT import tools such as the upload applet. Creating a - blacklist means that all DICOM series will be considered <i>except</i> for series that have one of the - specified series filter patterns. A modality map lets you specify boolean expressions in JavaScript that - can use DICOM header values from incoming DICOM objects to decide the appropriate modality for the - destination session. - </small> - </p> - <p> - <label for="seriesImportFilterList">Series Filter Patterns:</label><br/> - <textarea id="seriesImportFilterList" name="seriesImportFilterList" rows="20" cols="80" disabled placeholder="Enter white- or blacklisted series filters separated by newlines, e.g. <b>localizer</b> for localizer series."></textarea><br/> - </p> - <small> - The series filters can be written as exact string matches, but also can be regular expressions. The regular expressions are evaluated using the - <a href="http://docs.oracle.com/javase/tutorial/essential/regex/" target="_blank">Java regular expression syntax</a>. These expressions are - case-insensitive, i.e. the string "SAG LOCALIZER" will also match "Sag Localizer". - </small> - </div> - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="seriesImportFilter_save_button" onclick="window.seriesImportFilterManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="seriesImportFilter_reset_button" onclick="window.seriesImportFilterManager.resetForm();" disabled/> - </div> -</div> - - -<script type="text/javascript"> - - var filterList = jq('#seriesImportFilterList'); - var filterMode = jq('#seriesImportFilterMode'); - var filterEnabled = jq('#seriesImportFilterEnabled'); - - function toggleControlsOnFilterEnabled() { - var enabled = filterEnabled.is(':checked'); - filterList.prop('disabled', !enabled); - filterMode.prop('disabled', !enabled); - } - - function dirty() { - // Add check for class manager, since setting the initial value of the radio button - // will cause the dirty() function to be called, at which point the manager is null. - if (window.seriesImportFilterManager && !window.seriesImportFilterManager.wasDirty()) { - window.seriesImportFilterManager.dirtyForm(); - } - toggleControlsOnFilterEnabled(); - } - - filterList.bind('input propertychange', dirty); - filterMode.change(dirty); - filterEnabled.change(dirty); - - function configurationSeriesImportFilterTabChange(obj) { - if(obj.newValue.get("href")=="#seriesImportFilter") { - if(window.seriesImportFilterManager==undefined) { - window.seriesImportFilterManager = new SettingsTabManager('seriesImportFilter_mgmt_div', 'seriesImportFilter'); - } - toggleControlsOnFilterEnabled(); - } - } - - function addSeriesImportFilterMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#seriesImportFilter") { - if(window.seriesImportFilterManager==undefined) { - window.seriesImportFilterManager = new SettingsTabManager('seriesImportFilter_mgmt_div', 'seriesImportFilter'); - } - } else { - window.configurationTabView.subscribe("activeTabChange", configurationSeriesImportFilterTabChange); - } - } - - YAHOO.util.Event.onDOMReady(addSeriesImportFilterMgmtMonitor); - putConfigurationControls('seriesImportFilter', ['seriesImportFilterEnabled', 'seriesImportFilterMode', 'seriesImportFilterList']); -</script> diff --git a/src/main/webapp/xnat-templates/screens/configuration/siteInfo.vm b/src/main/webapp/xnat-templates/screens/configuration/siteInfo.vm deleted file mode 100644 index 5aa92140..00000000 --- a/src/main/webapp/xnat-templates/screens/configuration/siteInfo.vm +++ /dev/null @@ -1,208 +0,0 @@ -#* @vtlvariable name="initialize" type="java.lang.Boolean" *# -#* @vtlvariable name="link" type="org.apache.turbine.services.pull.tools.TemplateLink" *# -<!-- title: Site Information --> -<!-- divName: siteInfo --> -<div class="mgmt_container"> - - <div id="site_info_mgmt_div"> - <script src="$content.getURI("scripts/lib/epicEditor/js/epiceditor.js")"></script> - <script> - /* XNAT uses the Epic Editor markdown editor. - * Documentation: http://epiceditor.com/ - * Source: https://github.com/OscarGodson/EpicEditor - */ - - // configure markdown editor for site description - jq(document).ready(function(){ - var editor = new EpicEditor({ basePath: "$content.getURI("scripts/lib/epicEditor")", textarea: "siteDescriptionText", autogrow: true }).load(); - }); - - function changeSiteDescriptionType(radioEl){ - var text = $('#epiceditor_container'); - var page = $('#siteDescriptionPage'); - if (window.siteInfoManager) { - window.siteInfoManager.dirtyForm(); - } - if($(radioEl).val() == 'Text'){ - text.show(); - page.hide(); - } else { - page.show(); - text.hide(); - } - }; - </script> - - <div class="row"> - <label for="siteId">Site ID</label> - <input size="30" type="text" id="siteId" onchange="this.value=stringCamelCaps(this.value); window.siteInfoManager.dirtyForm();" /> - <small>The id used to refer to this site (also used to generate database ids). No spaces or non-alphanumeric characters. It should be a short, - one-word name or acronym which describes your site.</small> - </div> - <div class="row"> - <table> - <tr valign="top"> - <td><label for="siteDescription" style="vertical-align: top;">Site Description <br />(Displayed on Login Page)</label></td> - <td><input type="radio" name="siteDescriptionType" id="siteDescriptionTypePage" value="Page" onchange="changeSiteDescriptionType(this);"> - <label for="siteDescriptionTypePage" style="width:50px;"> Page</label> - <input size="30" type="text" name="siteDescriptionPage" id="siteDescriptionPage" onchange="window.siteInfoManager.dirtyForm();" style="display: none;" /> - <br /> - <input type="radio" name="siteDescriptionType" id="siteDescriptionTypeText" value="Text" onchange="changeSiteDescriptionType(this);" checked="checked"> - <label for="siteDescriptionTypeText" style="width:50px;"> Text</label> - </td> - </tr> - </table> - - <div id="epiceditor_container"> - <small>XNAT allows you to use <a href="https://help.github.com/articles/github-flavored-markdown/" target="_blank">GitHub-flavored Markdown</a> to create and format your own site description. A tutorial for basic usage can be found here: <a href="https://help.github.com/articles/markdown-basics" target="_blank">https://help.github.com/articles/markdown-basics</a>. </small> - <textarea name="siteDescriptionText" id="siteDescriptionText" class="hidden" onchange="window.siteInfoManager.dirtyForm();"></textarea> - <div id="epiceditor" style="margin: 1em 0;"></div> - </div> - </div> - - <div class="row"> - <label for="siteUrl">Site URL</label> - <input size="30" type="text" id="siteUrl" onchange="window.siteInfoManager.dirtyForm();" /> - <small>The address you want visible to users in emails, and other external links. This should be a functional address (i.e. if the user pasted - this address in their web browser, they should come to the site). localhost only works if the web browser is located on the same machine. - You are required to guarantee that this address is functional for reaching the site.</small> - </div> - - <div class="row"> - <label for="siteAdminEmail">Site Admin Email Address</label> - <input size="30" type="text" id="siteAdminEmail" onchange="window.siteInfoManager.dirtyForm();" /> - <small>The administrative email account to receive system emails. This address will receive frequent emails on system events, such as errors, - processing completion, new user registration and so on. The number of emails can be configured on the - <a class="iframe-dialog" href="$link.setPage("XDATScreen_emailSpecifications.vm").addPathInfo("popup","true")">Administer > More Options... > Set email settings</a> dialog.</small> - </div> - - <div class="row"> - <label for="siteLoginLanding">Site Login Landing Page</label> - <input size="30" type="text" name="siteLoginLanding" id="siteLoginLanding" onchange="window.siteInfoManager.dirtyForm();" /> - <label for="siteLandingLayout" style="padding-left: 20px; width: 50px;">Layout</label> - <select name="siteLandingLayout" id="siteLandingLayout" value="menu" onchange="window.siteInfoManager.dirtyForm();"> - <option value="/Index.vm">Menu</option> - <option value="/NoMenu.vm">No Menu</option> - <option value="/Noninteractive.vm">Non-Interactive</option> - </select> - <small>The page and default layout users will land on immediately after logging in.</small> - <br/> - <label for="siteHome">Site Home Page</label> - <input size="30" type="text" name="siteHome" id="siteHome" onchange="window.siteInfoManager.dirtyForm();" /> - <label for="siteHomeLayout" style="padding-left: 20px; width: 50px;">Layout</label> - <select name="siteHomeLayout" id="siteHomeLayout" value="menu" onchange="window.siteInfoManager.dirtyForm();"> - <option value="/Index.vm">Menu</option> - <option value="/NoMenu.vm">No Menu</option> - <option value="/Noninteractive.vm">Non-Interactive</option> - </select> - <small>The page and default layout users will land on by clicking the "Home" link in the menu bar.</small> - </div> - - <div class="row"> - <label for="showapplet">Applet Link</label> - <input type="checkbox" id="showapplet" onchange="window.siteInfoManager.dirtyForm();" /> - <small>Should a prominent link to the applet show up on the left bar of the index page?</small> - </div> - - <div class="row"> - <label for="UI.debug-extension-points" style="width: 290px;">Show points in UI where new VM content can be added dynamically. (development only)</label> - <input type="checkbox" id="UI.debug-extension-points" onchange="window.siteInfoManager.dirtyForm();" /> - <small> - Should this site display highlighted divs at every point where new VM content can be dynamically added? If turned on, the divs will show up - listing the directory where new VMs can be added and will be dynamically added into the UI. FYI, new dynamically-added VMs often require a - server restart to be included. This setting should never be enabled on a production server. - </small> - </div> - - </div> - - <div class="buttons"> - <input type="button" class="submit" value="Save" name="eventSubmit_doPerform" id="siteInfo_save_button" onclick="window.siteInfoManager.saveTabSettings();"/> - <input type="button" class="reset" value="Reset" name="eventSubmit_doReset" id="siteInfo_reset_button" onclick="window.siteInfoManager.resetForm();" disabled/> - </div> - -</div> - -<script type="text/javascript"> - - jq('a.iframe-dialog').click(function(e){ - e.preventDefault(); - var link = this.href; - XNAT.ui.dialog.iframe({ - src: link, - width: '80%', - height: '80%', - minHeight: 540, - minWidth: 720, - maxWidth: 960, - title: link, - titleStyle: 'visibility:hidden;opacity:0;', - onClose: function(){ - xmodal.loading.open('Please wait...'); - window.top.location.reload(true); - }, - okLabel: 'Done' - //footer: false - }); - }); - - - function configurationSiteInfoTabChange(obj) { - if(obj.newValue.get("href")=="#siteInfo") { - initializeSiteInfoMgmtTab(); - } - } - - function addSiteInfoMgmtMonitor(){ - if(window.configurationTabView.get("activeTab").get("href")=="#siteInfo") { - initializeSiteInfoMgmtTab(); - } else { - window.configurationTabView.subscribe("activeTabChange", configurationSiteInfoTabChange); - } - } - - function initializeSiteInfoMgmtTab() { - if(window.siteInfoManager==undefined) { - if (window.initializing) { - var postLoad = function() { - if(window.anonymizationManager==undefined) { - window.anonymizationManager = new SettingsTabManager('anonymization_mgmt_div', 'anonymization'); - } - if(window.appletManager==undefined) { - window.appletManager = new SettingsTabManager('applet_mgmt_div', 'applet'); - } - if(window.dicomReceiverManager==undefined) { - window.dicomReceiverManager = new SettingsTabManager('dicom_receiver_mgmt_div', 'dicomReceiver'); - } - if(window.fileSystemManager==undefined) { - window.fileSystemManager = new SettingsTabManager('file_system_mgmt_div', 'fileSystem'); - } - if(window.securityManager==undefined) { - window.securityManager = new SettingsTabManager('security_mgmt_div', 'security'); - } - if(window.notificationsManager==undefined) { - window.notificationsManager = new SettingsTabManager('notifications_mgmt_div', 'notifications'); - } - if(window.registrationManager==undefined) { - window.registrationManager = new SettingsTabManager('registration_mgmt_div', 'registration'); - } - if(window.seriesImportFilterManager==undefined) { - window.seriesImportFilterManager = new SettingsTabManager('seriesImportFilter_mgmt_div', 'seriesImportFilter'); - } - if(window.petTracerManager==undefined) { - window.petTracerManager = new SettingsTabManager('tracers_mgmt_div', 'tracers'); - } - if(window.scanTypeMappingManager==undefined) { - window.scanTypeMappingManager = new SettingsTabManager('scanTypeMapping_mgmt_div', 'scanTypeMapping'); - } - }; - } - window.siteInfoManager = new SettingsTabManager('site_info_mgmt_div', 'siteInfo', postLoad); - } else { - window.siteInfoManager = new SettingsTabManager('site_info_mgmt_div', 'siteInfo'); - } - } - - YAHOO.util.Event.onDOMReady(addSiteInfoMgmtMonitor); - putConfigurationControls('siteInfo', ['siteId','UI.debug-extension-points', 'siteDescriptionType', 'siteDescriptionText', 'siteDescriptionPage', 'siteUrl', 'siteAdminEmail', 'siteLoginLanding', 'siteLandingLayout', 'siteHome', 'siteHomeLayout', 'showapplet']); -</script> -- GitLab