Skip to content

Commit

Permalink
Add development infra
Browse files Browse the repository at this point in the history
Replace Feign with spring-addons-starter-rest & RestClient

Use MapStruct
  • Loading branch information
ch4mpy committed Jun 18, 2024
1 parent 1ee9704 commit 18224eb
Show file tree
Hide file tree
Showing 81 changed files with 24,923 additions and 1,625 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
KEYCLOAK_ADMIN_PASSWORD=admin
POSTGRES_QUIZ_PASSWORD=secret
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,6 @@ resource-server-spring/**

# OpenAPI specs
**/*.openapi.json

# Generated infra
compose-*.yml
12 changes: 12 additions & 0 deletions angular-ui.app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideHttpClient()],
};

export const reverseProxyUri = 'http://LOCALHOST_NAME:7080';
export const baseUri = `${reverseProxyUri}/angular-ui/`;
1 change: 1 addition & 0 deletions api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!keycloak-admin-api.openapi.json
8 changes: 8 additions & 0 deletions api/bff/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@
<profiles>
<profile>
<id>openapi</id>
<properties>
<integration-tests.port>7080</integration-tests.port>
</properties>
<dependencies>
<dependency>
<groupId>org.springdoc</groupId>
Expand Down Expand Up @@ -124,6 +127,11 @@
<goals>
<goal>start</goal>
</goals>
<configuration>
<environmentVariables>
<KEYCLOAK_HOST>https://oidc.c4-soft.com/auth</KEYCLOAK_HOST>
</environmentVariables>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
Expand Down
6 changes: 3 additions & 3 deletions api/bff/src/main/java/com/c4soft/quiz/BffApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@SpringBootApplication
public class BffApplication {

public static void main(String[] args) {
SpringApplication.run(BffApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(BffApplication.class, args);
}
}
47 changes: 24 additions & 23 deletions api/bff/src/main/java/com/c4soft/quiz/BffController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

import java.net.URISyntaxException;
import java.util.List;

import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
Expand All @@ -21,24 +18,28 @@
@RestController
@Tag(name = "BFF")
public class BffController {
private final List<LoginOptionDto> loginOptions;

public BffController(
OAuth2ClientProperties clientProps,
SpringAddonsOidcProperties addonsProperties,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
this.loginOptions = clientProps.getRegistration().entrySet().stream().filter(e -> "authorization_code".equals(e.getValue().getAuthorizationGrantType()))
.map(e -> new LoginOptionDto(e.getValue().getProvider(), "%s/oauth2/authorization/%s".formatted(addonsProperties.getClient().getClientUri(), e.getKey())))
.toList();
}

@GetMapping(path = "/login-options", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "getLoginOptions")
public Mono<List<LoginOptionDto>> getLoginOptions(Authentication auth) throws URISyntaxException {
final boolean isAuthenticated = auth instanceof OAuth2AuthenticationToken;
return Mono.just(isAuthenticated ? List.of() : this.loginOptions);
}

public static record LoginOptionDto(@NotEmpty String label, @NotEmpty String loginUri) {
}
private final List<LoginOptionDto> loginOptions;

public BffController(OAuth2ClientProperties clientProps,
SpringAddonsOidcProperties addonsProperties,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
this.loginOptions =
clientProps.getRegistration().entrySet().stream()
.filter(e -> "authorization_code".equals(e.getValue().getAuthorizationGrantType()))
.map(
e -> new LoginOptionDto(e.getValue().getProvider(),
"%s/oauth2/authorization/%s"
.formatted(addonsProperties.getClient().getClientUri(), e.getKey())))
.toList();
}

@GetMapping(path = "/login-options", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "getLoginOptions")
public Mono<List<LoginOptionDto>> getLoginOptions(Authentication auth) throws URISyntaxException {
final boolean isAuthenticated = auth instanceof OAuth2AuthenticationToken;
return Mono.just(isAuthenticated ? List.of() : this.loginOptions);
}

public static record LoginOptionDto(@NotEmpty String label, @NotEmpty String loginUri) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"type": "java.lang.String",
"description": "'http' or 'https', used to build URIs involved in authentication and can be used in 'gateway-uri', 'bao-loc-api-uri' or 'ui-uri'"
},
{
"name": "hostname",
"type": "java.lang.String",
"description": "the host name"
},
{
"name": "oauth2-issuer",
"type": "java.lang.String",
Expand Down
47 changes: 12 additions & 35 deletions api/bff/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
scheme: http
keycloak-host: https://oidc.c4-soft.com/auth
hostname: localhost
keycloak-host: http://${hostname}/auth
keycloak-realm: quiz
oauth2-issuer: ${keycloak-host}/realms/${keycloak-realm}
oauth2-client-id: quiz-bff
oauth2-client-secret: change-me
oauth2-client-secret: secret

gateway-uri: ${scheme}://localhost:${server.port}
quiz-api-uri: ${scheme}://localhost:7084
ui-host: https://localhost:4200
gateway-uri: ${scheme}://${hostname}:${server.port}
quiz-api-uri: ${scheme}://${hostname}:7084

server:
port: 8080
shutdown: graceful
port: 7080
ssl:
enabled: false

Expand All @@ -35,29 +34,12 @@ spring:
client-id: ${oauth2-client-id}
client-secret: ${oauth2-client-secret}
authorization-grant-type: authorization_code
scope:
- openid
- profile
- email
- offline_access
scope: openid, profile, email, offline_access
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin Access-Control-Request-Method Access-Control-Request-Headers
routes:
# Redirection from / to /ui/
- id: home
uri: ${gateway-uri}
predicates:
- Path=/
filters:
- RedirectTo=301,${gateway-uri}/ui/
# Serve the Angular app through the gateway
- id: ui
uri: ${ui-host}
predicates:
- Path=/ui/**
# Access the quiz API with BFF pattern
- id: quiz-bff
uri: ${quiz-api-uri}
predicates:
Expand All @@ -66,14 +48,6 @@ spring:
- TokenRelay=
- SaveSession
- StripPrefix=2
# Access the quiz API with OAuth2 clients like Postman
- id: quiz-resource-server
uri: ${quiz-api-uri}
predicates:
- Path=/resource-server/v1/**
filters:
- SaveSession
- StripPrefix=2
# Cert-manager http01 challenge for SSL certificates on K8s
- id: letsencrypt
uri: https://cert-manager-webhook
Expand All @@ -95,24 +69,27 @@ com:
security-matchers:
- /login/**
- /oauth2/**
- /logout
- /logout/**
- /bff/**
permit-all:
- /login/**
- /oauth2/**
- /logout/connect/back-channel/quiz-bff
- /bff/**
csrf: cookie-accessible-from-js
post-login-redirect-path: /ui/
post-logout-redirect-path: /ui/
oauth2-redirections:
rp-initiated-logout: ACCEPTED
pkce-forced: true
back-channel-logout:
enabled: true
internal-logout-uri: ${scheme}://${hostname}:${serve.port}/logout
# OAuth2 resource server configuration
resourceserver:
permit-all:
- /login-options
- /ui/**
- /resource-server/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
Expand Down
Loading

0 comments on commit 18224eb

Please sign in to comment.