ialbert 2022-08-15 19:28:11 +03:00
parent baf625f959
commit 1dce58b76c
11 changed files with 174 additions and 7 deletions

View file

@ -41,6 +41,14 @@
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-messaging</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
</dependencies>
<dependencyManagement>

View file

@ -0,0 +1,39 @@
package ru.spcex.clearing.backendapi.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SuppressWarnings("Guava")
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("clearing-backend-api")
.apiInfo(metadata())
.select()
.apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
.paths(PathSelectors.any())
.build()
.useDefaultResponseMessages(false);
}
private ApiInfo metadata() {
return new ApiInfoBuilder()
.title("Spcex Clearing service")
.description("Сервис клиринга")
.version("0.0.1")
.build();
}
}

View file

@ -0,0 +1,39 @@
package ru.spcex.clearing.backendapi.config;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@SuppressWarnings("Duplicates")
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/v2/api-docs", "/v2/api-docs?group=api");
registry.addRedirectViewController("/swagger-resources/configuration/ui", "/swagger-resources/configuration/ui");
registry.addRedirectViewController("/swagger-resources/configuration/security", "/swagger-resources/configuration/security");
registry.addRedirectViewController("/swagger-resources", "/swagger-resources");
registry.addRedirectViewController("", "/swagger-ui.html");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/swagger-ui.html**")
.addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
}
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
return (factory) -> factory.setRegisterDefaultServlet(true);
}
}

View file

@ -3,6 +3,7 @@ package ru.spcex.clearing.backendapi.config.element;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import ru.spcex.clearing.backendapi.security.element.SecuritySettings;
import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings;
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
@ -12,6 +13,7 @@ import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
public class BackendApiSettings {
private HazelcastClientParams hazelcast;
private KafkaProducerSettings kafka;
private SecuritySettings security;
private String exampleSetting;
public HazelcastClientParams getHazelcast() {
@ -37,4 +39,12 @@ public class BackendApiSettings {
public void setExampleSetting(String exampleSetting) {
this.exampleSetting = exampleSetting;
}
public SecuritySettings getSecurity() {
return security;
}
public void setSecurity(SecuritySettings security) {
this.security = security;
}
}

View file

@ -1,5 +1,8 @@
package ru.spcex.clearing.backendapi.controller;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
@ -14,7 +17,10 @@ import ru.spcex.clearing.backendapi.config.element.BackendApiSettings;
@Controller
public class DefaultController implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private Boolean authorizationDisabled = false;
@ApiOperation(value = "Test backend-api availability.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK")})
@RequestMapping(method = RequestMethod.GET, path = "/anonymous/method1", produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String processGet() {
@ -22,19 +28,22 @@ public class DefaultController implements InitializingBean {
return "backend-api controller test method";
}
@ApiOperation(value = "Test backend-api availability (for authorized access). Available for anonymous, if authorization-disabled=true.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK")})
@RequestMapping(method = RequestMethod.GET, path = "/users/method2", produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String processProtectedGet() {
log.info("controller method2");
return "use post";
return "backend-api controller test method (authorized endpoint); authorization: " + (authorizationDisabled ? "disabled" : "enabled");
}
@Autowired
private BackendApiSettings settings;
@Override
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
log.info("controller started");
log.info("settings example {}", settings.getExampleSetting());
this.authorizationDisabled = settings.getSecurity().getAuthorizationDisabled();
}
}

View file

@ -3,6 +3,7 @@ package ru.spcex.clearing.backendapi.controller.cud;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.*;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
@ -30,9 +31,16 @@ public class CudController {
this.json = new ObjectMapper();
}
@ApiOperation(value = "create/update/delete business objects. See meta.xml for field descriptions.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = MetaDataResponse.class)})
@RequestMapping(value = "/{destination}", method = RequestMethod.POST)
@ResponseBody
public BasicSpcexResponse add(@PathVariable("destination") String destination,
public MetaDataResponse add(
@ApiParam(value = "Последняя часть URL определяет 'направление', по которому пойдет запрос. " +
"Должно биться с форматом запроса.", required = true, example = "money-market-security-new")
@PathVariable("destination")
String destination,
@ApiParam(value = "Параметры команды в JSON формате, поля см. в meta.xml.", required = true)
@RequestBody String body) throws JsonProcessingException, ExecutionException, InterruptedException {
Class<IAction<?>> actionClazz = meta.byDestination(destination);
if (actionClazz == null) {
@ -48,11 +56,15 @@ public class CudController {
return responseToClient;
}
@ApiModel(description="Ответ в результате отправки операции в топик Kafka.")
private static class MetaDataResponse extends BasicSpcexResponse {
@ApiModelProperty(value="Offset положенного сообщения")
@JsonProperty
private Long offset;
@ApiModelProperty(value="Partition положенного сообщения")
@JsonProperty
private Integer partition;
@ApiModelProperty(value="Название топика, в который было положено сообщение")
@JsonProperty
private String topic;

View file

@ -1,7 +1,13 @@
package ru.spcex.clearing.backendapi.controller.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(description="Базовый формат ответа")
public class BasicSpcexResponse {
@ApiModelProperty(value="Код ответа (успешный 0)", required = true)
private int code;
@ApiModelProperty(value="Сообщение ответа")
private String message;
public int getCode() {

View file

@ -7,14 +7,22 @@ import org.springframework.beans.factory.annotation.Autowired;
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.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import ru.spcex.clearing.backendapi.config.element.BackendApiSettings;
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
private final Boolean securityDisabled;
public WebSecurityConfig(BackendApiSettings settings) {
this.securityDisabled = settings.getSecurity().getAuthorizationDisabled();
}
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
@ -30,7 +38,7 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl anyReq = http
// .formLogin()
// .loginProcessingUrl("/backend-api-login/perform-login")
// .and()
@ -39,8 +47,12 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
.antMatchers("/anonymous/**").permitAll()
.antMatchers("/sso/login").permitAll()
.antMatchers("/error").permitAll()
.antMatchers( "/cud/**").permitAll() //todo remove
.antMatchers("/backend-api-login/**").permitAll()
.anyRequest().hasAnyRole("admin", "default-roles-master");
.anyRequest();
if (securityDisabled) {
anyReq.permitAll();
} else {
anyReq.hasAnyRole("admin", "default-roles-master");
}
}
}

View file

@ -0,0 +1,13 @@
package ru.spcex.clearing.backendapi.security.element;
public class SecuritySettings {
private Boolean authorizationDisabled = false;
public Boolean getAuthorizationDisabled() {
return authorizationDisabled;
}
public void setAuthorizationDisabled(Boolean authorizationDisabled) {
this.authorizationDisabled = authorizationDisabled;
}
}

View file

@ -15,6 +15,8 @@ backend-api.kafka.batch-size=16384
backend-api.kafka.linger-ms=1
backend-api.kafka.buffer-memory=33554432
backend-api.security.authorization-disabled=true
##keycloak
##keycloak.auth-server-url=http://10.200.200.147:8080/

17
pom.xml
View file

@ -39,6 +39,8 @@
<external_libraries.slf4j.version>1.7.33</external_libraries.slf4j.version>
<external_libraries.logback.version>1.2.10</external_libraries.logback.version>
<external_libraries.kafka.version>2.8.1</external_libraries.kafka.version>
<external_libraries.swagger.version>2.9.2</external_libraries.swagger.version>
<external_libraries.swagger.annotations.version>1.5.22</external_libraries.swagger.annotations.version>
</properties>
<dependencyManagement>
@ -127,6 +129,21 @@
<artifactId>spring-kafka</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${external_libraries.swagger.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${external_libraries.swagger.annotations.version}</version>
</dependency>
<!-- TEST -->
<dependency>