diff options
Diffstat (limited to 'modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui')
4 files changed, 514 insertions, 0 deletions
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java new file mode 100644 index 00000000..96d58def --- /dev/null +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.asitplus.eidas.specific.core.gui; + +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.AbstractVelocityGuiFormBuilderImpl; + +@Service("velocityGUIBuilderImpl") +public class DefaultVelocityGuiBuilderImpl extends AbstractVelocityGuiFormBuilderImpl { + private static final Logger log = LoggerFactory.getLogger(DefaultVelocityGuiBuilderImpl.class); + + private static final String CLASSPATH_HTMLTEMPLATES_DIR = "templates/"; + + public DefaultVelocityGuiBuilderImpl() throws GuiBuildException { + super(); + + } + + @Override + protected InputStream getInternalTemplate(IVelocityGuiBuilderConfiguration config) + throws GuiBuildException { + final String viewName = config.getViewName(); + log.debug("GUI template:" + viewName + " is not found in configuration directory. " + + " Load template from project library ... "); + final String pathLocation = getInternalClasspathTemplateDir(config, CLASSPATH_HTMLTEMPLATES_DIR) + + viewName; + try { + final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(pathLocation); + return is; + + } catch (final Exception e1) { + log.error("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1); + throw new GuiBuildException("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1); + + } + } + + @Override + public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config, + String loggerName) throws GuiBuildException { + return MediaType.TEXT_HTML_VALUE; + + } + +} diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java new file mode 100644 index 00000000..62a0005d --- /dev/null +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java @@ -0,0 +1,69 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.asitplus.eidas.specific.core.gui; + +import java.net.MalformedURLException; +import java.net.URI; + +import javax.annotation.Nonnull; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; + +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; + +@Service("GUIBuilderConfigurationFactory") +public class GuiBuilderConfigurationFactory implements IGuiBuilderConfigurationFactory { + @Autowired(required = true) private IConfiguration basicConfig; + @Autowired(required = true) private ResourceLoader resourceLoader; + + @Override + public IGuiBuilderConfiguration getDefaultErrorGui(String authUrl) { + return new StaticGuiBuilderConfiguration(basicConfig, authUrl, MsEidasNodeConstants.TEMPLATE_HTML_ERROR, + null, resourceLoader); + } + + @Override + public IVelocityGuiBuilderConfiguration getSpSpecificSaml2PostConfiguration(IRequest pendingReq, + String viewName, URI configRootContextDir) + throws MalformedURLException { + return new StaticGuiBuilderConfiguration(basicConfig, pendingReq, + MsEidasNodeConstants.TEMPLATE_HTML_PVP_POSTBINDING, null, resourceLoader); + } + + @Override + public IGuiBuilderConfiguration getDefaultIFrameParentHopGui(IRequest pendingReq, + @Nonnull String endpoint, @Nonnull String errorId) { + //TODO: implement if iFrame to parent hop is needed + throw new RuntimeException("Operation not supported yet."); + + } + +} diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java new file mode 100644 index 00000000..0fd85d3d --- /dev/null +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java @@ -0,0 +1,148 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.asitplus.eidas.specific.core.gui; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.GroupDefinition; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; + +public class StaticGuiBuilderConfiguration extends AbstractGuiFormBuilderConfiguration implements + IVelocityGuiBuilderConfiguration, ModifyableGuiBuilderConfiguration { + private static final Logger log = LoggerFactory.getLogger(StaticGuiBuilderConfiguration.class); + + private IRequest pendingReq = null; + private IConfiguration basicConfig = null; + private ResourceLoader resourceLoader; + + /** + * Static resource configuration for GUI Builder implementations. + * + * @param basicConfig basicConfig + * @param authUrl Public URL of the application + * @param viewName Name of the template + * @param formSubmitEndpoint Form Submit end-point, if template contains a form. + * @param resourceLoader Spring ResourceLoader implementation + */ + public StaticGuiBuilderConfiguration(IConfiguration basicConfig, String authUrl, String viewName, + String formSubmitEndpoint, ResourceLoader resourceLoader) { + super(authUrl, viewName, formSubmitEndpoint); + this.basicConfig = basicConfig; + this.resourceLoader = resourceLoader; + + } + + /** + * Static resource configuration for GUI Builder implementations. + * + * @param basicConfig Application configuration + * @param pendingReq Current pending request + * @param viewName Name of the template + * @param formSubmitEndpoint Form Submit end-point, if template contains a form. + * @param resourceLoader Spring ResourceLoader implementation + */ + public StaticGuiBuilderConfiguration(IConfiguration basicConfig, IRequest pendingReq, String viewName, + String formSubmitEndpoint, ResourceLoader resourceLoader) { + super(pendingReq.getAuthUrl(), viewName, formSubmitEndpoint); + this.pendingReq = pendingReq; + this.basicConfig = basicConfig; + this.resourceLoader = resourceLoader; + + } + + @Override + public String getClasspathTemplateDir() { + return MsEidasNodeConstants.CLASSPATH_TEMPLATE_DIR; + + } + + @Override + public String getDefaultContentType() { + return null; + + } + + @Override + public InputStream getTemplate(String viewName) { + final String templateUrl = MsEidasNodeConstants.FILESYSTEM_TEMPLATE_DIR + viewName; + try { + final String absUrl = FileUtils.makeAbsoluteUrl(templateUrl, this.basicConfig + .getConfigurationRootDirectory()); + log.debug("Load template URL for view: " + viewName + " from: " + absUrl); + Resource resource = resourceLoader.getResource(absUrl); + return resource.getInputStream(); + + } catch (IOException e) { + log.info("Can can build filesytem path to template: " + templateUrl + + " Reason: " + e.getMessage()); + + } + + return null; + } + + @Override + public void putCustomParameterWithOutEscaption(GroupDefinition group, String key, Object value) { + setViewParameter(getFromGroup(), key, value); + + } + + @Override + public void putCustomParameter(GroupDefinition group, String key, String value) { + setViewParameter(getFromGroup(), key, StringEscapeUtils.escapeHtml4(value)); + + } + + @Override + protected void putSpecificViewParameters() { + if (pendingReq != null) { + setViewParameter(getFromGroup(), PARAM_PENDINGREQUESTID, StringEscapeUtils.escapeHtml4(pendingReq + .getPendingRequestId())); + setViewParameter(getFromGroup(), PARAM_PENDINGREQUESTID_DEPRECATED, StringEscapeUtils.escapeHtml4( + pendingReq.getPendingRequestId())); + + } + + } + + @Override + protected GroupDefinition getFromGroup() { + return null; + + } + +} diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/config/StaticResourceConfiguration.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/config/StaticResourceConfiguration.java new file mode 100644 index 00000000..ea080497 --- /dev/null +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/config/StaticResourceConfiguration.java @@ -0,0 +1,220 @@ +/* + * Copyright 2019 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.asitplus.eidas.specific.core.gui.config; + +import java.net.MalformedURLException; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.CookieLocaleResolver; +import org.thymeleaf.templateresolver.FileTemplateResolver; + +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; + +/** + * Spring configurator for Web resources. + * + * @author tlenz + * + */ +@Configuration +public class StaticResourceConfiguration implements WebMvcConfigurer { + private static final Logger log = LoggerFactory.getLogger(StaticResourceConfiguration.class); + private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { + "/" + }; + + private static final String DEFAULT_MESSAGE_SOURCE = "classpath:properties/status_messages"; + + @Autowired + private IConfiguration basicConfig; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + final String staticResources = basicConfig.getBasicConfiguration( + MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_STATIC_PATH); + try { + if (StringUtils.isNotEmpty(staticResources)) { + String absPath = FileUtils.makeAbsoluteUrl(staticResources, basicConfig + .getConfigurationRootDirectory()); + if (!absPath.endsWith("/")) { + absPath += "/"; + } + + registry.addResourceHandler("/static/**").addResourceLocations(absPath); + log.info("Add Ressourcefolder: " + absPath + " for static Web content"); + + } else { + log.debug("No Ressourcefolder for static Web content"); + } + + } catch (final MalformedURLException e) { + log.warn("Can NOT initialize ressourcefolder for static Web content", e); + + } + + registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS); + + } + + /** + * Get a message source with only internal message properties. + * + * @param ressourceLocations List of source-locations + * @return + */ + @Bean + public ReloadableResourceBundleMessageSource internalMessageSource( + @Autowired(required = false) final List<IMessageSourceLocation> ressourceLocations) { + final ReloadableResourceBundleMessageSource messageSource = + new ReloadableResourceBundleMessageSource(); + + // add default message source + messageSource.setBasename(DEFAULT_MESSAGE_SOURCE); + + if (ressourceLocations != null) { + // load more message sources + for (final IMessageSourceLocation el : ressourceLocations) { + if (el.getMessageSourceLocation() != null) { + for (final String source : el.getMessageSourceLocation()) { + messageSource.addBasenames(source); + log.debug("Add additional messageSources: {}", el.getMessageSourceLocation().toArray()); + + } + } + } + } + + messageSource.setDefaultEncoding("UTF-8"); + return messageSource; + + } + + /** + * Get full message source with internal and external message-properties files. + * + * @param ressourceLocations List of source-locations + * @return + */ + @Bean + public ReloadableResourceBundleMessageSource messageSource( + @Autowired(required = false) final List<IMessageSourceLocation> ressourceLocations) { + final ReloadableResourceBundleMessageSource messageSource = + new ReloadableResourceBundleMessageSource(); + messageSource.setDefaultEncoding("UTF-8"); + messageSource.setParentMessageSource(internalMessageSource(ressourceLocations)); + + final String staticResources = basicConfig + .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH); + try { + if (StringUtils.isNotEmpty(staticResources)) { + final String absPath = + FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory()); + messageSource.setBasename(absPath); + + } else { + log.debug("No Ressourcefolder for dynamic Web content templates"); + + } + + } catch (final MalformedURLException e) { + log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e); + + } + + return messageSource; + + } + + /** + * Get a i18n resolver based on cookies. + * + * @return + */ + @Bean + public CookieLocaleResolver localeResolver() { + final CookieLocaleResolver localeResolver = new CookieLocaleResolver(); + localeResolver.setCookieName("currentLanguage"); + localeResolver.setCookieMaxAge(3600); + return localeResolver; + + } + + /** + * Get a Tyhmeleaf Template-Resolver with external configuration path. + * + * @return + */ + @Bean(name = "templateResolver") + public FileTemplateResolver templateResolver() { + final String staticResources = basicConfig + .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_PATH); + try { + if (StringUtils.isNotEmpty(staticResources)) { + String absPath = + FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory()); + if (!absPath.endsWith("/")) { + absPath += "/"; + + } + + if (absPath.startsWith("file:")) { + absPath = absPath.substring("file:".length()); + + } + + final FileTemplateResolver viewResolver = new FileTemplateResolver(); + viewResolver.setPrefix(absPath); + viewResolver.setSuffix(".html"); + viewResolver.setTemplateMode("HTML"); + viewResolver.setCacheable(false); + + log.info("Add Ressourcefolder: {} for dynamic Web content templates", absPath); + return viewResolver; + + } else { + log.debug("No Ressourcefolder for dynamic Web content templates"); + + } + + } catch (final MalformedURLException e) { + log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e); + + } + + throw new RuntimeException("Can NOT initialize HTML template resolver"); + + } +} |