Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ on:

jobs:
build:
uses: valitydev/java-workflow/.github/workflows/maven-service-build.yml@v1
uses: valitydev/java-workflow/.github/workflows/maven-service-build.yml@v3
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:
build-and-deploy:
uses: valitydev/java-workflow/.github/workflows/maven-service-deploy.yml@v1
uses: valitydev/java-workflow/.github/workflows/maven-service-deploy.yml@v3
with:
ignore-coverage: true
secrets:
Expand Down
102 changes: 83 additions & 19 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>dev.vality</groupId>
<artifactId>service-parent-pom</artifactId>
<version>1.0.16</version>
<version>3.1.9</version>
</parent>

<artifactId>fraudbusters-api</artifactId>
Expand All @@ -23,35 +23,44 @@
<management.port>8023</management.port>
<exposed.ports>${server.port} ${management.port}</exposed.ports>
<dockerfile.registry>${env.REGISTRY}</dockerfile.registry>
<swag-fraudbusters.version>1.47-7bd0be7-server</swag-fraudbusters.version>
<swag-fraudbusters.version>1.117-7e0ac25</swag-fraudbusters.version>
<fraudbusters-proto.version>1.108-0800fde</fraudbusters-proto.version>
<jjwt-version>0.12.6</jjwt-version>
<damsel.version>1.681-7a97267</damsel.version>
</properties>

<dependencies>

<!--ValityDev-->
<dependency>
<groupId>dev.vality.woody</groupId>
<artifactId>woody-thrift</artifactId>
</dependency>
<dependency>
<groupId>dev.vality</groupId>
<artifactId>shared-resources</artifactId>
</dependency>
<dependency>
<groupId>dev.vality</groupId>
<artifactId>swag-fraudbusters</artifactId>
<artifactId>swag-fraudbusters-server</artifactId>
<version>${swag-fraudbusters.version}</version>
</dependency>
<dependency>
<groupId>dev.vality</groupId>
<artifactId>fraudbusters-proto</artifactId>
<version>${fraudbusters-proto.version}</version>
</dependency>
<dependency>
<groupId>dev.vality</groupId>
<artifactId>damsel</artifactId>
<version>${damsel.version}</version>
</dependency>
<dependency>
<groupId>dev.vality.geck</groupId>
<artifactId>serializer</artifactId>
</dependency>
<dependency>
<groupId>dev.vality.woody</groupId>
<artifactId>libthrift</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>dev.vality.woody</groupId>
<artifactId>woody-thrift</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>dev.vality.geck</groupId>
<artifactId>common</artifactId>
Expand Down Expand Up @@ -85,15 +94,29 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</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>

<!--third party-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand All @@ -110,12 +133,36 @@
<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>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock.integrations</groupId>
<artifactId>wiremock-spring-boot</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.79</version>
<scope>test</scope>
</dependency>
</dependencies>

Expand Down Expand Up @@ -148,6 +195,23 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>15</source>
<target>15</target>
<parameters>true</parameters>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package dev.vality.fraudbusters.api.configuration;

import dev.vality.fraudbusters.api.configuration.converter.JwtAuthConverter;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
public class SecurityConfig {

private final JwtAuthConverter jwtAuthConverter;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.authorizeHttpRequests(
(authorize) -> authorize
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers(HttpMethod.GET, "/**/health/liveness").permitAll()
.requestMatchers(HttpMethod.GET, "/**/health/readiness").permitAll()
.requestMatchers(HttpMethod.GET, "/**/actuator/prometheus").permitAll()
.anyRequest().authenticated());
http.oauth2ResourceServer(server -> server.jwt(token -> token.jwtAuthenticationConverter(jwtAuthConverter)));
http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.cors(c -> c.configurationSource(corsConfigurationSource()));
return http.build();
}

public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.applyPermitDefaultValues();
configuration.addAllowedMethod(HttpMethod.PUT);
configuration.addAllowedMethod(HttpMethod.DELETE);
configuration.addAllowedMethod(HttpMethod.OPTIONS);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.vality.fraudbusters.api.configuration.converter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Component
public class JwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {

private static final String principleAttribute = "preferred_username";
private static final String resourceAttribute = "resource_access";

@Override
public AbstractAuthenticationToken convert(Jwt jwt) {
return new JwtAuthenticationToken(
jwt,
new HashSet<>(extractResourceRoles(jwt)),
getPrincipleClaimName(jwt)
);
}

private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt token) {
if (token.getClaim(resourceAttribute) == null) {
return Set.of();
}
Map<String, Object> resourceAccess = token.getClaim(resourceAttribute);
if (resourceAccess.isEmpty()) {
return Set.of();
}

return resourceAccess.values().stream()
.map(resourceAccessInfo -> (Map<String, Object>) resourceAccessInfo)
.flatMap(resourceAccessInfo -> ((Collection<String>) resourceAccessInfo.get("roles")).stream())
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toSet());
}

private String getPrincipleClaimName(Jwt jwt) {
return jwt.getClaim(principleAttribute);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package dev.vality.fraudbusters.api.converter;

import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.domain.*;
import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.proxy_inspector.*;
import dev.vality.damsel.proxy_inspector.Invoice;
import dev.vality.damsel.proxy_inspector.InvoicePayment;
import dev.vality.damsel.proxy_inspector.Party;
import dev.vality.damsel.proxy_inspector.Shop;
import dev.vality.damsel.proxy_inspector.*;
import dev.vality.swag.fraudbusters.model.*;
import lombok.RequiredArgsConstructor;
import org.springframework.core.convert.converter.Converter;
Expand Down Expand Up @@ -38,9 +37,9 @@ public Context convert(PaymentInspectRequest request) {
private Shop buildShop(Merchant merchant) {
var shop = merchant.getShop();
return new Shop()
.setId(shop.getId())
.setDetails(new ShopDetails()
.setName(shop.getName()))
.setShopRef(new ShopConfigRef()
.setId(shop.getId()))
.setName(shop.getName())
.setCategory(new Category()
.setName(shop.getCategory())
.setDescription(MOCK_UNUSED_DATA))
Expand All @@ -49,7 +48,8 @@ private Shop buildShop(Merchant merchant) {

private Party buildParty(Merchant merchant) {
return new Party()
.setPartyId(merchant.getId());
.setPartyRef(new PartyConfigRef()
.setId(merchant.getId()));
}

private Invoice buildInvoice(Payment payment) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.vality.fraudbusters.api.converter;

import dev.vality.damsel.proxy_inspector.ShopContext;
import dev.vality.swag.fraudbusters.model.Merchant;
import dev.vality.swag.fraudbusters.model.Shop;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class ShopContextToMerchantConverter implements Converter<ShopContext, Merchant> {

@Override
public Merchant convert(ShopContext shopContext) {
var shop = shopContext.getShop();
Shop swaggerShop = new Shop();
if (shop != null) {
swaggerShop
.id(shop.getShopRef() != null ? shop.getShopRef().getId() : null)
.name(shop.getName())
.category(shop.getCategory() != null ? shop.getCategory().getName() : null)
.location(shop.getLocation() != null ? shop.getLocation().getUrl() : null);
}
var party = shopContext.getParty();
return new Merchant()
.id(party != null && party.getPartyRef() != null ? party.getPartyRef().getId() : null)
.shop(swaggerShop);
}
}

Loading
Loading