diff --git a/.github/workflows/workflows.yaml b/.github/workflows/workflows.yaml new file mode 100644 index 00000000..2ed259ec --- /dev/null +++ b/.github/workflows/workflows.yaml @@ -0,0 +1,41 @@ +name: Tests + +on: [push] + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + java: [ 8, 11 ] + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Cache Maven packages + uses: actions/cache@v2 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + - name: Build with Maven + run: mvn -U clean install -DskipTests + - name: Run Tests + run: mvn test + + dependency: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Run Dependency Check + run: mvn -Powasp-dependency-check verify -DskipTests + - name: Archive code coverage results + uses: actions/upload-artifact@v2 + with: + name: dependency-check-report + path: target/dependency-check-report.html + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fd551dad..00000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: java -sudo: false -cache: - directories: - - "$HOME/.cache" diff --git a/LICENSE_HEADER b/LICENSE_HEADER index 53711c1d..8a89b71b 100755 --- a/LICENSE_HEADER +++ b/LICENSE_HEADER @@ -1,6 +1,6 @@ ShinyProxy -Copyright (C) 2016-2020 Open Analytics +Copyright (C) 2016-2021 Open Analytics =========================================================================== diff --git a/README.md b/README.md index 614beeaf..a7d385ad 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@
-               _____ _     _             _____                     
-              / ____| |   (_)           |  __ \                    
-             | (___ | |__  _ _ __  _   _| |__) | __ _____  ___   _ 
+               _____ _     _             _____
+              / ____| |   (_)           |  __ \
+             | (___ | |__  _ _ __  _   _| |__) | __ _____  ___   _
               \___ \| '_ \| | '_ \| | | |  ___/ '__/ _ \ \/ / | | |
               ____) | | | | | | | | |_| | |   | | | (_) >  <| |_| |
              |_____/|_| |_|_|_| |_|\__, |_|   |_|  \___/_/\_\\__, |
                                     __/ |                     __/ |
