Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ out/
**.toml

### Mac OS ###
.DS_Store
.DS_Store

.env
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {

id 'jacoco'


}

jacoco {
Expand Down Expand Up @@ -154,5 +154,7 @@ implementation 'org.postgresql:postgresql'
implementation("org.apache.poi:poi:5.2.5")
implementation("org.apache.poi:poi-ooxml:5.2.5")

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package school.hei.vola.endpoint.rest.security;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
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.configurers.LogoutConfigurer;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConf {

private final VolaAdminChecker volaAdminChecker;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
auth ->
auth.requestMatchers(
"/ping",
"/health/**",
"/error",
"/swagger-ui/**",
"/v3/api-docs/**",
"/payment",
"/payments/search",
"/orange/**")
.permitAll()
.requestMatchers("/payments/**")
.authenticated()
.anyRequest()
.denyAll())
.oauth2Login(oauth2 -> oauth2.successHandler(authenticationSuccessHandler()))
.logout(LogoutConfigurer::permitAll)
.csrf(csrf -> csrf.ignoringRequestMatchers("/payment", "/payments/search", "/orange/**"));

return http.build();
}

@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return (request, response, authentication) -> {
var oidcUser = (OidcUser) authentication.getPrincipal();
String email = oidcUser.getEmail();
if (!volaAdminChecker.isAdmin(email)) {
throw new AccessDeniedException("You're not a Vola Administrator");
}
response.sendRedirect("/payments");
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package school.hei.vola.endpoint.rest.security;

import java.util.Arrays;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class VolaAdminChecker {
private String admins;

public VolaAdminChecker(@Value("${vola.admins}") String admins) {
this.admins = admins;
}

public boolean isAdmin(String email) {
if (email == null || admins == null) {
return false;
}
return Arrays.stream(admins.split(","))
.map(String::trim)
.map(String::toLowerCase)
.anyMatch(admin -> admin.equals(email.toLowerCase()));
}
}
16 changes: 16 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
spring:
security:
oauth2:
client:
registration:
casdoor:
client-id: ${CASDOOR_CLIENT_ID}
client-secret: ${CASDOOR_CLIENT_SECRET}
scope: openid, profile, email
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
provider:
casdoor:
issuer-uri: ${CASDOOR_ISSUER_URI}
vola:
admins: ${VOLA_ADMINS}
16 changes: 15 additions & 1 deletion src/test/java/school/hei/vola/conf/EnvConf.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ void configureProperties(DynamicPropertyRegistry registry) {
"spring.datasource.url", () -> "jdbc:h2:mem:testdb;CASE_INSENSITIVE_IDENTIFIERS=TRUE");
registry.add("spring.datasource.driverClassName", () -> "org.h2.Driver");
registry.add("spring.jpa.database-platform", () -> "org.hibernate.dialect.H2Dialect");
registry.add("orange.api.url", () -> apiUrl);
registry.add("orange.api.url", () -> apiUrl != null ? apiUrl : "http://dummy.orange.api");
registry.add(
"spring.security.oauth2.client.registration.casdoor.provider", () -> "casdoor-test");
registry.add("spring.security.oauth2.client.registration.casdoor.client-id", () -> "dummy");
registry.add("spring.security.oauth2.client.registration.casdoor.client-secret", () -> "dummy");
registry.add(
"spring.security.oauth2.client.registration.casdoor.authorization-grant-type",
() -> "authorization_code");
registry.add(
"spring.security.oauth2.client.registration.casdoor.redirect-uri",
() -> "{baseUrl}/login/oauth2/code/casdoor");
registry.add(
"spring.security.oauth2.client.provider.casdoor-test.authorization-uri", () -> "dummy");
registry.add("spring.security.oauth2.client.provider.casdoor-test.token-uri", () -> "dummy");
registry.add("vola.admins", () -> "admin@test.com");
}
}
36 changes: 36 additions & 0 deletions src/test/java/school/hei/vola/unit/VolaAdminCheckerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package school.hei.vola.unit;

import org.junit.jupiter.api.Test;
import school.hei.vola.endpoint.rest.security.VolaAdminChecker;

class VolaAdminCheckerTest {
@Test
void admin_email_returns_true() {
var checker = new VolaAdminChecker("admin@hei.school, bob@hei.school");
assert checker.isAdmin("admin@hei.school");
}

@Test
void admin_email_case_insensitive() {
var checker = new VolaAdminChecker("admin@hei.school,bob@hei.school");
assert checker.isAdmin("bob@Hei.School");
}

@Test
void non_admin_email_returns_false() {
var checker = new VolaAdminChecker("admin@hei.school,bob@hei.school");
assert !checker.isAdmin("other@hei.school");
}

@Test
void null_email_returns_false() {
var checker = new VolaAdminChecker("admin@hei.school, valisoa@hei.school");
assert !checker.isAdmin(null);
}

@Test
void second_admin_also_matches() {
var checker = new VolaAdminChecker("admin@hei.school,valisoa@hei.school");
assert checker.isAdmin("valisoa@hei.school");
}
}
Loading