From ecc4715cb504375c9b025c19cb9eca2e4dc4f318 Mon Sep 17 00:00:00 2001 From: nenzen Date: Sat, 10 Jan 2026 16:58:53 +0100 Subject: [PATCH 01/15] Add checkstyle configuration files --- bff/checkstyle-configuration.xml | 203 +++++++++++++++++++++++++++++++ bff/checkstyle-suppressions.xml | 9 ++ 2 files changed, 212 insertions(+) create mode 100644 bff/checkstyle-configuration.xml create mode 100644 bff/checkstyle-suppressions.xml diff --git a/bff/checkstyle-configuration.xml b/bff/checkstyle-configuration.xml new file mode 100644 index 0000000..b84802b --- /dev/null +++ b/bff/checkstyle-configuration.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bff/checkstyle-suppressions.xml b/bff/checkstyle-suppressions.xml new file mode 100644 index 0000000..3c57c7f --- /dev/null +++ b/bff/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + -- 2.39.5 From d7932a5b7e42d9fa3438f6f2212bf17274cb64c0 Mon Sep 17 00:00:00 2001 From: nenzen Date: Sat, 10 Jan 2026 17:01:51 +0100 Subject: [PATCH 02/15] Add checkstyle Maven plugin --- bff/pom.xml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/bff/pom.xml b/bff/pom.xml index 9786d17..8f7dca5 100644 --- a/bff/pom.xml +++ b/bff/pom.xml @@ -20,6 +20,7 @@ UTF-8 25 2.8.6 + 10.21.4 @@ -60,8 +61,40 @@ + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.6.0 + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + + + + checkstyle-configuration.xml + true + true + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + validate + validate + + check + + + + + -- 2.39.5 From 142353ea98e7fc1be26e5bce5668267b3c0dd818 Mon Sep 17 00:00:00 2001 From: nenzen Date: Mon, 12 Jan 2026 18:20:56 +0100 Subject: [PATCH 03/15] Change LeftCurly rule to align with prettier --- bff/checkstyle-configuration.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bff/checkstyle-configuration.xml b/bff/checkstyle-configuration.xml index b84802b..1dd5ab9 100644 --- a/bff/checkstyle-configuration.xml +++ b/bff/checkstyle-configuration.xml @@ -155,7 +155,7 @@ - + -- 2.39.5 From 51615cc3b1650d504550b16f73a97b33a2f040bd Mon Sep 17 00:00:00 2001 From: nenzen Date: Mon, 12 Jan 2026 18:22:01 +0100 Subject: [PATCH 04/15] Add prettier --- bff/.prettierrc.yaml | 2 + bff/package-lock.json | 140 ++++++++++++++++++++++++++++++++++++++++++ bff/package.json | 5 ++ 3 files changed, 147 insertions(+) create mode 100644 bff/.prettierrc.yaml create mode 100644 bff/package-lock.json create mode 100644 bff/package.json diff --git a/bff/.prettierrc.yaml b/bff/.prettierrc.yaml new file mode 100644 index 0000000..3a4f5ee --- /dev/null +++ b/bff/.prettierrc.yaml @@ -0,0 +1,2 @@ +plugins: + - prettier-plugin-java diff --git a/bff/package-lock.json b/bff/package-lock.json new file mode 100644 index 0000000..6ccbb35 --- /dev/null +++ b/bff/package-lock.json @@ -0,0 +1,140 @@ +{ + "name": "bff", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "prettier-plugin-java": "^2.8.1" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/java-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-3.0.1.tgz", + "integrity": "sha512-sDIR7u9b7O2JViNUxiZRhnRz7URII/eE7g2B+BmGxDeS6Ex3OYAcCyz5oh0H4LQ+hL/BS8OJTz8apMy9xtGmrQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chevrotain": "11.0.3", + "chevrotain-allstar": "0.3.1", + "lodash": "4.17.21" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-java": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-2.8.1.tgz", + "integrity": "sha512-tkteH5OSCEb0E7wKnhhUSitr1pGUCUt9M//CwerSNhoalL/qv0jXTeSVBPZ36KC+kZl3nbq4dxh144NuGchACg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "java-parser": "3.0.1" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + } + } +} diff --git a/bff/package.json b/bff/package.json new file mode 100644 index 0000000..6f88278 --- /dev/null +++ b/bff/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "prettier-plugin-java": "^2.8.1" + } +} -- 2.39.5 From f909afb3985d06884f4eb5c7790cd9a4e63cd7d6 Mon Sep 17 00:00:00 2001 From: nenzen Date: Mon, 12 Jan 2026 18:22:16 +0100 Subject: [PATCH 05/15] Ignore node_modules --- bff/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/bff/.gitignore b/bff/.gitignore index 2f7896d..71ee748 100644 --- a/bff/.gitignore +++ b/bff/.gitignore @@ -1 +1,2 @@ target/ +node_modules -- 2.39.5 From 0e3c33a1d0ba5237d58fac2b833729e7b34eb693 Mon Sep 17 00:00:00 2001 From: nenzen Date: Mon, 12 Jan 2026 18:22:54 +0100 Subject: [PATCH 06/15] Run prettier --- .../studentportalen/bff/Studentportalen.java | 6 +- .../bff/config/BackendApiConfiguration.java | 3 +- .../bff/config/FrontendConfiguration.java | 10 +- .../bff/config/SecurityConfiguration.java | 79 ++++++----- .../bff/controller/ProfileController.java | 20 +-- .../bff/controller/TestController.java | 133 +++++++++--------- .../bff/dto/response/ProfileResponse.java | 27 ++-- .../login/BFFAuthenticationEntryPoint.java | 27 ++-- .../bff/service/ProfileService.java | 8 +- 9 files changed, 164 insertions(+), 149 deletions(-) diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/Studentportalen.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/Studentportalen.java index 19d9281..97ed7eb 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/Studentportalen.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/Studentportalen.java @@ -11,7 +11,7 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer @ConfigurationPropertiesScan public class Studentportalen extends SpringBootServletInitializer { - public static void main(String[] args) { - SpringApplication.run(Studentportalen.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Studentportalen.class, args); + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/BackendApiConfiguration.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/BackendApiConfiguration.java index a11ff1f..6214ce3 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/BackendApiConfiguration.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/BackendApiConfiguration.java @@ -3,5 +3,4 @@ package se.su.dsv.studentportalen.bff.config; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("se.su.dsv.backend-api") -public record BackendApiConfiguration(String daisyUrl) { -} +public record BackendApiConfiguration(String daisyUrl) {} diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/FrontendConfiguration.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/FrontendConfiguration.java index ad670db..bd7d358 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/FrontendConfiguration.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/FrontendConfiguration.java @@ -4,9 +4,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("se.su.dsv.frontend") public record FrontendConfiguration(String url) { - public FrontendConfiguration { - if (url == null || url.isBlank()) { - throw new IllegalArgumentException("se.su.dsv.frontend.url must not be null or blank"); - } + public FrontendConfiguration { + if (url == null || url.isBlank()) { + throw new IllegalArgumentException( + "se.su.dsv.frontend.url must not be null or blank" + ); } + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/SecurityConfiguration.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/SecurityConfiguration.java index d188365..daca14d 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/config/SecurityConfiguration.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/config/SecurityConfiguration.java @@ -1,5 +1,6 @@ package se.su.dsv.studentportalen.bff.config; +import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -7,45 +8,55 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import se.su.dsv.studentportalen.bff.login.BFFAuthenticationEntryPoint; -import java.util.List; - @Configuration public class SecurityConfiguration { - @Bean - public SecurityFilterChain securityFilterChain( - HttpSecurity http, - FrontendConfiguration frontendConfiguration) - throws Exception - { - http.exceptionHandling(exception -> exception - .authenticationEntryPoint(new BFFAuthenticationEntryPoint())); - http.oauth2Login(login -> login - .defaultSuccessUrl(frontendConfiguration.url(), true)); - http.authorizeHttpRequests(authorize -> authorize - .requestMatchers("/swagger", "/swagger-ui/**", "/v3/api-docs/**").permitAll() - .anyRequest().authenticated()); - http.cors(cors -> cors - .configurationSource(_ -> frontendOnlyCors(frontendConfiguration))); - http.csrf(csrf -> csrf.spa()); - return http.build(); - } + @Bean + public SecurityFilterChain securityFilterChain( + HttpSecurity http, + FrontendConfiguration frontendConfiguration + ) throws Exception { + http.exceptionHandling(exception -> + exception.authenticationEntryPoint(new BFFAuthenticationEntryPoint()) + ); + http.oauth2Login(login -> + login.defaultSuccessUrl(frontendConfiguration.url(), true) + ); + http.authorizeHttpRequests(authorize -> + authorize + .requestMatchers("/swagger", "/swagger-ui/**", "/v3/api-docs/**") + .permitAll() + .anyRequest() + .authenticated() + ); + http.cors(cors -> + cors.configurationSource(_ -> frontendOnlyCors(frontendConfiguration)) + ); + http.csrf(csrf -> csrf.spa()); + return http.build(); + } - private static CorsConfiguration frontendOnlyCors(FrontendConfiguration frontendConfiguration) { - var corsConfiguration = new CorsConfiguration(); - corsConfiguration.setAllowedOrigins(List.of(frontendConfiguration.url())); - corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); + private static CorsConfiguration frontendOnlyCors( + FrontendConfiguration frontendConfiguration + ) { + var corsConfiguration = new CorsConfiguration(); + corsConfiguration.setAllowedOrigins(List.of(frontendConfiguration.url())); + corsConfiguration.setAllowedMethods( + List.of("GET", "POST", "PUT", "DELETE") + ); - // Allow the frontend to see the X-Authorization-Url header - corsConfiguration.setExposedHeaders(List.of("X-Authorization-Url")); + // Allow the frontend to see the X-Authorization-Url header + corsConfiguration.setExposedHeaders(List.of("X-Authorization-Url")); - // To allow the session cookie to be included - corsConfiguration.setAllowCredentials(true); + // To allow the session cookie to be included + corsConfiguration.setAllowCredentials(true); - // Content-Type is allowed by default but with a restriction on the value - // The restriction does not allow "application/json" so we add it as an allowed header - // X-XSRF-TOKEN is needed for CSRF protection - corsConfiguration.setAllowedHeaders(List.of("Content-Type", "X-XSRF-TOKEN")); - return corsConfiguration; - } + // Content-Type is allowed by default but with a restriction on the value + // The restriction does not allow "application/json" so we add it as an allowed header + // X-XSRF-TOKEN is needed for CSRF protection + corsConfiguration.setAllowedHeaders( + List.of("Content-Type", "X-XSRF-TOKEN") + ); + return corsConfiguration; + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/ProfileController.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/ProfileController.java index eb97bd2..91313b6 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/ProfileController.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/ProfileController.java @@ -16,16 +16,16 @@ import se.su.dsv.studentportalen.bff.service.ProfileService; @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) public class ProfileController { - private final ProfileService service; + private final ProfileService service; - public ProfileController(ProfileService service) { - this.service = service; - } + public ProfileController(ProfileService service) { + this.service = service; + } - @GetMapping("/profile") - public ProfileResponse getProfile( - @AuthenticationPrincipal(errorOnInvalidType = true) OAuth2User currentUser) - { - return service.getProfile(currentUser); - } + @GetMapping("/profile") + public ProfileResponse getProfile( + @AuthenticationPrincipal(errorOnInvalidType = true) OAuth2User currentUser + ) { + return service.getProfile(currentUser); + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/TestController.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/TestController.java index b977a13..1b4d890 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/TestController.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/controller/TestController.java @@ -1,85 +1,88 @@ package se.su.dsv.studentportalen.bff.controller; +import java.time.Duration; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.StructuredTaskScope; +import java.util.concurrent.StructuredTaskScope.Subtask; import org.springframework.context.annotation.Profile; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestClient; import se.su.dsv.studentportalen.bff.config.BackendApiConfiguration; -import java.time.Duration; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.StructuredTaskScope; -import java.util.concurrent.StructuredTaskScope.Subtask; - @RestController @RequestMapping("/test") @Profile("development") public class TestController { - private static final int NAME_DELAY_SECONDS = 2; - private static final int EMAIL_DELAY_SECONDS = 3; + private static final int NAME_DELAY_SECONDS = 2; + private static final int EMAIL_DELAY_SECONDS = 3; - private final RestClient restClient; - private final BackendApiConfiguration backendApiConfiguration; + private final RestClient restClient; + private final BackendApiConfiguration backendApiConfiguration; - public TestController(final BackendApiConfiguration backendApiConfiguration) { - this.backendApiConfiguration = backendApiConfiguration; - this.restClient = RestClient.builder() - .baseUrl("http://localhost:8080") - .build(); + public TestController(final BackendApiConfiguration backendApiConfiguration) { + this.backendApiConfiguration = backendApiConfiguration; + this.restClient = RestClient.builder() + .baseUrl("http://localhost:8080") + .build(); + } + + @RequestMapping + public String helloWorld() throws InterruptedException, ExecutionException { + // Pick the scope based on the desired behaviour + try (var scope = StructuredTaskScope.open()) { + Subtask nameTask = scope.fork(() -> { + String name = restClient + .get() + .uri("/test/name") + .retrieve() + .body(String.class); + return name; + }); + + Subtask emailTask = scope.fork(() -> { + String email = restClient + .get() + .uri("/test/email") + .retrieve() + .body(String.class); + return email; + }); + + Subtask daisyProfile = scope.fork(() -> { + DaisyProfile profile = restClient + .get() + .uri(backendApiConfiguration.daisyUrl(), builder -> + builder.path("/profile").build() + ) + .retrieve() + .body(DaisyProfile.class); + return profile; + }); + + // Wait for all tasks to complete (either success or failure) + scope.join(); + + return "Hello, I am %s and my email is %s. My Daisy profile is: %s".formatted( + nameTask.get(), + emailTask.get(), + daisyProfile.get() + ); } + } - @RequestMapping - public String helloWorld() throws InterruptedException, ExecutionException { - // Pick the scope based on the desired behaviour - try (var scope = StructuredTaskScope.open()) { - Subtask nameTask = scope.fork(() -> { - String name = restClient.get() - .uri("/test/name") - .retrieve() - .body(String.class); - return name; - }); + @RequestMapping("/name") + public String name() throws InterruptedException { + Thread.sleep(Duration.ofSeconds(NAME_DELAY_SECONDS)); + return "Greg"; + } - Subtask emailTask = scope.fork(() -> { - String email = restClient.get() - .uri("/test/email") - .retrieve() - .body(String.class); - return email; - }); + @RequestMapping("/email") + public String email() throws InterruptedException { + Thread.sleep(Duration.ofSeconds(EMAIL_DELAY_SECONDS)); + return "greg@localhost"; + } - Subtask daisyProfile = scope.fork(() -> { - DaisyProfile profile = restClient.get() - .uri(backendApiConfiguration.daisyUrl(), builder -> builder - .path("/profile") - .build()) - .retrieve() - .body(DaisyProfile.class); - return profile; - }); - - // Wait for all tasks to complete (either success or failure) - scope.join(); - - return "Hello, I am %s and my email is %s. My Daisy profile is: %s".formatted( - nameTask.get(), - emailTask.get(), - daisyProfile.get()); - } - } - - @RequestMapping("/name") - public String name() throws InterruptedException { - Thread.sleep(Duration.ofSeconds(NAME_DELAY_SECONDS)); - return "Greg"; - } - - @RequestMapping("/email") - public String email() throws InterruptedException { - Thread.sleep(Duration.ofSeconds(EMAIL_DELAY_SECONDS)); - return "greg@localhost"; - } - - record DaisyProfile(String name, String mail) {} + record DaisyProfile(String name, String mail) {} } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/dto/response/ProfileResponse.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/dto/response/ProfileResponse.java index a5c655c..4361f29 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/dto/response/ProfileResponse.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/dto/response/ProfileResponse.java @@ -1,26 +1,25 @@ package se.su.dsv.studentportalen.bff.dto.response; import com.fasterxml.jackson.annotation.JsonProperty; - import java.util.Objects; /** * User profile information. */ public record ProfileResponse( - @JsonProperty(value = "name", required = true) - String name, + @JsonProperty(value = "name", required = true) String name, - @JsonProperty(value = "language", required = true) - Language language) -{ - public enum Language { - @JsonProperty("sv") SWEDISH, - @JsonProperty("en") ENGLISH - } + @JsonProperty(value = "language", required = true) Language language +) { + public enum Language { + @JsonProperty("sv") + SWEDISH, + @JsonProperty("en") + ENGLISH, + } - public ProfileResponse { - Objects.requireNonNull(name, "name must be specified"); - Objects.requireNonNull(language, "language must be specified"); - } + public ProfileResponse { + Objects.requireNonNull(name, "name must be specified"); + Objects.requireNonNull(language, "language must be specified"); + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/login/BFFAuthenticationEntryPoint.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/login/BFFAuthenticationEntryPoint.java index 9992289..915849e 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/login/BFFAuthenticationEntryPoint.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/login/BFFAuthenticationEntryPoint.java @@ -7,17 +7,18 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; public class BFFAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence( - HttpServletRequest request, - HttpServletResponse response, - AuthenticationException authException) - { - String loginUri = ServletUriComponentsBuilder.fromRequest(request) - .replacePath("/oauth2/authorization/studentportalen") - .build() - .toUriString(); - response.addHeader("X-Authorization-Url", loginUri); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - } + + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException + ) { + String loginUri = ServletUriComponentsBuilder.fromRequest(request) + .replacePath("/oauth2/authorization/studentportalen") + .build() + .toUriString(); + response.addHeader("X-Authorization-Url", loginUri); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + } } diff --git a/bff/src/main/java/se/su/dsv/studentportalen/bff/service/ProfileService.java b/bff/src/main/java/se/su/dsv/studentportalen/bff/service/ProfileService.java index a21963c..68ab003 100644 --- a/bff/src/main/java/se/su/dsv/studentportalen/bff/service/ProfileService.java +++ b/bff/src/main/java/se/su/dsv/studentportalen/bff/service/ProfileService.java @@ -10,8 +10,8 @@ import se.su.dsv.studentportalen.bff.dto.response.ProfileResponse; @Service public class ProfileService { - public ProfileResponse getProfile(OAuth2User currentUser) { - String name = currentUser.getAttribute("name"); - return new ProfileResponse(name, ProfileResponse.Language.ENGLISH); - } + public ProfileResponse getProfile(OAuth2User currentUser) { + String name = currentUser.getAttribute("name"); + return new ProfileResponse(name, ProfileResponse.Language.ENGLISH); + } } -- 2.39.5 From a403a01e074a54e7b196e872e6a390c14fc7cd2c Mon Sep 17 00:00:00 2001 From: nenzen Date: Mon, 12 Jan 2026 18:29:37 +0100 Subject: [PATCH 07/15] Include checkstyle --- branch-bff.Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/branch-bff.Dockerfile b/branch-bff.Dockerfile index 11697e9..f20bf78 100644 --- a/branch-bff.Dockerfile +++ b/branch-bff.Dockerfile @@ -5,6 +5,8 @@ WORKDIR /build COPY mvnw mvnw COPY .mvn/ .mvn/ COPY pom.xml pom.xml +COPY checkstyle-configuration.xml checkstyle-configuration.xml +COPY checkstyle-suppressions.xml checkstyle-suppressions.xml RUN ./mvnw dependency:go-offline \ --batch-mode \ -- 2.39.5 From b4d51dbae7a78b14f8f4a5827929ad00f58e8132 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 08:22:44 +0100 Subject: [PATCH 08/15] Add prettier maven plugin --- bff/pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bff/pom.xml b/bff/pom.xml index 8f7dca5..f323f16 100644 --- a/bff/pom.xml +++ b/bff/pom.xml @@ -78,6 +78,14 @@ true + + com.hubspot.maven.plugins + prettier-maven-plugin + 0.22 + + 2.8.1 + + @@ -94,6 +102,18 @@ + + com.hubspot.maven.plugins + prettier-maven-plugin + + + validate + + check + + + + -- 2.39.5 From 33938f7f70c1976e9cf8480ad8dfe1e225235389 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 08:26:57 +0100 Subject: [PATCH 09/15] Add gitea action to run validate --- .gitea/workflows/code-style.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .gitea/workflows/code-style.yaml diff --git a/.gitea/workflows/code-style.yaml b/.gitea/workflows/code-style.yaml new file mode 100644 index 0000000..674c60b --- /dev/null +++ b/.gitea/workflows/code-style.yaml @@ -0,0 +1,19 @@ +name: Code style BFF +on: + - pull_request + - push +jobs: + check: + runs-on: ubuntu-latest + defaults: + run: + working-directory: bff + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 25 + cache: maven + - name: Run checkstyle and prettier + run: mvn validate --batch-mode -- 2.39.5 From ca71c27ac2072236e3fadc628e3da43cde0edc31 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 08:29:21 +0100 Subject: [PATCH 10/15] Don't run twice on push to PR --- .gitea/workflows/code-style.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/code-style.yaml b/.gitea/workflows/code-style.yaml index 674c60b..dd8ff68 100644 --- a/.gitea/workflows/code-style.yaml +++ b/.gitea/workflows/code-style.yaml @@ -1,7 +1,9 @@ name: Code style BFF on: - - pull_request - - push + pull_request: + push: + branches: + - main jobs: check: runs-on: ubuntu-latest -- 2.39.5 From 9de6d9611f86f78a0125f9b9b06ec20ab73acabd Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 08:30:31 +0100 Subject: [PATCH 11/15] Use ./mvnw instead of mvn --- .gitea/workflows/code-style.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/code-style.yaml b/.gitea/workflows/code-style.yaml index dd8ff68..50538bd 100644 --- a/.gitea/workflows/code-style.yaml +++ b/.gitea/workflows/code-style.yaml @@ -18,4 +18,4 @@ jobs: java-version: 25 cache: maven - name: Run checkstyle and prettier - run: mvn validate --batch-mode + run: ./mvnw validate --batch-mode -- 2.39.5 From 4a191ef8a90473142b9d0fd0dfa36b761d1beaf9 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 08:34:09 +0100 Subject: [PATCH 12/15] Run npm ci --- .gitea/workflows/code-style.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitea/workflows/code-style.yaml b/.gitea/workflows/code-style.yaml index 50538bd..f7c3816 100644 --- a/.gitea/workflows/code-style.yaml +++ b/.gitea/workflows/code-style.yaml @@ -17,5 +17,11 @@ jobs: distribution: temurin java-version: 25 cache: maven + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + cache-dependency-path: bff/package-lock.json + - run: npm ci - name: Run checkstyle and prettier run: ./mvnw validate --batch-mode -- 2.39.5 From e5295f498d87c710fb4b3421ae887e976733bc98 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 12:15:26 +0100 Subject: [PATCH 13/15] Use frontend-maven-plugin to install node and prettier-plugin-java --- .gitea/workflows/code-style.yaml | 6 ------ bff/pom.xml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/code-style.yaml b/.gitea/workflows/code-style.yaml index f7c3816..50538bd 100644 --- a/.gitea/workflows/code-style.yaml +++ b/.gitea/workflows/code-style.yaml @@ -17,11 +17,5 @@ jobs: distribution: temurin java-version: 25 cache: maven - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: npm - cache-dependency-path: bff/package-lock.json - - run: npm ci - name: Run checkstyle and prettier run: ./mvnw validate --batch-mode diff --git a/bff/pom.xml b/bff/pom.xml index f323f16..cfd48dd 100644 --- a/bff/pom.xml +++ b/bff/pom.xml @@ -86,6 +86,15 @@ 2.8.1 + + com.github.eirslett + frontend-maven-plugin + 2.0.0 + + v22.13.0 + ${project.build.directory} + + @@ -102,6 +111,29 @@ + + com.github.eirslett + frontend-maven-plugin + + + install-node-and-npm + validate + + install-node-and-npm + + + + npm-install + validate + + npm + + + install + + + + com.hubspot.maven.plugins prettier-maven-plugin -- 2.39.5 From be42b9a74178b446d53dcdfdcf1c63f56fc3343a Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 12:42:49 +0100 Subject: [PATCH 14/15] Add workingDirectory --- bff/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/bff/pom.xml b/bff/pom.xml index cfd48dd..59215d1 100644 --- a/bff/pom.xml +++ b/bff/pom.xml @@ -93,6 +93,7 @@ v22.13.0 ${project.build.directory} + ${project.basedir} -- 2.39.5 From 5478715a0f4584fa3ce91e362b2df69e65bc13c6 Mon Sep 17 00:00:00 2001 From: nenzen Date: Tue, 13 Jan 2026 12:48:29 +0100 Subject: [PATCH 15/15] Remove unneeded directory, copy package and package-lock --- bff/pom.xml | 1 - branch-bff.Dockerfile | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bff/pom.xml b/bff/pom.xml index 59215d1..cfd48dd 100644 --- a/bff/pom.xml +++ b/bff/pom.xml @@ -93,7 +93,6 @@ v22.13.0 ${project.build.directory} - ${project.basedir} diff --git a/branch-bff.Dockerfile b/branch-bff.Dockerfile index f20bf78..fd09647 100644 --- a/branch-bff.Dockerfile +++ b/branch-bff.Dockerfile @@ -7,6 +7,8 @@ COPY .mvn/ .mvn/ COPY pom.xml pom.xml COPY checkstyle-configuration.xml checkstyle-configuration.xml COPY checkstyle-suppressions.xml checkstyle-suppressions.xml +COPY package.json package.json +COPY package-lock.json package-lock.json RUN ./mvnw dependency:go-offline \ --batch-mode \ -- 2.39.5