mirror of
https://github.com/valitydev/anapi-v2.git
synced 2024-11-06 00:25:17 +00:00
Auth via tokenkeeper (#73)
* Auth via tokenkeeper * Update dependency dev.vality:damsel to v1.614-3df747f (#72) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency dev.vality:bouncer-proto to v1.51-23d1761 (#71) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency dev.vality:analytics-proto to v1.43-2d1fdc2 (#70) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency com.github.tomakehurst:wiremock-jre8-standalone to v2.35.1 [SECURITY] (#66) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update all non-major maven dependencies (#68) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Feedback edits --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
parent
193f05fb0c
commit
520a524690
69
pom.xml
69
pom.xml
@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>anapi-v2</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.4</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>anapi-v2</name>
|
||||
@ -44,7 +44,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
<artifactId>bouncer-proto</artifactId>
|
||||
<version>1.46-d5e5639</version>
|
||||
<version>1.51-23d1761</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
@ -69,7 +69,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
<artifactId>analytics-proto</artifactId>
|
||||
<version>1.41-f691834</version>
|
||||
<version>1.43-2d1fdc2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
@ -83,60 +83,19 @@
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
<artifactId>damsel</artifactId>
|
||||
<version>1.597-bfedcb9</version>
|
||||
<version>1.614-3df747f</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.vality</groupId>
|
||||
<artifactId>token-keeper-proto</artifactId>
|
||||
<version>1.32-8b8bb43</version>
|
||||
</dependency>
|
||||
|
||||
<!--spring-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-admin-client</artifactId>
|
||||
<version>15.1.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jackson2-provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxb-provider</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-spring-security-adapter</artifactId>
|
||||
<version>15.1.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
@ -173,7 +132,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.8</version>
|
||||
<version>1.6.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -222,7 +181,7 @@
|
||||
<dependency>
|
||||
<groupId>org.openapitools</groupId>
|
||||
<artifactId>jackson-databind-nullable</artifactId>
|
||||
<version>0.2.3</version>
|
||||
<version>0.2.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -254,7 +213,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock-jre8-standalone</artifactId>
|
||||
<version>2.34.0</version>
|
||||
<version>2.35.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -297,12 +256,12 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-remote-resources-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-filtering</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
|
@ -1,16 +1,17 @@
|
||||
package dev.vality.anapi.v2.config;
|
||||
|
||||
import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.analytics.AnalyticsServiceSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.reporter.ReportingSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityEmailExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityIdExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityRealmExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityUsernameExtensionKit;
|
||||
import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder;
|
||||
import dev.vality.damsel.analytics.AnalyticsServiceSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.reporter.ReportingSrv;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -86,4 +87,14 @@ public class ApplicationConfig {
|
||||
.withAddress(resource.getURI())
|
||||
.build(ReportingSrv.Iface.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient(
|
||||
@Value("${service.tokenKeeper.url}") Resource resource,
|
||||
@Value("${service.tokenKeeper.networkTimeout}") int networkTimeout) throws IOException {
|
||||
return new THSpawnClientBuilder()
|
||||
.withNetworkTimeout(networkTimeout)
|
||||
.withAddress(resource.getURI())
|
||||
.build(TokenAuthenticatorSrv.Iface.class);
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
package dev.vality.anapi.v2.config;
|
||||
|
||||
import dev.vality.anapi.v2.config.properties.KeycloakProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
|
||||
public class KeycloakConfig {
|
||||
|
||||
private final KeycloakProperties keycloakProperties;
|
||||
|
||||
@Bean
|
||||
public KeycloakConfigResolver keycloakConfigResolver() {
|
||||
return facade -> {
|
||||
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(adapterConfig());
|
||||
deployment.setNotBefore(keycloakProperties.getNotBefore());
|
||||
return deployment;
|
||||
};
|
||||
}
|
||||
|
||||
private AdapterConfig adapterConfig() {
|
||||
if (StringUtils.hasLength(keycloakProperties.getRealmPublicKeyPath())) {
|
||||
keycloakProperties.setRealmPublicKey(readKeyFromFile(keycloakProperties.getRealmPublicKeyPath()));
|
||||
}
|
||||
|
||||
AdapterConfig adapterConfig = new AdapterConfig();
|
||||
adapterConfig.setRealm(keycloakProperties.getRealm());
|
||||
adapterConfig.setRealmKey(keycloakProperties.getRealmPublicKey());
|
||||
adapterConfig.setResource(keycloakProperties.getResource());
|
||||
adapterConfig.setAuthServerUrl(keycloakProperties.getAuthServerUrl());
|
||||
adapterConfig.setUseResourceRoleMappings(true);
|
||||
adapterConfig.setBearerOnly(true);
|
||||
adapterConfig.setSslRequired(keycloakProperties.getSslRequired());
|
||||
return adapterConfig;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private String readKeyFromFile(String filePath) {
|
||||
List<String> strings = Files.readAllLines(Paths.get(filePath));
|
||||
strings.remove(strings.size() - 1);
|
||||
strings.remove(0);
|
||||
return strings.stream().map(String::trim).collect(Collectors.joining());
|
||||
}
|
||||
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package dev.vality.anapi.v2.config;
|
||||
|
||||
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
|
||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@ComponentScan(
|
||||
basePackageClasses = KeycloakSecurityComponents.class,
|
||||
excludeFilters = @ComponentScan.Filter(
|
||||
type = FilterType.REGEX,
|
||||
pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
|
||||
@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
|
||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
||||
return new NullAuthenticatedSessionStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
super.configure(http);
|
||||
http
|
||||
.cors().and()
|
||||
.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.antMatchers(HttpMethod.GET, "/**/health").permitAll()
|
||||
.antMatchers(HttpMethod.GET, "/**/prometheus").permitAll()
|
||||
.anyRequest().authenticated();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(keycloakAuthenticationProvider());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.applyPermitDefaultValues();
|
||||
configuration.addAllowedMethod(HttpMethod.PUT);
|
||||
configuration.addAllowedMethod(HttpMethod.DELETE);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
}
|
@ -1,17 +1,12 @@
|
||||
package dev.vality.anapi.v2.config;
|
||||
|
||||
import dev.vality.woody.api.flow.WFlow;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityEmailExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityIdExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityRealmExtensionKit;
|
||||
import dev.vality.woody.api.trace.context.metadata.user.UserIdentityUsernameExtensionKit;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
@ -19,18 +14,27 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static dev.vality.anapi.v2.util.DeadlineUtil.*;
|
||||
import static dev.vality.woody.api.trace.ContextUtils.setCustomMetadataValue;
|
||||
import static dev.vality.woody.api.trace.ContextUtils.setDeadline;
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings({"ParameterName", "LocalVariableName"})
|
||||
public class WebConfig {
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurer corsConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("*");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean woodyFilter() {
|
||||
WFlow woodyFlow = new WFlow();
|
||||
@ -41,20 +45,15 @@ public class WebConfig {
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
woodyFlow.createServiceFork(
|
||||
() -> {
|
||||
try {
|
||||
if (request.getUserPrincipal() != null) {
|
||||
addWoodyContext(request.getUserPrincipal());
|
||||
() -> {
|
||||
try {
|
||||
setWoodyDeadline(request);
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (IOException | ServletException e) {
|
||||
sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
setWoodyDeadline(request);
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (IOException | ServletException e) {
|
||||
sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
@ -71,17 +70,6 @@ public class WebConfig {
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
private void addWoodyContext(Principal principal) {
|
||||
KeycloakSecurityContext keycloakSecurityContext =
|
||||
((KeycloakAuthenticationToken) principal).getAccount().getKeycloakSecurityContext();
|
||||
AccessToken accessToken = keycloakSecurityContext.getToken();
|
||||
|
||||
setCustomMetadataValue(UserIdentityIdExtensionKit.KEY, accessToken.getSubject());
|
||||
setCustomMetadataValue(UserIdentityUsernameExtensionKit.KEY, accessToken.getPreferredUsername());
|
||||
setCustomMetadataValue(UserIdentityEmailExtensionKit.KEY, accessToken.getEmail());
|
||||
setCustomMetadataValue(UserIdentityRealmExtensionKit.KEY, keycloakSecurityContext.getRealm());
|
||||
}
|
||||
|
||||
private void setWoodyDeadline(HttpServletRequest request) {
|
||||
String xRequestDeadline = request.getHeader("X-Request-Deadline");
|
||||
String xRequestId = request.getHeader("X-Request-ID");
|
||||
|
@ -1,34 +0,0 @@
|
||||
package dev.vality.anapi.v2.config.properties;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Component
|
||||
@Validated
|
||||
@ConfigurationProperties(prefix = "keycloak")
|
||||
public class KeycloakProperties {
|
||||
|
||||
@NotEmpty
|
||||
private String realm;
|
||||
@NotEmpty
|
||||
private String authServerUrl;
|
||||
@NotEmpty
|
||||
private String resource;
|
||||
|
||||
private Integer notBefore;
|
||||
|
||||
@NotEmpty
|
||||
private String sslRequired;
|
||||
|
||||
private String realmPublicKey;
|
||||
|
||||
private String realmPublicKeyPath;
|
||||
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package dev.vality.anapi.v2.controller;
|
||||
|
||||
import dev.vality.anapi.v2.exception.AuthorizationException;
|
||||
import dev.vality.anapi.v2.exception.BadRequestException;
|
||||
import dev.vality.anapi.v2.exception.DeadlineException;
|
||||
import dev.vality.anapi.v2.exception.NotFoundException;
|
||||
import dev.vality.anapi.v2.exception.*;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -11,7 +8,6 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
@ -84,15 +80,15 @@ public class ErrorControllerAdvice {
|
||||
|
||||
}
|
||||
|
||||
@ExceptionHandler({AccessDeniedException.class})
|
||||
@ExceptionHandler({TokenKeeperException.class})
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public void handleAccessDeniedException(AccessDeniedException e) {
|
||||
public void handleTokenKeeperException(TokenKeeperException e) {
|
||||
log.warn("<- Res [403]: Request denied access", e);
|
||||
}
|
||||
|
||||
@ExceptionHandler({AuthorizationException.class})
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public void handleAccessDeniedException(AuthorizationException e) {
|
||||
public void handleAuthorizationException(AuthorizationException e) {
|
||||
log.warn("<- Res [403]: Request denied access", e);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
package dev.vality.anapi.v2.exception;
|
||||
|
||||
public class TokenKeeperException extends RuntimeException {
|
||||
|
||||
public TokenKeeperException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public TokenKeeperException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ package dev.vality.anapi.v2.security;
|
||||
import dev.vality.anapi.v2.exception.AuthorizationException;
|
||||
import dev.vality.anapi.v2.exception.BouncerException;
|
||||
import dev.vality.anapi.v2.service.BouncerService;
|
||||
import dev.vality.anapi.v2.service.KeycloakService;
|
||||
import dev.vality.anapi.v2.service.TokenKeeperService;
|
||||
import dev.vality.anapi.v2.service.VortigonService;
|
||||
import dev.vality.bouncer.base.Entity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -24,7 +24,7 @@ public class AccessService {
|
||||
|
||||
private final VortigonService vortigonService;
|
||||
private final BouncerService bouncerService;
|
||||
private final KeycloakService keycloakService;
|
||||
private final TokenKeeperService tokenKeeperService;
|
||||
|
||||
@Value("${service.bouncer.auth.enabled}")
|
||||
private boolean authEnabled;
|
||||
@ -86,16 +86,13 @@ public class AccessService {
|
||||
}
|
||||
|
||||
private AnapiBouncerContext buildAnapiBouncerContext(AccessData accessData, @Nullable List<String> shopIds) {
|
||||
var token = keycloakService.getAccessToken();
|
||||
return AnapiBouncerContext.builder()
|
||||
.operationId(accessData.getOperationId())
|
||||
.partyId(accessData.getPartyId())
|
||||
.shopIds(shopIds)
|
||||
.fileId(accessData.getFileId())
|
||||
.reportId(accessData.getReportId())
|
||||
.tokenExpiration(token.getExp())
|
||||
.tokenId(token.getId())
|
||||
.userId(token.getSubject())
|
||||
.authData(tokenKeeperService.getAuthData())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package dev.vality.anapi.v2.security;
|
||||
|
||||
import dev.vality.token.keeper.AuthData;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@ -17,6 +18,6 @@ public class AnapiBouncerContext {
|
||||
private final List<String> shopIds;
|
||||
private final String reportId;
|
||||
private final String fileId;
|
||||
|
||||
private final AuthData authData;
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package dev.vality.anapi.v2.security;
|
||||
|
||||
import dev.vality.anapi.v2.config.properties.BouncerProperties;
|
||||
import dev.vality.anapi.v2.service.KeycloakService;
|
||||
import dev.vality.anapi.v2.service.OrgManagerService;
|
||||
import dev.vality.anapi.v2.util.JwtUtil;
|
||||
import dev.vality.bouncer.base.Entity;
|
||||
import dev.vality.bouncer.context.v1.*;
|
||||
import dev.vality.bouncer.ctx.ContextFragmentType;
|
||||
@ -14,6 +14,7 @@ import org.apache.thrift.TSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@ -23,7 +24,6 @@ public class BouncerContextFactory {
|
||||
|
||||
private final BouncerProperties bouncerProperties;
|
||||
private final OrgManagerService orgManagerService;
|
||||
private final KeycloakService keycloakService;
|
||||
|
||||
@SneakyThrows
|
||||
public Context buildContext(AnapiBouncerContext bouncerContext) {
|
||||
@ -32,11 +32,17 @@ public class BouncerContextFactory {
|
||||
var fragment = new dev.vality.bouncer.ctx.ContextFragment()
|
||||
.setType(ContextFragmentType.v1_thrift_binary)
|
||||
.setContent(serializer.serialize(contextFragment));
|
||||
var userFragment = orgManagerService.getUserAuthContext(
|
||||
keycloakService.getAccessToken().getSubject());
|
||||
|
||||
var context = new Context();
|
||||
context.putToFragments(bouncerProperties.getContextFragmentId(), fragment);
|
||||
context.putToFragments("user", userFragment);
|
||||
context.putToFragments("anapi", fragment);
|
||||
context.putToFragments("token-keeper", bouncerContext.getAuthData().getContext());
|
||||
|
||||
Optional<String> subject = JwtUtil.getSubject(bouncerContext.getAuthData().getToken());
|
||||
if (subject.isPresent()) {
|
||||
log.debug("User context fragment will be added");
|
||||
var userFragment = orgManagerService.getUserAuthContext(subject.get());
|
||||
context.putToFragments("user", userFragment);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@ -46,21 +52,11 @@ public class BouncerContextFactory {
|
||||
var contextReports = buildReportContext(bouncerContext);
|
||||
ContextFragment fragment = new ContextFragment();
|
||||
return fragment
|
||||
.setAuth(buildAuth())
|
||||
.setEnv(env)
|
||||
.setAnapi(contextAnalyticsApi)
|
||||
.setReports(contextReports);
|
||||
}
|
||||
|
||||
private Auth buildAuth() {
|
||||
var auth = new Auth();
|
||||
var accessToken = keycloakService.getAccessToken();
|
||||
return auth
|
||||
.setToken(new Token().setId(accessToken.getId()))
|
||||
.setMethod(bouncerProperties.getAuthMethod())
|
||||
.setExpiration(Instant.ofEpochSecond(accessToken.getExp()).toString());
|
||||
}
|
||||
|
||||
private Environment buildEnvironment() {
|
||||
var deployment = new Deployment()
|
||||
.setId(bouncerProperties.getDeploymentId());
|
||||
|
@ -1,17 +0,0 @@
|
||||
package dev.vality.anapi.v2.service;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KeycloakService {
|
||||
|
||||
public AccessToken getAccessToken() {
|
||||
var keycloakPrincipal = (KeycloakPrincipal) SecurityContextHolder.getContext()
|
||||
.getAuthentication()
|
||||
.getPrincipal();
|
||||
return keycloakPrincipal.getKeycloakSecurityContext().getToken();
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package dev.vality.anapi.v2.service;
|
||||
|
||||
import dev.vality.anapi.v2.exception.TokenKeeperException;
|
||||
import dev.vality.token.keeper.AuthData;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import dev.vality.token.keeper.TokenSourceContext;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.thrift.TException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TokenKeeperService {
|
||||
|
||||
private static final String bearerPrefix = "Bearer ";
|
||||
private final TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
public AuthData getAuthData() {
|
||||
log.debug("Retrieving auth info");
|
||||
try {
|
||||
var token = getBearerToken();
|
||||
return tokenKeeperClient.authenticate(
|
||||
token.orElseThrow(() -> new TokenKeeperException("Token not found!")), new TokenSourceContext());
|
||||
} catch (TException e) {
|
||||
throw new TokenKeeperException("Error while call token keeper: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> getBearerToken() {
|
||||
var attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (ObjectUtils.isEmpty(attributes)
|
||||
|| ObjectUtils.isEmpty(attributes.getRequest().getHeader(HttpHeaders.AUTHORIZATION))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String token = attributes.getRequest().getHeader(HttpHeaders.AUTHORIZATION).substring(bearerPrefix.length());
|
||||
return Optional.of(token);
|
||||
}
|
||||
|
||||
}
|
33
src/main/java/dev/vality/anapi/v2/util/JwtUtil.java
Normal file
33
src/main/java/dev/vality/anapi/v2/util/JwtUtil.java
Normal file
@ -0,0 +1,33 @@
|
||||
package dev.vality.anapi.v2.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class JwtUtil {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static final String subjectFieldName = "sub";
|
||||
|
||||
public static Optional<String> getSubject(String token) {
|
||||
try {
|
||||
String[] chunks = token.split("\\.");
|
||||
Base64.Decoder decoder = Base64.getUrlDecoder();
|
||||
String payload = new String(decoder.decode(chunks[1]));
|
||||
Map<String, Object> parsedPayload = objectMapper.readValue(payload, HashMap.class);
|
||||
if (parsedPayload.containsKey(subjectFieldName)) {
|
||||
return Optional.of(String.valueOf(parsedPayload.get(subjectFieldName)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Unable to parse jwt token while looking for subject: ", e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -33,6 +33,9 @@ service:
|
||||
orgManager:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 5000
|
||||
tokenKeeper:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 5000
|
||||
bouncer:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 10000
|
||||
@ -57,13 +60,3 @@ spring:
|
||||
info:
|
||||
version: '@project.version@'
|
||||
stage: dev
|
||||
|
||||
keycloak:
|
||||
realm: internal
|
||||
auth-server-url: http://keycloak:8080/auth/
|
||||
resource: common-api
|
||||
not-before: 0
|
||||
ssl-required: none
|
||||
realm-public-key:
|
||||
|
||||
auth.enabled: true
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.AnalyticsUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.analytics.AnalyticsServiceSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class AnalyticsTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@ -44,6 +46,8 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
private AnalyticsServiceSrv.Iface analyticsClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -55,7 +59,8 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{analyticsClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{analyticsClient, vortigonClient,
|
||||
orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +73,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void getAveragePaymentRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(analyticsClient.getAveragePayment(any())).thenReturn(AnalyticsUtil.createAveragePaymentRequiredResponse());
|
||||
@ -82,6 +88,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(analyticsClient, times(1)).getAveragePayment(any());
|
||||
@ -91,6 +98,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void getAveragePaymentAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(analyticsClient.getAveragePayment(any())).thenReturn(AnalyticsUtil.createAveragePaymentAllResponse());
|
||||
@ -105,6 +113,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(analyticsClient, times(1)).getAveragePayment(any());
|
||||
@ -132,6 +141,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void getAveragePaymentRequestServerUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(analyticsClient.getAveragePayment(any())).thenThrow(TException.class);
|
||||
@ -145,6 +155,7 @@ class AnalyticsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(analyticsClient, times(1)).getAveragePayment(any());
|
||||
|
@ -1,11 +1,12 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.reporter.ReportingSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -21,13 +22,14 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.OpenApiUtil.getReportsRequiredParams;
|
||||
import static dev.vality.anapi.v2.testutil.RandomUtil.randomInt;
|
||||
import static dev.vality.anapi.v2.testutil.RandomUtil.randomIntegerAsString;
|
||||
import static dev.vality.anapi.v2.testutil.ReporterUtil.createReport;
|
||||
import static dev.vality.anapi.v2.testutil.ReporterUtil.createSearchReportsResponse;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -37,7 +39,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class ReportsTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@ -47,6 +49,8 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
private ReportingSrv.Iface reporterClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -58,7 +62,8 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {reporterClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[] {reporterClient, vortigonClient, orgManagerClient,
|
||||
bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -72,6 +77,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
void cancelReportRequestSuccess() {
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
int reportId = randomInt(1, 1000);
|
||||
mvc.perform(post("/lk/v2/reports/{reportId}/cancel", reportId)
|
||||
.header("Authorization", "Bearer " + generateSimpleJwt())
|
||||
@ -84,6 +90,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isAccepted())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).cancelReport(reportId);
|
||||
}
|
||||
@ -93,6 +100,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
void cancelReportRequestServerUnavailable() {
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
int reportId = randomInt(1, 1000);
|
||||
doThrow(new TException()).when(reporterClient).cancelReport(reportId);
|
||||
mvc.perform(post("/lk/v2/reports/{reportId}/cancel", reportId)
|
||||
@ -106,6 +114,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isInternalServerError())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).cancelReport(reportId);
|
||||
}
|
||||
@ -115,6 +124,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
void createReportRequestSuccess() {
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
long reportId = randomInt(1, 1000);
|
||||
when(reporterClient.createReport(any(), any())).thenReturn(reportId);
|
||||
when(reporterClient.getReport(reportId)).thenReturn(createReport(reportId));
|
||||
@ -129,6 +139,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).createReport(any(), any());
|
||||
verify(reporterClient, times(1)).getReport(reportId);
|
||||
@ -139,6 +150,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
void downloadUrlRequestSuccess() {
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
String reportId = randomIntegerAsString(1, 1000);
|
||||
String fileId = randomIntegerAsString(1, 1000);
|
||||
when(reporterClient.generatePresignedUrl(eq(fileId), any())).thenReturn("www.google.ru");
|
||||
@ -153,6 +165,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).generatePresignedUrl(eq(fileId), notNull());
|
||||
}
|
||||
@ -162,6 +175,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
void getReportRequestSuccess() {
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
long reportId = randomInt(1, 1000);
|
||||
when(reporterClient.getReport(reportId)).thenReturn(createReport(reportId));
|
||||
mvc.perform(get("/lk/v2/reports/{reportID}", reportId)
|
||||
@ -175,6 +189,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).getReport(reportId);
|
||||
}
|
||||
@ -183,6 +198,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void getSearchReportsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(reporterClient.getReports(any())).thenReturn(createSearchReportsResponse());
|
||||
@ -197,6 +213,7 @@ class ReportsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(reporterClient, times(1)).getReports(notNull());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -35,7 +37,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
|
||||
class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchChargebacksTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -45,6 +47,8 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -56,7 +60,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -69,6 +73,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchChargebacksRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchChargebacks(any())).thenReturn(MagistaUtil.createSearchChargebackRequiredResponse());
|
||||
@ -83,6 +88,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
@ -92,6 +98,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchChargebacksAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchChargebacks(any())).thenReturn(MagistaUtil.createSearchChargebackAllResponse());
|
||||
@ -106,6 +113,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
@ -133,6 +141,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchChargebacksRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenThrow(TException.class);
|
||||
@ -146,6 +155,7 @@ class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchInvoiceTemplatesTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -44,6 +46,8 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -55,7 +59,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +72,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
@SneakyThrows
|
||||
void searchInvoiceTemplatesRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoiceTemplates(any())).thenReturn(
|
||||
@ -83,6 +88,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoiceTemplates(any());
|
||||
@ -92,6 +98,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
@SneakyThrows
|
||||
void searchInvoiceTemplatesAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoiceTemplates(any())).thenReturn(
|
||||
@ -107,6 +114,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoiceTemplates(any());
|
||||
@ -134,6 +142,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
@SneakyThrows
|
||||
void searchInvoiceTemplatesRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoiceTemplates(any())).thenThrow(TException.class);
|
||||
@ -147,6 +156,7 @@ class SearchInvoiceTemplatesTest extends AbstractKeycloakOpenIdAsWiremockConfig
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoiceTemplates(any());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchInvoicesTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -43,6 +45,8 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
@ -55,7 +59,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +72,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchInvoicesRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenReturn(MagistaUtil.createSearchInvoiceRequiredResponse());
|
||||
@ -82,6 +87,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
@ -91,6 +97,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchInvoicesAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenReturn(MagistaUtil.createSearchInvoiceAllResponse());
|
||||
@ -105,6 +112,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
@ -132,6 +140,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchInvoicesRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenThrow(TException.class);
|
||||
@ -145,6 +154,7 @@ class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchPaymentsTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -44,6 +46,8 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -55,7 +59,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +72,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPaymentsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenReturn(MagistaUtil.createSearchPaymentRequiredResponse());
|
||||
@ -82,6 +87,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
@ -91,6 +97,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPaymentsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenReturn(MagistaUtil.createSearchPaymentAllResponse());
|
||||
@ -105,6 +112,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
@ -132,6 +140,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPaymentsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenThrow(TException.class);
|
||||
@ -145,6 +154,7 @@ class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchPayoutsTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -44,6 +46,8 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -55,7 +59,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +72,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPayoutsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenReturn(MagistaUtil.createSearchPayoutRequiredResponse());
|
||||
@ -82,6 +87,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
@ -91,6 +97,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPayoutsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenReturn(MagistaUtil.createSearchPayoutAllResponse());
|
||||
@ -105,6 +112,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
@ -132,6 +140,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchPayoutsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenThrow(TException.class);
|
||||
@ -145,6 +154,7 @@ class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dev.vality.anapi.v2;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
@ -8,6 +8,7 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.magista.MerchantStatisticsServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -24,8 +25,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -34,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class SearchRefundsTest extends AbstractConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@ -44,6 +46,8 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
@ -55,7 +59,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{magistaClient, vortigonClient, orgManagerClient, bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -68,6 +72,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchRefundsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenReturn(MagistaUtil.createSearchRefundRequiredResponse());
|
||||
@ -82,6 +87,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
@ -91,6 +97,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchRefundsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenReturn(MagistaUtil.createSearchRefundAllResponse());
|
||||
@ -105,6 +112,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
@ -132,6 +140,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@SneakyThrows
|
||||
void searchRefundsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenThrow(TException.class);
|
||||
@ -145,6 +154,7 @@ class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
|
@ -10,9 +10,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
public class KeycloakOpenIdTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public KeycloakOpenIdStub keycloakOpenIdStub(@Value("${keycloak.auth-server-url}") String keycloakAuthServerUrl,
|
||||
@Value("${keycloak.realm}") String keycloakRealm,
|
||||
JwtTokenBuilder jwtTokenBuilder) {
|
||||
return new KeycloakOpenIdStub(keycloakAuthServerUrl, keycloakRealm, jwtTokenBuilder);
|
||||
public KeycloakOpenIdStub keycloakOpenIdStub(JwtTokenBuilder jwtTokenBuilder) {
|
||||
return new KeycloakOpenIdStub(jwtTokenBuilder);
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,16 @@
|
||||
package dev.vality.anapi.v2.auth.utils;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
|
||||
public class KeycloakOpenIdStub {
|
||||
|
||||
private final String keycloakRealm;
|
||||
private final String issuer;
|
||||
private final String openidConfig;
|
||||
private final JwtTokenBuilder jwtTokenBuilder;
|
||||
|
||||
public KeycloakOpenIdStub(String keycloakAuthServerUrl, String keycloakRealm, JwtTokenBuilder jwtTokenBuilder) {
|
||||
this.keycloakRealm = keycloakRealm;
|
||||
public KeycloakOpenIdStub(JwtTokenBuilder jwtTokenBuilder) {
|
||||
this.jwtTokenBuilder = jwtTokenBuilder;
|
||||
this.issuer = keycloakAuthServerUrl + "/realms/" + keycloakRealm;
|
||||
this.openidConfig = "{\n" +
|
||||
" \"issuer\": \"" + issuer + "\",\n" +
|
||||
" \"authorization_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/auth\",\n" +
|
||||
" \"token_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token\",\n" +
|
||||
" \"token_introspection_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token/introspect\",\n" +
|
||||
" \"userinfo_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/userinfo\",\n" +
|
||||
" \"end_session_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/logout\",\n" +
|
||||
" \"jwks_uri\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/certs\",\n" +
|
||||
" \"check_session_iframe\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/login-status-iframe.html\",\n" +
|
||||
" \"registration_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/clients-registrations/openid-connect\",\n" +
|
||||
" \"introspection_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token/introspect\"\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
public void givenStub() {
|
||||
stubFor(get(urlEqualTo(String.format("/auth/realms/%s/.well-known/openid-configuration", keycloakRealm)))
|
||||
.willReturn(aResponse()
|
||||
.withHeader("Content-Type", "application/json")
|
||||
.withBody(openidConfig)
|
||||
)
|
||||
);
|
||||
this.issuer = "test/realms/test";
|
||||
}
|
||||
|
||||
public String generateJwt(String... roles) {
|
||||
return jwtTokenBuilder.generateJwtWithRoles(issuer, roles);
|
||||
}
|
||||
|
||||
public String generateJwt(long iat, long exp, String... roles) {
|
||||
return jwtTokenBuilder.generateJwtWithRoles(iat, exp, issuer, roles);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package dev.vality.anapi.v2.config;
|
||||
|
||||
import dev.vality.anapi.v2.AnapiV2Application;
|
||||
import dev.vality.anapi.v2.auth.utils.KeycloakOpenIdStub;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
@ -13,22 +12,15 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = {AnapiV2Application.class},
|
||||
properties = {
|
||||
"wiremock.server.baseUrl=http://localhost:${wiremock.server.port}",
|
||||
"keycloak.auth-server-url=${wiremock.server.baseUrl}/auth"})
|
||||
properties = {"wiremock.server.baseUrl=http://localhost:${wiremock.server.port}"})
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureWireMock(port = 0)
|
||||
@ExtendWith(SpringExtension.class)
|
||||
public abstract class AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public abstract class AbstractConfig {
|
||||
|
||||
@Autowired
|
||||
private KeycloakOpenIdStub keycloakOpenIdStub;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp(@Autowired KeycloakOpenIdStub keycloakOpenIdStub) throws Exception {
|
||||
keycloakOpenIdStub.givenStub();
|
||||
}
|
||||
|
||||
protected String generateSimpleJwt() {
|
||||
return keycloakOpenIdStub.generateJwt();
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
package dev.vality.anapi.v2.controller;
|
||||
|
||||
import dev.vality.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import dev.vality.anapi.v2.config.AbstractConfig;
|
||||
import dev.vality.anapi.v2.converter.magista.request.ParamsToRefundSearchQueryConverter;
|
||||
import dev.vality.anapi.v2.exception.BadRequestException;
|
||||
import dev.vality.anapi.v2.model.DefaultLogicError;
|
||||
import dev.vality.anapi.v2.testutil.OpenApiUtil;
|
||||
import dev.vality.anapi.v2.testutil.MagistaUtil;
|
||||
import dev.vality.bouncer.decisions.ArbiterSrv;
|
||||
import dev.vality.damsel.vortigon.VortigonServiceSrv;
|
||||
import dev.vality.orgmanagement.AuthContextProviderSrv;
|
||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -24,6 +24,9 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createJudgementAllowed;
|
||||
import static dev.vality.anapi.v2.testutil.TokenKeeperUtil.createAuthData;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -32,7 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
class ErrorControllerTest extends AbstractConfig {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@ -44,6 +47,8 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
public AuthContextProviderSrv.Iface orgManagerClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
@MockBean
|
||||
public TokenAuthenticatorSrv.Iface tokenKeeperClient;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
@ -52,7 +57,8 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{refundSearchConverter, vortigonClient, orgManagerClient, bouncerClient};
|
||||
preparedMocks = new Object[]{refundSearchConverter, vortigonClient, orgManagerClient,
|
||||
bouncerClient, tokenKeeperClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -83,8 +89,9 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@Test
|
||||
void testBadRequestException() throws Exception {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(MagistaUtil.createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(MagistaUtil.createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
String message = "Error!";
|
||||
Mockito.doThrow(new BadRequestException(message)).when(refundSearchConverter)
|
||||
.convert(any(), any(), any(), any(),
|
||||
@ -106,6 +113,7 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").value(message));
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(refundSearchConverter, times(1))
|
||||
@ -153,8 +161,9 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
@Test
|
||||
void testInternalException() throws Exception {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(MagistaUtil.createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(MagistaUtil.createJudgementAllowed());
|
||||
when(tokenKeeperClient.authenticate(any(), any())).thenReturn(createAuthData(generateSimpleJwt()));
|
||||
when(orgManagerClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
doThrow(new RuntimeException()).when(refundSearchConverter)
|
||||
.convert(any(), any(), any(), any(),
|
||||
any(), any(), any(), any(),
|
||||
@ -174,6 +183,7 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
.andExpect(status().isInternalServerError())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(tokenKeeperClient, times(1)).authenticate(any(), any());
|
||||
verify(orgManagerClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(refundSearchConverter, times(1))
|
||||
@ -184,16 +194,19 @@ class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@Test
|
||||
void testUnauthorizedException() throws Exception {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
mockMvc.perform(
|
||||
get("/lk/v2/refunds")
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", "fail")
|
||||
.header("X-Request-Deadline",
|
||||
Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
}
|
||||
|
||||
}
|
||||
|
26
src/test/java/dev/vality/anapi/v2/testutil/BouncerUtil.java
Normal file
26
src/test/java/dev/vality/anapi/v2/testutil/BouncerUtil.java
Normal file
@ -0,0 +1,26 @@
|
||||
package dev.vality.anapi.v2.testutil;
|
||||
|
||||
import dev.vality.bouncer.ctx.ContextFragment;
|
||||
import dev.vality.bouncer.decisions.Judgement;
|
||||
import dev.vality.bouncer.decisions.Resolution;
|
||||
import dev.vality.bouncer.decisions.ResolutionAllowed;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.thrift.TSerializer;
|
||||
|
||||
@UtilityClass
|
||||
public class BouncerUtil {
|
||||
|
||||
@SneakyThrows
|
||||
public static ContextFragment createContextFragment() {
|
||||
ContextFragment fragment = DamselUtil.fillRequiredTBaseObject(new ContextFragment(), ContextFragment.class);
|
||||
fragment.setContent(new TSerializer().serialize(new dev.vality.bouncer.context.v1.ContextFragment()));
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static Judgement createJudgementAllowed() {
|
||||
Resolution resolution = new Resolution();
|
||||
resolution.setAllowed(new ResolutionAllowed());
|
||||
return new Judgement().setResolution(resolution);
|
||||
}
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
package dev.vality.anapi.v2.testutil;
|
||||
|
||||
import dev.vality.bouncer.ctx.ContextFragment;
|
||||
import dev.vality.bouncer.decisions.Judgement;
|
||||
import dev.vality.bouncer.decisions.Resolution;
|
||||
import dev.vality.bouncer.decisions.ResolutionAllowed;
|
||||
import dev.vality.damsel.base.Content;
|
||||
import dev.vality.damsel.domain.InvoicePaymentRefundStatus;
|
||||
import dev.vality.damsel.domain.InvoicePaymentStatus;
|
||||
@ -15,9 +11,7 @@ import dev.vality.magista.InvoicePaymentFlowHold;
|
||||
import dev.vality.magista.InvoicePaymentFlowInstant;
|
||||
import dev.vality.magista.Payer;
|
||||
import dev.vality.magista.*;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.thrift.TSerializer;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
@ -169,19 +163,6 @@ public class MagistaUtil {
|
||||
return DamselUtil.fillRequiredTBaseObject(new StatInvoiceTemplateResponse(), StatInvoiceTemplateResponse.class);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static ContextFragment createContextFragment() {
|
||||
ContextFragment fragment = DamselUtil.fillRequiredTBaseObject(new ContextFragment(), ContextFragment.class);
|
||||
fragment.setContent(new TSerializer().serialize(new dev.vality.bouncer.context.v1.ContextFragment()));
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static Judgement createJudgementAllowed() {
|
||||
Resolution resolution = new Resolution();
|
||||
resolution.setAllowed(new ResolutionAllowed());
|
||||
return new Judgement().setResolution(resolution);
|
||||
}
|
||||
|
||||
public static InvoicePaymentFlow createInvoicePaymentFlowHold() {
|
||||
return InvoicePaymentFlow.hold(
|
||||
DamselUtil.fillRequiredTBaseObject(new InvoicePaymentFlowHold(), InvoicePaymentFlowHold.class));
|
||||
|
@ -0,0 +1,24 @@
|
||||
package dev.vality.anapi.v2.testutil;
|
||||
|
||||
import dev.vality.token.keeper.AuthData;
|
||||
import dev.vality.token.keeper.AuthDataStatus;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static dev.vality.anapi.v2.testutil.BouncerUtil.createContextFragment;
|
||||
|
||||
@UtilityClass
|
||||
public class TokenKeeperUtil {
|
||||
|
||||
public static AuthData createAuthData(String token) {
|
||||
return new AuthData()
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.setAuthority(UUID.randomUUID().toString())
|
||||
.setToken(token)
|
||||
.setStatus(AuthDataStatus.active)
|
||||
.setContext(createContextFragment());
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user