package alien4cloud.webconfiguration; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.alien4cloud.tosca.catalog.index.CsarService; import org.alien4cloud.tosca.catalog.index.ICsarAuthorizationFilter; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.resource.ResourceResolver; import org.springframework.web.servlet.resource.ResourceResolverChain; import alien4cloud.exception.InitializationException; import alien4cloud.exception.NotFoundException; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @Slf4j @Configuration public class StaticResourcesConfiguration extends WebMvcConfigurerAdapter { public final static String PLUGIN_STATIC_ENDPOINT = "/static/plugins/"; @Setter private ICsarAuthorizationFilter csarAuthorizationFilter = null; @Setter private CsarService csarService = null; @Value("${directories.alien}/${directories.csar_repository}/") private String toscaRepo; @Value("${directories.alien}/work/plugins/ui/") private String pluginsUi; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String prefix = "file:///"; // resource locations must be full path and not relatives String absToscaRepo = prefix.concat(safeGetRealPath(toscaRepo)).concat("/"); String absPluginUi = prefix.concat(safeGetRealPath(pluginsUi)).concat("/"); log.info("Serving {} as tosca repo content.", absToscaRepo); log.info("Serving {} as plugin ui content.", absPluginUi); registry.addResourceHandler("/static/tosca/{csarName:.+}/{csarVersion:.+}/**").addResourceLocations(absToscaRepo).resourceChain(false) .addResolver(new ResourceResolver() { @Override public Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) { log.debug("Resolving editor resource"); // check security for the requested topology file. ServletWebRequest webRequest = new ServletWebRequest(request); Map uriTemplateVars = (Map) webRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, 0); String csarName = (String) uriTemplateVars.get("csarName"); String csarVersion = (String) uriTemplateVars.get("csarVersion"); if (csarAuthorizationFilter == null || csarService == null) { // not initialized as master throw new NotFoundException("Only master nodes can provide editor static resources."); } else { csarAuthorizationFilter.checkReadAccess(csarService.getOrFail(csarName, csarVersion)); } // let the usual resolving return chain.resolveResource(request, csarName + "/" + csarVersion + "/" + requestPath, locations); } @Override public String resolveUrlPath(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) { return chain.resolveUrlPath(resourceUrlPath, locations); } }); registry.addResourceHandler(PLUGIN_STATIC_ENDPOINT + "**").addResourceLocations(absPluginUi); } private String safeGetRealPath(String pathStr) { Path path = Paths.get(pathStr); try { if (!Files.exists(path)) { Files.createDirectories(path); } return path.toRealPath().toString(); } catch (IOException e) { throw new InitializationException("Unable to initialize alien as specified directories cannot be created.", e); } } }