-                                   |___/                     |___/ 
+                                   |___/                     |___/
 
 
@@ -18,7 +18,7 @@ Open Source Enterprise Deployment for Shiny Apps Learn more at https://shinyproxy.io -#### (c) Copyright Open Analytics NV, 2016-2020 - Apache License 2.0 +#### (c) Copyright Open Analytics NV, 2016-2021 - Apache License 2.0 ## Building from source @@ -33,7 +33,7 @@ The build will result in a single `.jar` file that is made available in the `tar ## Running the application ``` -java -jar shinyproxy-2.3.0.jar +java -jar shinyproxy-2.3.0.jar ``` Navigate to http://localhost:8080 to access the application. If the default configuration is used, authentication will be done against the LDAP server at *ldap.forumsys.com*; to log in one can use the user name "tesla" and password "password". diff --git a/pom.xml b/pom.xml index bde17c5e..072d1503 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ eu.openanalytics shinyproxy - 2.4.3 + 2.5.0 jar ShinyProxy @@ -26,7 +26,7 @@ UTF-8 1.8 - 0.8.7 + 0.8.8 & diff --git a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyConfiguration.java b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyConfiguration.java index c97be451..af9ea24f 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyConfiguration.java +++ b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyConfiguration.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecMergeStrategy.java b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecMergeStrategy.java index 9713fcb2..40b3e6ff 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecMergeStrategy.java +++ b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecMergeStrategy.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecProvider.java b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecProvider.java index 2244566c..26331af7 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecProvider.java +++ b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxySpecProvider.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * @@ -29,9 +29,13 @@ import java.util.stream.Collectors; import javax.annotation.PostConstruct; +import javax.inject.Inject; +import eu.openanalytics.containerproxy.util.SessionHelper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonParseException; @@ -56,6 +60,13 @@ public class ShinyProxySpecProvider implements IProxySpecProvider { private List specs = new ArrayList<>(); + private static Environment environment; + + @Autowired + public void setEnvironment(Environment env){ + ShinyProxySpecProvider.environment = env; + } + @PostConstruct public void afterPropertiesSet() { this.specs.stream().collect(Collectors.groupingBy(ProxySpec::getId)).forEach((id, duplicateSpecs) -> { @@ -75,6 +86,11 @@ public ProxySpec getSpec(String id) { public void setSpecs(List specs) { this.specs = specs.stream().map(ShinyProxySpecProvider::convert).collect(Collectors.toList()); } + + private static String getPublicPath(String appName) { + String contextPath = SessionHelper.getContextPath(environment, true); + return contextPath + "app_direct/" + appName + "/"; + } private static ProxySpec convert(ShinyProxySpec from) { ProxySpec to = new ProxySpec(); @@ -100,7 +116,15 @@ private static ProxySpec convert(ShinyProxySpec from) { ContainerSpec cSpec = new ContainerSpec(); cSpec.setImage(from.getContainerImage()); cSpec.setCmd(from.getContainerCmd()); - cSpec.setEnv(from.getContainerEnv()); + + Map env = from.getContainerEnv(); + if (env == null) { + env = new HashMap<>(); + } + + env.put("SHINYPROXY_PUBLIC_PATH", getPublicPath(from.getId())); + cSpec.setEnv(env); + cSpec.setEnvFile(from.getContainerEnvFile()); cSpec.setNetwork(from.getContainerNetwork()); cSpec.setNetworkConnections(from.getContainerNetworkConnections()); diff --git a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyTestStrategy.java b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyTestStrategy.java index c15d4e4f..ff5e38a6 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyTestStrategy.java +++ b/src/main/java/eu/openanalytics/shinyproxy/ShinyProxyTestStrategy.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * @@ -23,6 +23,7 @@ import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; +import java.util.Arrays; import java.util.function.IntPredicate; import javax.inject.Inject; @@ -65,8 +66,9 @@ public boolean testProxy(Proxy proxy) { URL testURL = new URL(targetURI.toString()); HttpURLConnection connection = ((HttpURLConnection) testURL.openConnection()); connection.setConnectTimeout(timeoutMs); + connection.setInstanceFollowRedirects(false); int responseCode = connection.getResponseCode(); - if (responseCode == 200) return true; + if (Arrays.asList(200, 301, 302, 303, 307, 308).contains(responseCode)) return true; } catch (Exception e) { if (i > 1 && log != null) log.warn(String.format("Container unresponsive, trying again (%d/%d): %s", i, maxTries, targetURI)); } diff --git a/src/main/java/eu/openanalytics/shinyproxy/UISecurityConfig.java b/src/main/java/eu/openanalytics/shinyproxy/UISecurityConfig.java index 2480b083..acc889dc 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/UISecurityConfig.java +++ b/src/main/java/eu/openanalytics/shinyproxy/UISecurityConfig.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/java/eu/openanalytics/shinyproxy/controllers/AdminController.java b/src/main/java/eu/openanalytics/shinyproxy/controllers/AdminController.java index 75a9bb0b..8f742fc9 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/controllers/AdminController.java +++ b/src/main/java/eu/openanalytics/shinyproxy/controllers/AdminController.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/java/eu/openanalytics/shinyproxy/controllers/AppController.java b/src/main/java/eu/openanalytics/shinyproxy/controllers/AppController.java index 6cdec46f..b9cd98cf 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/controllers/AppController.java +++ b/src/main/java/eu/openanalytics/shinyproxy/controllers/AppController.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * @@ -20,24 +20,23 @@ */ package eu.openanalytics.shinyproxy.controllers; -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import eu.openanalytics.containerproxy.model.runtime.Proxy; +import eu.openanalytics.containerproxy.model.runtime.ProxyStatus; +import eu.openanalytics.containerproxy.model.spec.ProxySpec; +import eu.openanalytics.containerproxy.util.ProxyMappingManager; +import eu.openanalytics.containerproxy.util.Retrying; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import eu.openanalytics.containerproxy.model.runtime.Proxy; -import eu.openanalytics.containerproxy.model.runtime.ProxyStatus; -import eu.openanalytics.containerproxy.model.spec.ProxySpec; -import eu.openanalytics.containerproxy.util.ProxyMappingManager; -import eu.openanalytics.containerproxy.util.Retrying; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; @Controller public class AppController extends BaseController { @@ -125,11 +124,11 @@ private boolean awaitReady(Proxy proxy) { private String buildContainerPath(HttpServletRequest request) { String appName = getAppName(request); if (appName == null) return ""; - - String queryString = request.getQueryString(); + + String queryString = ServletUriComponentsBuilder.fromRequest(request).replaceQueryParam("sp_hide_navbar").build().getQuery(); + queryString = (queryString == null) ? "" : "?" + queryString; - String containerPath = getContextPath() + "app_direct/" + appName + "/" + queryString; - return containerPath; + return getContextPath() + "app_direct/" + appName + "/" + queryString; } } diff --git a/src/main/java/eu/openanalytics/shinyproxy/controllers/BaseController.java b/src/main/java/eu/openanalytics/shinyproxy/controllers/BaseController.java index 67e86c7d..857232aa 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/controllers/BaseController.java +++ b/src/main/java/eu/openanalytics/shinyproxy/controllers/BaseController.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * @@ -28,12 +28,14 @@ import java.util.Base64; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; +import eu.openanalytics.containerproxy.auth.IAuthenticationBackend; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.core.env.Environment; @@ -59,7 +61,10 @@ public abstract class BaseController { @Inject Environment environment; - + + @Inject + IAuthenticationBackend authenticationBackend; + private static Logger logger = LogManager.getLogger(BaseController.class); private static Pattern appPattern = Pattern.compile(".*?/app[^/]*/([^/]*)/?.*"); private static Map imageCache = new HashMap<>(); @@ -106,17 +111,25 @@ protected String getProxyEndpoint(Proxy proxy) { protected void prepareMap(ModelMap map, HttpServletRequest request) { map.put("title", environment.getProperty("proxy.title", "ShinyProxy")); map.put("logo", resolveImageURI(environment.getProperty("proxy.logo-url"))); - map.put("showNavbar", !Boolean.valueOf(environment.getProperty("proxy.hide-navbar"))); - + + String hideNavBarParam = request.getParameter("sp_hide_navbar"); + if (Objects.equals(hideNavBarParam, "true")) { + map.put("showNavbar", false); + } else { + map.put("showNavbar", !Boolean.parseBoolean(environment.getProperty("proxy.hide-navbar"))); + } + map.put("bootstrapCss", "/webjars/bootstrap/3.4.1/css/bootstrap.min.css"); map.put("bootstrapJs", "/webjars/bootstrap/3.4.1/js/bootstrap.min.js"); map.put("jqueryJs", "/webjars/jquery/3.5.0/jquery.min.js"); - + map.put("cookieJs", "/webjars/js-cookie/2.2.1/js.cookie.min.js"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); boolean isLoggedIn = authentication != null && !(authentication instanceof AnonymousAuthenticationToken) && authentication.isAuthenticated(); map.put("isLoggedIn", isLoggedIn); map.put("isAdmin", userService.isAdmin(authentication)); map.put("isSupportEnabled", isLoggedIn && getSupportAddress() != null); + map.put("logoutUrl", authenticationBackend.getLogoutURL()); } protected String getSupportAddress() { diff --git a/src/main/java/eu/openanalytics/shinyproxy/controllers/IndexController.java b/src/main/java/eu/openanalytics/shinyproxy/controllers/IndexController.java index 87b80549..2cb86d01 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/controllers/IndexController.java +++ b/src/main/java/eu/openanalytics/shinyproxy/controllers/IndexController.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/java/eu/openanalytics/shinyproxy/controllers/IssueController.java b/src/main/java/eu/openanalytics/shinyproxy/controllers/IssueController.java index a8b02720..46eeeca4 100644 --- a/src/main/java/eu/openanalytics/shinyproxy/controllers/IssueController.java +++ b/src/main/java/eu/openanalytics/shinyproxy/controllers/IssueController.java @@ -1,7 +1,7 @@ /** * ShinyProxy * - * Copyright (C) 2016-2020 Open Analytics + * Copyright (C) 2016-2021 Open Analytics * * =========================================================================== * diff --git a/src/main/resources/fragments/navbar.html b/src/main/resources/fragments/navbar.html index dddec9cb..17f6f7e9 100644 --- a/src/main/resources/fragments/navbar.html +++ b/src/main/resources/fragments/navbar.html @@ -2,7 +2,7 @@ ShinyProxy - Copyright (C) 2016-2020 Open Analytics + Copyright (C) 2016-2021 Open Analytics =========================================================================== @@ -37,7 +37,7 @@ Report Issue Admin - Sign Out + Sign Out