Commit e2d62e73 authored by femiadeyemi's avatar femiadeyemi
Browse files

helmholtz-cerebrum: init helmholtz marketplace resource server

parents
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
HELMHOLTZ MARKETPLACE CEREBRUM
===================
![](https://github.com/helmoltz-markeplace/helmoltz-cerebrum/workflows/CI/badge.svg)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>de.helmholtz.marketplace.cerebrum</groupId>
<artifactId>helmholtz-cerebrum</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helmholtz-cerebrum</name>
<description>helmholtz marketplace resources server</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-reactive-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
</dependency>
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>8.3</version>
</dependency>
<!-- test stuff -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.7.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@EnableNeo4jRepositories
@SpringBootApplication
public class HelmholtzCerebrumApplication
{
public static void main(String[] args) {
SpringApplication.run(HelmholtzCerebrumApplication.class, args);
}
}
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum.annotation;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* https://stackoverflow.com/questions/60727265/use-authenticationprincipal-with-jwtauthenticationtoken-to-use-own-user-class
*/
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal(expression = "@marketuserRepository.findBySub(#this)")
public @interface CurrentUser {}
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum.config;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.JettyClientHttpConnector;
import org.springframework.security.oauth2.server.resource.web.reactive.function.client.ServletBearerExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class CerebrumConfig
{
/**
* FIXME: This is workaround for the Internal Server Error
* org.springframework.web.util.NestedServletException:
* Request processing failed; nested exception is
* java.lang.NullPointerException: Missing SslContextFactory
*/
private final SslContextFactory ssl = new SslContextFactory();
private final HttpClient httpClient = new HttpClient(ssl);
ClientHttpConnector clientConnector = new JettyClientHttpConnector(httpClient);
@Bean
public WebClient authorisationServer() {
return WebClient.builder()
.filter(new ServletBearerExchangeFilterFunction())
.clientConnector(clientConnector)
.build();
}
}
package de.helmholtz.marketplace.cerebrum.config;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CerebrumMethodSecurityConfig extends GlobalMethodSecurityConfiguration {}
package de.helmholtz.marketplace.cerebrum.config;
import de.helmholtz.marketplace.cerebrum.repository.listeners.MarketUserEventHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CerebrumRepositoryConfig
{
public CerebrumRepositoryConfig() {
super();
}
@Bean
MarketUserEventHandler makeUserEventHandler() {
return new MarketUserEventHandler();
}
}
package de.helmholtz.marketplace.cerebrum.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import static org.springframework.security.config.Customizer.withDefaults;
@EnableWebSecurity
public class CerebrumSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors(withDefaults())
.mvcMatcher("/**")
.authorizeRequests()
.mvcMatchers("/api/v0/admin/**").hasRole("ADMIN")
.mvcMatchers("/api/v0/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("${cerebrum.allowed.client.origins}"));
configuration.setAllowedMethods(Arrays.asList("GET","DELETE","PUT","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.helmholtz.marketplace.cerebrum.repository.MarketUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.Objects;
@RestController
@RequestMapping("${spring.data.rest.base-path}")
public class MarketUserController
{
private final WebClient authorisationServer;
private final MarketUserRepository marketUserRepository;
@Autowired
public MarketUserController(WebClient authorisationServer, MarketUserRepository marketUserRepository) {
this.authorisationServer = authorisationServer;
this.marketUserRepository = marketUserRepository;
}
@PreAuthorize("isAuthenticated()")
@GetMapping(path = "/whoami")
public JsonNode whoami() {
return this.authorisationServer
.get()
.uri("https://login.helmholtz-data-federation.de/oauth2/userinfo")
.retrieve()
.bodyToMono(JsonNode.class)
.block();
}
public boolean isSomebody(JwtAuthenticationToken token) {
if (Objects.isNull(token)) return false;
String name = marketUserRepository.findBySub((String) token.getTokenAttributes().get("sub")).getFirstName();
if (Objects.isNull(name)) return false;
return name.trim().isEmpty();
}
}
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum.entities;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
@NodeEntity
public class MarketUser
{
@Id @GeneratedValue private Long id;
private String firstName;
private String lastName;
private String screenName;
private String email;
private String sub;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getScreenName() {
return screenName;
}
public void setScreenName(String screenName) {
this.screenName = screenName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSub() {
return sub;
}
public void setSub(String sub) {
this.sub = sub;
}
}
package de.helmholtz.marketplace.cerebrum.repository;
import de.helmholtz.marketplace.cerebrum.entities.MarketUser;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource ;
import org.springframework.security.access.prepost.PreAuthorize;
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface MarketUserRepository extends CrudRepository<MarketUser, Long>
{
MarketUser findBySub(@Param("sub") String sub);
@PreAuthorize("hasAnyAuthority('ADMIN')")
MarketUser save (MarketUser user);
}
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum.repository.listeners;
import de.helmholtz.marketplace.cerebrum.entities.MarketUser;
import org.springframework.data.rest.core.annotation.*;
import java.util.logging.Logger;
@RepositoryEventHandler
public class MarketUserEventHandler
{
Logger logger = Logger.getLogger("Class MarketUserEventHandler");
public MarketUserEventHandler() {
super();
}
@HandleAfterCreate
public void handleMarketUserBeforeCreate(MarketUser user) {
logger.info("A new MarketUser is created successfully....");
String name = user.getFirstName();
}
}
\ No newline at end of file
cerebrum:
allowed:
client:
origins:
- https://localhost
- http://localhost:8080
logging:
level:
root: INFO
org.springframework.web: INFO
org.springframework.security: INFO
org.springframework.security.oauth2: INFO
org.springframework.boot.autoconfigure: DEBUG
server:
port: 8090
spring:
data:
rest:
base-path: /api/v0
neo4j:
username: neo4j
password: secret
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://login.helmholtz-data-federation.de/oauth2
jwk-set-uri: https://login.helmholtz-data-federation.de/oauth2/jwk
\ No newline at end of file
package de.helmholtz.marketplace.cerebrum;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class HelmholtzCerebrumApplicationTest
{
@Test
void contextLoads() {}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment