diff --git a/build.sh b/build.sh
index 5df0e1ce8b819d6e60cc939b9bf32b1ff95bad9f..84efdf7b37f26e7a7083bbb402aeced4609a152e 100755
--- a/build.sh
+++ b/build.sh
@@ -37,6 +37,7 @@ docker build --build-arg BUILD_DATE=$(date -Iseconds) \
--tag "$IMAGE:$VERSION" \
.
+
BUGSNAG_KEY=""
eval $(grep -e "^\\s*BUGSNAG_KEY" Dockerfile | tr '\\' ' ')
diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index e3a624a13a6c1588210c0546923888956fe45a9f..e34a00c0c2d4b693fc1a4ff26d3f709b43223299 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -30,7 +30,8 @@ hbp:
clientSecret: {{ .Env.CLIENT_SECRET }}
accessTokenUri: {{ default .Env.TOKEN_URI "https://services.humanbrainproject.eu/oidc/token" }}
userAuthorizationUri: {{ default .Env.AUTH_URI "https://services.humanbrainproject.eu/oidc/authorize" }}
- tokenName: oauth_token
+ logoutUri: {{ .Env.LOGOUT_URI }}
+ tokenName: access_token
authenticationScheme: query
clientAuthenticationScheme: form
useCurrentUri: false
@@ -46,12 +47,13 @@ frontend:
loginUrl: {{ default .Env.FRONTEND_LOGIN_URL "http://frontend/services/login/hbp" }}
redirectAfterLogoutUrl: {{ default .Env.FRONTEND_AFTER_LOGOUT_URL (default .Env.LOGIN_URI "http://frontend/services/login/hbp") }}
redirectAfterLoginUrl: {{ default .Env.FRONTEND_AFTER_LOGIN_URL "http://frontend/home" }}
-
+
logging:
level:
root: {{ default .Env.LOG_LEVEL "INFO" }}
org:
springframework:
+ security: DEBUG
web: {{ default .Env.LOGGING_LEVEL_WEB "WARN" }}
web.servlet.handler.BeanNameUrlHandlerMapping: WARN
hibernate: {{ default .Env.LOGGING_LEVEL_HIBERNATE "WARN" }}
@@ -86,4 +88,5 @@ services:
galaxyUsername: {{ default .Env.GALAXY_USERNAME "admin" }}
galaxyPassword: {{ default .Env.GALAXY_PASSWORD "password" }}
galaxyContext: {{ default .Env.GALAXY_CONTEXT "nativeGalaxy" }}
-
+ keycloak:
+ keycloakUrl: {{ .Env.KEYCLOAK_URL }}
diff --git a/pom.xml b/pom.xml
index 33287a67edb208121a0935c13ae7ab66d8690f7b..674ec19543bfb73623cdf88324f209ae513aa0c3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,7 @@
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.8.RELEASE</version>
<relativePath/>
+
</parent>
<properties>
@@ -65,30 +66,15 @@
</repositories>
<dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-log4j2</artifactId>
- </dependency>
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-boot-starter-actuator.version}</version>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
@@ -98,22 +84,11 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
+
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
@@ -145,12 +120,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- </exclusions>
<scope>test</scope>
</dependency>
<dependency>
@@ -249,6 +218,11 @@
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
+ <dependency>
+ <groupId>com.auth0</groupId>
+ <artifactId>java-jwt</artifactId>
+ <version>3.8.3</version>
+ </dependency>
</dependencies>
<build>
diff --git a/src/main/java/eu/hbp/mip/MIPApplication.java b/src/main/java/eu/hbp/mip/MIPApplication.java
index df70ba78a5ba397676f1ad1533895e86a67c4f89..befb16ec91ee35a0bbd2c9a7631f30be9cde4b21 100644
--- a/src/main/java/eu/hbp/mip/MIPApplication.java
+++ b/src/main/java/eu/hbp/mip/MIPApplication.java
@@ -4,14 +4,23 @@
package eu.hbp.mip;
+
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
@SpringBootApplication
public class MIPApplication {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MIPApplication.class);
+
public static void main(String[] args) {
SpringApplication.run(MIPApplication.class, args);
}
+
+
+
}
diff --git a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
index d8ec1acfbc932f8cb5faa1a42199904ffc88a092..a92879577926739b703e4d015a1a64caa1ed5b87 100644
--- a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
@@ -4,10 +4,12 @@ import eu.hbp.mip.model.UserInfo;
import eu.hbp.mip.utils.CORSFilter;
import eu.hbp.mip.utils.CustomLoginUrlAuthenticationEntryPoint;
import eu.hbp.mip.utils.HTTPUtil;
+import eu.hbp.mip.utils.UserActionLogging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
@@ -34,6 +36,10 @@ import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;
+import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -42,179 +48,324 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+//newlyadded for logout
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import java.net.URI;
+
+
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
// See https://spring.io/guides/tutorials/spring-boot-oauth2/ for reference about configuring OAuth2 login
// also http://cscarioni.blogspot.ch/2013/04/pro-spring-security-and-oauth-2.html
-/**
- * Configuration for security.
- */
@Configuration
@EnableOAuth2Client
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
- private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
-
- @Autowired
- private OAuth2ClientContext oauth2ClientContext;
-
- /**
- * Enable HBP collab authentication (1) or disable it (0). Default is 1
- */
- @Value("#{'${hbp.authentication.enabled:1}'}")
- private boolean authentication;
-
- /**
- * Absolute URL to redirect to when login is required
- */
- @Value("#{'${frontend.loginUrl:/login/hbp}'}")
- private String loginUrl;
-
- /**
- * Absolute URL to redirect to after successful login
- */
- @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
- private String frontendRedirectAfterLogin;
-
- /**
- * Absolute URL to redirect to after logout has occurred
- */
- @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
- private String redirectAfterLogoutUrl;
-
- /**
- * URL to revoke auth token
- */
- @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
- private String revokeTokenURI;
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- // @formatter:off
- http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
-
- if (authentication) {
- http.antMatcher("/**")
- .authorizeRequests()
- .antMatchers(
- "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
- ).permitAll()
- .anyRequest().authenticated()
- .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
- .and().logout().addLogoutHandler(new CustomLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
- .and().logout().permitAll()
- .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
- .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
- .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
- }
- else {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
+
+ @Autowired
+ private OAuth2ClientContext oauth2ClientContext;
+
+ /**
+ * Enable HBP collab authentication (1) or disable it (0). Default is 1
+ */
+ @Value("#{'${hbp.authentication.enabled:1}'}")
+ private boolean authentication;
+
+ /**
+ * Absolute URL to redirect to when login is required
+ */
+ @Value("#{'${frontend.loginUrl:/login/hbp}'}")
+ private String loginUrl;
+
+ /**
+ * Absolute URL to redirect to when logout is required
+ */
+ @Value("#{'${hbp.client.logoutUri}'}")
+ private String logoutUri;
+
+ /**
+ * Absolute URL to redirect to after successful login
+ */
+ @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
+ private String frontendRedirectAfterLogin;
+
+ /**
+ * Absolute URL to redirect to after logout has occurred
+ */
+ @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
+ private String redirectAfterLogoutUrl;
+
+ /**
+ * URL to revoke auth token
+ */
+ @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
+ private String revokeTokenURI;
+
+
+
+// @Autowired
+// private HttpServletRequest request;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ disableCertificateValidation();
+ // @formatter:off
+ http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
+
+ if (authentication) {
+ http.antMatcher("/**")
+ .authorizeRequests()
+ .antMatchers(
+ "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
+ )
+ .permitAll()
+ .antMatchers("/galaxy*","/galaxy/*").hasRole("Data Manager")
+ //.anyRequest().authenticated()
+ .anyRequest().hasRole("Researcher")
+ .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
+ .and().logout().addLogoutHandler(authLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
+ .and().logout().permitAll()
+ .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
+ .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
+ .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
+ }
+ else {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/**").permitAll().and().csrf().disable();
- }
- }
+ }
+ }
- private Filter ssoFilter() {
- OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
- OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
- hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
- hbpFilter.setRestTemplate(hbpTemplate);
- hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
- return hbpFilter;
- }
+ private Filter ssoFilter() {
+ OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
+ OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
+ hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
+ hbpFilter.setRestTemplate(hbpTemplate);
+ hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
+ return hbpFilter;
+ }
- @Bean
- public FilterRegistrationBean oauth2ClientFilterRegistration(
- OAuth2ClientContextFilter filter) {
- FilterRegistrationBean registration = new FilterRegistrationBean();
- registration.setFilter(filter);
- registration.setOrder(-100);
- return registration;
- }
+ @Bean
+ public FilterRegistrationBean oauth2ClientFilterRegistration(
+ OAuth2ClientContextFilter filter) {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setFilter(filter);
+ registration.setOrder(-100);
+ return registration;
+ }
- @Bean(name="hbp")
- @ConfigurationProperties("hbp.client")
- public OAuth2ProtectedResourceDetails hbp() {
- return new AuthorizationCodeResourceDetails();
- }
+ @Bean(name="hbp")
+ @ConfigurationProperties("hbp.client")
+ public BaseOAuth2ProtectedResourceDetails hbp() {
+ return new AuthorizationCodeResourceDetails();
+ }
- @Bean(name="hbpResource")
- @ConfigurationProperties("hbp.resource")
- public ResourceServerProperties hbpResource() {
- return new ResourceServerProperties();
- }
+ @Bean(name="hbpResource")
+ @ConfigurationProperties("hbp.resource")
+ public ResourceServerProperties hbpResource() {
+ return new ResourceServerProperties();
+ }
- public boolean isAuthentication() {
- return authentication;
- }
+ public boolean isAuthentication() {
+ return authentication;
+ }
- public String getFrontendRedirectAfterLogin() {
- return frontendRedirectAfterLogin;
- }
+ public String getFrontendRedirectAfterLogin() {
+ return frontendRedirectAfterLogin;
+ }
- private Filter csrfHeaderFilter() {
- return new OncePerRequestFilter() {
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
- FilterChain filterChain) throws ServletException, IOException {
- CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
- if (csrf != null) {
- Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
- String token = csrf.getToken();
- if (cookie == null || token != null && !token.equals(cookie.getValue())) {
- cookie = new Cookie("XSRF-TOKEN", token);
- cookie.setPath("/");
- response.addCookie(cookie);
- }
- }
- filterChain.doFilter(request, response);
- }
- };
- }
+ private Filter csrfHeaderFilter() {
+ return new OncePerRequestFilter() {
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+ FilterChain filterChain) throws ServletException, IOException {
+ CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
+ if (csrf != null) {
+ Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
+ String token = csrf.getToken();
+ if (cookie == null || token != null && !token.equals(cookie.getValue())) {
+ cookie = new Cookie("XSRF-TOKEN", token);
+ cookie.setPath("/");
+ response.addCookie(cookie);
+ }
+ }
+ filterChain.doFilter(request, response);
+ }
+ };
+ }
+
+ private CsrfTokenRepository csrfTokenRepository() {
+ HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
+ repository.setHeaderName("X-XSRF-TOKEN");
+ return repository;
+ }
+
+ private class CustomLogoutHandler implements LogoutHandler {
+ @Override
+ public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
+
+ // Hackish way of accessing to this information...
+ final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
+ if (userInfo != null) {
+ userInfo.setFakeAuth(false);
+ }
- private CsrfTokenRepository csrfTokenRepository() {
- HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
- repository.setHeaderName("X-XSRF-TOKEN");
- return repository;
+ if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null)
+ {
+ return;
+ }
+
+ String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
+
+ StringBuilder query = new StringBuilder();
+ query.append("{");
+ query.append("\"token\":");
+ query.append("\"").append(idToken).append("\"");
+ query.append("}");
+
+ try {
+ int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
+ if (responseCode != 200)
+ {
+ LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
+ }
+ else{
+ LOGGER.info("Should be logged out");
+ }
+ } catch (IOException e) {
+ LOGGER.warn("Cannot notify logout to OIDC server !");
+ LOGGER.trace("Cannot notify logout", e);
+ }
+
+ }
+ }
+
+ @Bean
+ public AuthoritiesExtractor keycloakAuthoritiesExtractor() {
+ return new KeycloakAuthoritiesExtractor();
}
- private class CustomLogoutHandler implements LogoutHandler {
+
+ public class KeycloakAuthoritiesExtractor
+ implements AuthoritiesExtractor {
+
@Override
- public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
+ public List<GrantedAuthority> extractAuthorities
+ (Map<String, Object> map) {
+ return AuthorityUtils
+ .commaSeparatedStringToAuthorityList(asAuthorities(map));
+ }
- // Hackish way of accessing to this information...
- final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
- if (userInfo != null) {
- userInfo.setFakeAuth(false);
+ private String asAuthorities(Map<String, Object> map) {
+ List<String> authorities = new ArrayList<>();
+// authorities.add("BAELDUNG_USER");
+ List<LinkedHashMap<String, String>> authz;
+ authz = (List<LinkedHashMap<String, String>>) map.get("authorities");
+ for (LinkedHashMap<String, String> entry : authz) {
+ authorities.add(entry.get("authority"));
}
+ return String.join(",", authorities);
+ }
+ }
+
+
+ private LogoutHandler authLogoutHandler() {
+ return (request, response, authentication) -> {
+ logout();
+ };
+ }
+
+
+ public void logout() {
+ // POSTするリクエストパラメーターを作成
+ UserActionLogging.LogAction("refresh token ", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
+ RestTemplate restTemplate = new RestTemplate();
+ MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
+ formParams.add("client_id", hbp().getClientId());
+ formParams.add("client_secret", hbp().getClientSecret());
+ formParams.add("refresh_token", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
+ // リクエストヘッダーを作成
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
+ // リクエストを作成
+ UserActionLogging.LogAction("logoutUri is ", logoutUri);
+ RequestEntity<MultiValueMap<String, String>> requestEntity =
+ new RequestEntity<>(formParams, httpHeaders, HttpMethod.POST,
+ URI.create(logoutUri));
+ // POSTリクエスト送信(ログアウト実行)
- if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null)
- {
- return;
- }
+ ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
+ }
+
+ @Value("#{'${services.keycloak.keycloakUrl}'}")
+ private String keycloakUrl;
+
+ // static {
+ // disableCertificateValidation();
+ // }
- String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
+ public void disableCertificateValidation() {
+ LOGGER.info("disabling certificate validation host : " + keycloakUrl);
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[] {
+ new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {}
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {}
+ } };
- StringBuilder query = new StringBuilder();
- query.append("{");
- query.append("\"token\":");
- query.append("\"").append(idToken).append("\"");
- query.append("}");
- try {
- int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
- if (responseCode != 200)
+ // Ignore differences between given hostname and certificate hostname
+ HostnameVerifier hv = new HostnameVerifier() {
+ public boolean verify(String hostname, SSLSession session) {
+
+ // System.out.println("Warning: URL Host: " + hostname + " vs. "
+ // + session.getPeerHost());
+ if(hostname.equals(keycloakUrl) && session.getPeerHost().equals(keycloakUrl))
{
- LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
+ return true;
}
- else{
- LOGGER.info("Should be logged out");
+ else
+ {
+ return false;
}
- } catch (IOException e) {
- LOGGER.warn("Cannot notify logout to OIDC server !");
- LOGGER.trace("Cannot notify logout", e);
}
+ };
+
+ // Install the all-trusting trust manager
+ try {
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, trustAllCerts, new SecureRandom());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+ HttpsURLConnection.setDefaultHostnameVerifier(hv);
+ } catch (Exception e) {}
+
+ }
- }
- }
}
diff --git a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
index 3b567b102c182f529006f055a11112efd5c749a7..963b181576f0626620d76b3a0370dcb840767778 100644
--- a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
@@ -10,6 +10,7 @@ import eu.hbp.mip.model.Article;
import eu.hbp.mip.model.User;
import eu.hbp.mip.model.UserInfo;
import eu.hbp.mip.repositories.ArticleRepository;
+import eu.hbp.mip.utils.UserActionLogging;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,8 +31,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/articles", description = "the articles API")
public class ArticlesApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(ArticlesApi.class);
-
@Autowired
private UserInfo userInfo;
@@ -44,8 +43,6 @@ public class ArticlesApi {
@ApiParam(value = "Only ask own articles") @RequestParam(value = "own", required = false) Boolean own,
@ApiParam(value = "Only ask results matching status", allowableValues = "draft, published") @RequestParam(value = "status", required = false) String status
) {
- LOGGER.info("Get articles");
-
User user = userInfo.getUser();
Iterable<Article> articles;
@@ -69,7 +66,8 @@ public class ArticlesApi {
}
}
}
-
+ UserActionLogging.LogAction("Get articles", "id : Get All articles");
+
return ResponseEntity.ok(articles);
}
@@ -80,8 +78,7 @@ public class ArticlesApi {
public ResponseEntity<Void> addAnArticle(
@RequestBody @ApiParam(value = "Article to create", required = true) @Valid Article article
) {
- LOGGER.info("Create an article");
-
+
User user = userInfo.getUser();
article.setCreatedAt(new Date());
@@ -111,7 +108,7 @@ public class ArticlesApi {
slug = new Slugify().slugify(article.getTitle());
} catch (IOException e) {
slug = "";
- LOGGER.trace("Cannot slugify title", e);
+ //LOGGER.trace("Cannot slugify title", e);
}
boolean alreadyExists = true;
@@ -130,8 +127,7 @@ public class ArticlesApi {
}
articleRepository.save(article);
- LOGGER.info("Article saved");
-
+ UserActionLogging.LogAction("Created article", "id : " + article.getSlug());
return new ResponseEntity<>(HttpStatus.CREATED);
}
@@ -141,7 +137,7 @@ public class ArticlesApi {
public ResponseEntity<Article> getAnArticle(
@ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
) {
- LOGGER.info("Get an article");
+ UserActionLogging.LogAction("Getting an article", "id : " + slug);
User user = userInfo.getUser();
Article article;
@@ -149,7 +145,7 @@ public class ArticlesApi {
if(article == null)
{
- LOGGER.warn("Cannot find article : " + slug);
+ //LOGGER.warn("Cannot find article : " + slug);
return ResponseEntity.badRequest().body(null);
}
@@ -169,7 +165,7 @@ public class ArticlesApi {
@ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
@RequestBody @ApiParam(value = "Article to update", required = true) @Valid Article article
) {
- LOGGER.info("Update an article");
+ UserActionLogging.LogAction("Update an article", "id : " + slug);
User user = userInfo.getUser();
@@ -201,8 +197,7 @@ public class ArticlesApi {
articleRepository.save(article);
- LOGGER.info("Article updated");
-
+
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
index 9f4fee480c37b7b0b0ac8d3fad50ed8e7bf79e59..deef20f755c0fd961e09a238eb662a671a9532e2 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
@@ -20,6 +20,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import eu.hbp.mip.utils.JWTUtil;
+import eu.hbp.mip.utils.UserActionLogging;
import java.io.IOException;
import java.util.*;
@@ -33,7 +34,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/experiments", description = "the experiments API")
public class ExperimentApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentApi.class);
+ //private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentApi.class);
private static final Gson gson = new Gson();
@@ -61,7 +62,7 @@ public class ExperimentApi {
@ApiOperation(value = "Create an experiment on Exareme", response = Experiment.class)
@RequestMapping(value = "/exareme", method = RequestMethod.POST)
public ResponseEntity<String> runExaremeExperiment(@RequestBody ExperimentQuery expQuery) {
- LOGGER.info("send ExaremeExperiment");
+ //LOGGER.info("send ExaremeExperiment");
Experiment experiment = saveExperiment(expQuery);
@@ -87,23 +88,24 @@ public class ExperimentApi {
experiment.setHasError(code >= 400);
experiment.setHasServerError(code >= 500);
} catch (IOException e) {
- LOGGER.trace("Invalid UUID", e);
- LOGGER.warn("Exareme experiment failed to run properly !");
+ //LOGGER.trace("Invalid UUID", e);
+ //LOGGER.warn("Exareme experiment failed to run properly !");
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(e.getMessage());
}
finishExperiment(experiment);
}).start();
-
+
+ UserActionLogging.LogAction("create ExaremeExperiment", "no info");
+
return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
}
@ApiOperation(value = "Create a workflow", response = Experiment.class)
@RequestMapping(value = "/workflow", method = RequestMethod.POST)
public ResponseEntity<String> runWorkflow(@RequestBody ExperimentQuery expQuery) {
- LOGGER.info("send Workflow");
-
+
Experiment experiment = saveExperiment(expQuery);
String algoCode = expQuery.getAlgorithms().get(0).getCode();
@@ -132,7 +134,7 @@ public class ExperimentApi {
experiment.setHasError(code >= 400);
experiment.setHasServerError(code >= 500);
} catch (IOException e) {
- LOGGER.trace("Invalid UUID", e);
+ //LOGGER.trace("Invalid UUID", e);
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(e.getMessage());
@@ -140,6 +142,8 @@ public class ExperimentApi {
finishExperiment(experiment);
}).start();
+ UserActionLogging.LogAction("create workflow", "no info");
+
return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
}
@@ -147,15 +151,14 @@ public class ExperimentApi {
@RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
public ResponseEntity<String> getExperiment(
@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
- LOGGER.info("Get an experiment");
Experiment experiment;
UUID experimentUuid;
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
- LOGGER.trace("Invalid UUID", iae);
- LOGGER.warn("An invalid Experiment UUID was received ! " + uuid);
+ //LOGGER.trace("Invalid UUID", iae);
+ //LOGGER.warn("An invalid Experiment UUID was received ! " + uuid);
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
@@ -164,7 +167,9 @@ public class ExperimentApi {
if (experiment == null) {
return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
}
-
+
+ UserActionLogging.LogAction("Get an experiment ", " uuid : "+ uuid);
+
return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
}
@@ -172,8 +177,9 @@ public class ExperimentApi {
@RequestMapping(value = "/workflow/status/{historyId}", method = RequestMethod.GET)
public ResponseEntity<String> getWorkflowStatus(
@ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
- LOGGER.info("Get a workflow status");
-
+
+ UserActionLogging.LogAction("Get a workflow status", " historyId : "+ historyId);
+
String url = workflowUrl + "/getWorkflowStatus/" + historyId;
try {
User user = userInfo.getUser();
@@ -186,6 +192,7 @@ public class ExperimentApi {
} catch (IOException e) {
return ResponseEntity.status(500).body(e.getMessage());
}
+
}
// TODO: factorize workflow results
@@ -193,8 +200,8 @@ public class ExperimentApi {
@RequestMapping(value = "/workflow/results/{historyId}", method = RequestMethod.GET)
public ResponseEntity<String> getWorkflowResults(
@ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
- LOGGER.info("Get a workflow results");
-
+ UserActionLogging.LogAction("Get workflow results", " historyId : "+ historyId);
+
String url = workflowUrl + "/getWorkflowResults/" + historyId;
try {
StringBuilder response = new StringBuilder();
@@ -214,8 +221,9 @@ public class ExperimentApi {
public ResponseEntity<String> getWorkflowResultBody(
@ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
@ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
- LOGGER.info("Get a workflow result content");
+ UserActionLogging.LogAction("Get workflow result content", " historyId : "+ historyId + " resultId : "+ resultId);
+
String url = workflowUrl + "/getWorkflowResultsBody/" + historyId + "/contents/" + resultId;
try {
StringBuilder response = new StringBuilder();
@@ -235,7 +243,7 @@ public class ExperimentApi {
public ResponseEntity<String> getWorkflowResultsDetails(
@ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
@ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
- LOGGER.info("Get a workflow result content");
+ UserActionLogging.LogAction("Get workflow result details", " historyId : "+ historyId + " resultId : "+ resultId);
String url = workflowUrl + "/getWorkflowResultsDetails/" + historyId + "/contents/" + resultId;
try {
@@ -255,7 +263,8 @@ public class ExperimentApi {
@RequestMapping(value = "/{uuid}/markAsViewed", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsViewed(
@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
- LOGGER.info("Mark an experiment as viewed");
+
+ UserActionLogging.LogAction("Mark an experiment as viewed", " uuid : "+ uuid);
Experiment experiment;
UUID experimentUuid;
@@ -263,8 +272,8 @@ public class ExperimentApi {
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
- LOGGER.trace("Invalid UUID", iae);
- LOGGER.warn("An invalid Experiment UUID was received !");
+ //LOGGER.trace("Invalid UUID", iae);
+ //LOGGER.warn("An invalid Experiment UUID was received !");
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
@@ -274,7 +283,7 @@ public class ExperimentApi {
experiment.setResultsViewed(true);
experimentRepository.save(experiment);
- LOGGER.info("Experiment updated (marked as viewed)");
+ UserActionLogging.LogAction("Experiment updated (marked as viewed)", " ");
return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
}
@@ -283,8 +292,9 @@ public class ExperimentApi {
@RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsShared(
@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
- LOGGER.info("Mark an experiment as shared");
+ UserActionLogging.LogAction("Mark an experiment as shared", " uuid : "+ uuid);
+
return doMarkExperimentAsShared(uuid, true);
}
@@ -292,8 +302,8 @@ public class ExperimentApi {
@RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsUnshared(
@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
- LOGGER.info("Mark an experiment as unshared");
-
+ UserActionLogging.LogAction("Mark an experiment as unshared", " uuid : "+ uuid);
+
return doMarkExperimentAsShared(uuid, false);
}
@@ -301,8 +311,9 @@ public class ExperimentApi {
@RequestMapping(method = RequestMethod.GET, params = { "maxResultCount" })
public ResponseEntity<String> listExperiments(
@ApiParam(value = "maxResultCount") @RequestParam int maxResultCount) {
- LOGGER.info("List experiments");
+ UserActionLogging.LogAction("List experiments", " maxResultCount : "+ maxResultCount);
+
return doListExperiments(false, null);
}
@@ -310,7 +321,8 @@ public class ExperimentApi {
@RequestMapping(method = RequestMethod.GET, params = { "slug", "maxResultCount" })
public ResponseEntity<String> listExperiments(@ApiParam(value = "slug") @RequestParam("slug") String modelSlug,
@ApiParam(value = "maxResultCount") @RequestParam("maxResultCount") int maxResultCount) {
- LOGGER.info("List experiments");
+
+ UserActionLogging.LogAction("List experiments", " modelSlug : "+ modelSlug);
if (maxResultCount <= 0 && (modelSlug == null || "".equals(modelSlug))) {
return new ResponseEntity<>("You must provide at least a slug or a limit of result",
@@ -323,7 +335,7 @@ public class ExperimentApi {
@ApiOperation(value = "list my experiments", response = Experiment.class, responseContainer = "List")
@RequestMapping(method = RequestMethod.GET, params = { "mine" })
public ResponseEntity<String> listMyExperiments(@ApiParam(value = "mine") @RequestParam("mine") boolean mine) {
- LOGGER.info("List my experiments");
+ UserActionLogging.LogAction("List my experiments", " mine : "+ mine);
return doListExperiments(true, null);
}
@@ -361,8 +373,8 @@ public class ExperimentApi {
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
- LOGGER.trace("Invalid UUID", iae);
- LOGGER.warn("An invalid Experiment UUID was received !");
+ //LOGGER.trace("Invalid UUID", iae);
+ //LOGGER.warn("An invalid Experiment UUID was received !");
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
@@ -373,8 +385,8 @@ public class ExperimentApi {
experiment.setShared(shared);
experimentRepository.save(experiment);
-
- LOGGER.info("Experiment updated (marked as shared)");
+
+ UserActionLogging.LogAction("Experiment updated (marked as shared)", "");
return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
}
@@ -383,7 +395,7 @@ public class ExperimentApi {
experiment.setFinished(new Date());
experimentRepository.save(experiment);
- LOGGER.info("Experiment updated (finished)");
+ UserActionLogging.LogAction("Experiment updated (finished)","");
}
private HashMap<String, String> makeObject(String name, String value) {
@@ -395,7 +407,6 @@ public class ExperimentApi {
}
private Experiment saveExperiment(ExperimentQuery expQuery) {
- LOGGER.info("saveExperiment");
Experiment experiment = new Experiment();
experiment.setUuid(UUID.randomUUID());
@@ -408,7 +419,7 @@ public class ExperimentApi {
experiment.setModel(modelRepository.findOne(expQuery.getModel()));
experimentRepository.save(experiment);
- LOGGER.info("Experiment saved");
+ UserActionLogging.LogAction("Saved an experiment", " id : "+experiment.getUuid());
return experiment;
}
diff --git a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
index d79717062874418824d305a908926f1c61075255..5acdb38ca88a851cb96a3c375c51165b1e157531 100644
--- a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
+++ b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
+import eu.hbp.mip.utils.UserActionLogging;
import java.time.LocalDateTime;
@@ -26,8 +27,7 @@ import java.time.LocalDateTime;
@Api(value = "/protected", description = "the protected files API")
public class FilesAPI {
- private static final Logger LOGGER = LoggerFactory.getLogger(FilesAPI.class);
-
+
@Autowired
private UserInfo userInfo;
@@ -36,12 +36,12 @@ public class FilesAPI {
public ResponseEntity<Void> getProtectedFile(
@ApiParam(value = "filename", required = true) @PathVariable("filename") String filename
) {
- LOGGER.info("Get protected file");
+ UserActionLogging.LogAction("Get protected file", " filename : " + filename);
String filepath = "/protected/" + filename;
String user = userInfo.getUser().getUsername();
String time = LocalDateTime.now().toString();
- LOGGER.info("User " + user + " downloaded " + filepath + " at "+ time);
+ UserActionLogging.LogAction("User " + user + " downloaded " + filepath, "");
HttpHeaders headers = new HttpHeaders();
headers.add("X-Accel-Redirect", filepath);
diff --git a/src/main/java/eu/hbp/mip/controllers/JWTApi.java b/src/main/java/eu/hbp/mip/controllers/JWTApi.java
index a3d939bbba3eb5c5a8666497be9f5c6d6414e446..a1cb6afd55431bb859170b52c9daa7007ca69c42 100644
--- a/src/main/java/eu/hbp/mip/controllers/JWTApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/JWTApi.java
@@ -13,14 +13,13 @@ import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import eu.hbp.mip.utils.JWTUtil;
+import eu.hbp.mip.utils.UserActionLogging;
@RestController
@RequestMapping(value = "/jwt", produces = { TEXT_PLAIN_VALUE })
@Api(value = "/jwt", description = "the jwt API")
public class JWTApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(JWTApi.class);
-
@Autowired
private UserInfo userInfo;
@@ -31,7 +30,7 @@ public class JWTApi {
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<String> createJWT() {
- LOGGER.info("Create a JSON Web Token");
+ UserActionLogging.LogAction("Create a JSON Web Token", "");
User user = userInfo.getUser();
String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
diff --git a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
index fe7e8cd4535ac8af92603be12d40fad2bd264a74..f88f6795156f566b4b4e6e70288a5e4d535a67da 100644
--- a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
@@ -15,14 +15,14 @@ import java.io.IOException;
import eu.hbp.mip.utils.JWTUtil;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import org.springframework.beans.factory.annotation.Autowired;
+import eu.hbp.mip.utils.UserActionLogging;
@RestController
@RequestMapping(value = "/methods", produces = { APPLICATION_JSON_VALUE })
@Api(value = "/methods", description = "the methods API")
public class MethodsApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(MethodsApi.class);
-
+
private static final Gson gson = new Gson();
@Value("#{'${services.exareme.algorithmsUrl:http://localhost:9090/mining/algorithms.json}'}")
@@ -40,7 +40,7 @@ public class MethodsApi {
@ApiOperation(value = "List Exareme algorithms and validations", response = String.class)
@RequestMapping(value = "/exareme", method = RequestMethod.GET)
public ResponseEntity<Object> getExaremeAlgorithms() {
- LOGGER.info("List Exareme algorithms and validations");
+ UserActionLogging.LogAction("List Exareme algorithms and validations", "");
try {
StringBuilder response = new StringBuilder();
@@ -57,7 +57,7 @@ public class MethodsApi {
@ApiOperation(value = "List Galaxy workflows", response = String.class)
@RequestMapping(value = "/workflows", method = RequestMethod.GET)
public ResponseEntity<Object> getWorkflows() {
- LOGGER.info("List Galaxy workflows");
+ UserActionLogging.LogAction("List Galaxy workflows", "");
try {
User user = userInfo.getUser();
diff --git a/src/main/java/eu/hbp/mip/controllers/MiningApi.java b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
index e34b317d48e37cdea220bc447c1b1a853b2ee8ed..13272fc7355ed509e5b030429409a98b83ac55e1 100644
--- a/src/main/java/eu/hbp/mip/controllers/MiningApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
@@ -21,6 +21,9 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
+
+import eu.hbp.mip.utils.UserActionLogging;
+
import org.springframework.web.bind.annotation.*;
@@ -37,7 +40,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/mining", description = "the mining API")
public class MiningApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(MiningApi.class);
private static final Gson gson = new Gson();
@Autowired
@@ -49,7 +51,7 @@ public class MiningApi {
@ApiOperation(value = "Create an histogram on Exareme", response = String.class)
@RequestMapping(value = "/exareme", method = RequestMethod.POST)
public ResponseEntity runExaremeMining(@RequestBody List<HashMap<String, String>> queryList) {
- LOGGER.info("Run an histogram");
+ UserActionLogging.LogAction("Run an histogram", "");
String query = gson.toJson(queryList);
String url = miningExaremeQueryUrl + "/" + "HISTOGRAMS";
@@ -67,7 +69,7 @@ public class MiningApi {
@ApiOperation(value = "Create an descriptive statistic on Exareme", response = String.class)
@RequestMapping(value = "/exareme-stats", method = RequestMethod.POST)
public ResponseEntity runExaremeDescriptiveStats(@RequestBody List<HashMap<String, String>> queryList) {
- LOGGER.info("Run descriptive stats");
+ UserActionLogging.LogAction("Run descriptive stats", "");
String query = gson.toJson(queryList);
String url = miningExaremeQueryUrl + "/" + "DESCRIPTIVE_STATS";
@@ -88,7 +90,7 @@ public class MiningApi {
@RequestBody List<HashMap<String, String>> queryList,
@ApiParam(value = "algorithmName", required = true) @PathVariable("algorithmName") String algorithmName
) {
- LOGGER.info("Run algo");
+ UserActionLogging.LogAction("Run algo", "");
String query = gson.toJson(queryList);
String url = miningExaremeQueryUrl + "/" + algorithmName;
diff --git a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
index 56bc1ce10bf5c4f322349720b69d48f6b14f61fe..02ee9ac6b25b353876566a7261a7e6deba962574 100644
--- a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
@@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
+import eu.hbp.mip.utils.UserActionLogging;
import java.io.IOException;
import java.util.*;
@@ -28,7 +29,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/models", description = "the models API")
public class ModelsApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(ModelsApi.class);
@Autowired
private UserInfo userInfo;
@@ -54,7 +54,7 @@ public class ModelsApi {
@ApiParam(value = "Only ask own models") @RequestParam(value = "own", required = false) Boolean own,
@ApiParam(value = "Only ask published models") @RequestParam(value = "valid", required = false) Boolean valid
) {
- LOGGER.info("Get models");
+ UserActionLogging.LogAction("Get models","");
User user = userInfo.getUser();
@@ -98,7 +98,7 @@ public class ModelsApi {
@RequestBody @ApiParam(value = "Model to create", required = true) Model model
) {
- LOGGER.info("Create a model");
+ UserActionLogging.LogAction("Create a model","");
User user = userInfo.getUser();
@@ -129,7 +129,7 @@ public class ModelsApi {
}
modelRepository.save(model);
- LOGGER.info("Model saved (also saved model.config and model.query)");
+ UserActionLogging.LogAction("Model saved (also saved model.config and model.query)"," id : " + model.getSlug());
return ResponseEntity.status(HttpStatus.CREATED).body(model);
}
@@ -165,7 +165,7 @@ public class ModelsApi {
slug = new Slugify().slugify(title);
} catch (IOException e) {
slug = ""; // Should never happen
- LOGGER.trace("Cannot slugify title", e);
+ //LOGGER.trace("Cannot slugify title", e);
}
return slug;
}
@@ -192,7 +192,7 @@ public class ModelsApi {
public ResponseEntity<Model> getAModel(
@ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
) {
- LOGGER.info("Get a model");
+ UserActionLogging.LogAction("Get a model", " id : " + slug);
User user = userInfo.getUser();
@@ -200,7 +200,7 @@ public class ModelsApi {
if(model == null)
{
- LOGGER.warn("Cannot find model : " + slug);
+ //LOGGER.warn("Cannot find model : " + slug);
return ResponseEntity.badRequest().body(null);
}
@@ -224,7 +224,7 @@ public class ModelsApi {
@ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
@RequestBody @ApiParam(value = "Model to update", required = true) Model model
) {
- LOGGER.info("Update a model");
+ UserActionLogging.LogAction("Update a model", " id : "+ slug);
User user = userInfo.getUser();
Model oldModel = modelRepository.findOne(slug);
@@ -269,7 +269,7 @@ public class ModelsApi {
datasetRepository.save(model.getDataset());
modelRepository.save(model);
- LOGGER.info("Model updated (also saved/updated model.config and model.query)");
+ UserActionLogging.LogAction("Model updated (also saved/updated model.config and model.query)", " id : "+ slug);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
diff --git a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java b/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
index 59511de85016213a66eb576e8ea7f8410d5d6b0f..27f635d3278e9a2990489b4a3c01bd0d9851c34a 100644
--- a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
@@ -18,6 +18,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import eu.hbp.mip.utils.UserActionLogging;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@@ -28,6 +29,8 @@ public class PathologiesApi {
@RequestMapping(name = "/pathologies", method = RequestMethod.GET)
public String getPathologies() {
+ UserActionLogging.LogAction("load the pathologies", "");
+
return loadPathologies();
}
diff --git a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
index cfddbd334d3070cb433672b93b3bc0d205339e10..0f93c437ea8477000e1881815cce984eca36f3f8 100644
--- a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
@@ -17,6 +17,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
+import org.springframework.security.access.prepost.PreAuthorize;
+import eu.hbp.mip.utils.UserActionLogging;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@@ -29,8 +31,6 @@ import java.util.Base64;
@RestController
public class SecurityApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(SecurityApi.class);
-
private static final Gson gson = new Gson();
@Autowired
@@ -45,7 +45,8 @@ public class SecurityApi {
@RequestMapping(path = "/user", method = RequestMethod.GET)
public Object user(Principal principal, HttpServletResponse response) {
ObjectMapper mapper = new ObjectMapper();
-
+
+ UserActionLogging.LogAction("get user from /user","");
try {
String userJSON = mapper.writeValueAsString(userInfo.getUser());
Cookie cookie = new Cookie("user", URLEncoder.encode(userJSON, "UTF-8"));
@@ -53,7 +54,7 @@ public class SecurityApi {
cookie.setPath("/");
response.addCookie(cookie);
} catch (JsonProcessingException | UnsupportedEncodingException e) {
- LOGGER.trace("Cannot read user json", e);
+ //LOGGER.trace("Cannot read user json", e);
}
if (!securityConfiguration.isAuthentication()) {
@@ -76,6 +77,9 @@ public class SecurityApi {
user.setAgreeNDA(agreeNDA);
userRepository.save(user);
}
+
+ UserActionLogging.LogAction("user agreeNDA","");
+
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@@ -102,13 +106,15 @@ public class SecurityApi {
*/
@RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
+ @PreAuthorize("hasRole('Data Manager')")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity getGalaxyConfiguration(){
String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes());
JsonObject object = new JsonObject();
object.addProperty("authorization", stringEncoded);
object.addProperty("context", galaxyContext);
-
+ UserActionLogging.LogAction("get galaxy information","");
+
return ResponseEntity.ok(gson.toJson(object));
}
diff --git a/src/main/java/eu/hbp/mip/controllers/StatsApi.java b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
index d09c032bc75659c18100a4f58ca3965c2e4b4933..a92adecde01cb383ce4c677b2476b27afa862437 100644
--- a/src/main/java/eu/hbp/mip/controllers/StatsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
@@ -3,7 +3,7 @@
*/
package eu.hbp.mip.controllers;
-
+import eu.hbp.mip.utils.UserActionLogging;
import eu.hbp.mip.model.GeneralStats;
import eu.hbp.mip.repositories.ArticleRepository;
import eu.hbp.mip.repositories.UserRepository;
@@ -25,8 +25,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/stats", description = "the stats API")
public class StatsApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(StatsApi.class);
-
+
@Autowired
private UserRepository userRepository;
@@ -37,7 +36,7 @@ public class StatsApi {
@ApiOperation(value = "Get general statistics", response = GeneralStats.class)
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<GeneralStats> getGeneralStatistics() {
- LOGGER.info("Get statistics (count on users, articles and variables)");
+ UserActionLogging.LogAction("Get statistics (count on users, articles and variables)","");
GeneralStats stats = new GeneralStats();
diff --git a/src/main/java/eu/hbp/mip/controllers/UsersApi.java b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
index 89767017e0557b231e200006f8e330d9ca44ee9c..ed3104eb807ab844c25f20df69fac2c200ed0bf2 100644
--- a/src/main/java/eu/hbp/mip/controllers/UsersApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
@@ -4,6 +4,7 @@
package eu.hbp.mip.controllers;
+import eu.hbp.mip.utils.UserActionLogging;
import io.swagger.annotations.*;
import eu.hbp.mip.model.User;
import eu.hbp.mip.repositories.UserRepository;
@@ -23,8 +24,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@Api(value = "/users", description = "the users API")
public class UsersApi {
- private static final Logger LOGGER = LoggerFactory.getLogger(UsersApi.class);
-
@Autowired
private UserRepository userRepository;
@@ -33,7 +32,7 @@ public class UsersApi {
public ResponseEntity<User> getAUser(
@ApiParam(value = "username", required = true) @PathVariable("username") String username
) {
- LOGGER.info("Get a user");
+ UserActionLogging.LogAction("Get a user","");
return ResponseEntity.ok(userRepository.findOne(username));
}
diff --git a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
new file mode 100644
index 0000000000000000000000000000000000000000..745fc24a6ca53951c1f43cd9db2f6fa5965a73d4
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
@@ -0,0 +1,23 @@
+package eu.hbp.mip.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.time.LocalTime;
+
+public class UserActionLogging {
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(UserActionLogging.class);
+
+ public static void LogAction(String actionName, String actionIdInfo)
+ {
+ LOGGER.info( LocalTime.now()+" User : "
+ + SecurityContextHolder.getContext().getAuthentication().getName()
+ + " called enpoint " + actionName
+ + " info "
+ + actionIdInfo);
+ }
+
+}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..efd7a874adcd194ee0145465dca9c08c1f3f5c5d
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+<configuration>
+ <appender name="FILE1" class="ch.qos.logback.core.FileAppender">
+ <file>logs/log1.txt</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="eu.hbp.mip">
+ <appender-ref ref="FILE1" />
+ </logger>
+ <logger name="org.springframework">
+ <appender-ref ref="FILE1" />
+ </logger>
+ <logger name="eu.hbp.mip.utils" level="INFO" additivity="false">
+ <appender-ref ref="FILE1" />
+ </logger>
+</configuration>
\ No newline at end of file