diff --git a/clearing-parent/backend-api/pom.xml b/clearing-parent/backend-api/pom.xml
index 558019a31..1875a33b2 100644
--- a/clearing-parent/backend-api/pom.xml
+++ b/clearing-parent/backend-api/pom.xml
@@ -41,6 +41,14 @@
ru.spcex.platform
platform-messaging
+
+ io.springfox
+ springfox-swagger2
+
+
+ io.springfox
+ springfox-swagger-ui
+
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/SwaggerConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/SwaggerConfig.java
new file mode 100644
index 000000000..e6d2929fe
--- /dev/null
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/SwaggerConfig.java
@@ -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();
+ }
+
+}
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java
new file mode 100644
index 000000000..8bd17c36d
--- /dev/null
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java
@@ -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 enableDefaultServlet() {
+ return (factory) -> factory.setRegisterDefaultServlet(true);
+ }
+}
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java
index cdd40615c..422d18323 100644
--- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java
@@ -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;
+ }
}
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/DefaultController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/DefaultController.java
index 498e1c646..90a43dcb0 100644
--- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/DefaultController.java
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/DefaultController.java
@@ -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();
}
}
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/cud/CudController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/cud/CudController.java
index d5a78360a..6763b14bf 100644
--- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/cud/CudController.java
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/cud/CudController.java
@@ -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,10 +31,17 @@ 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,
- @RequestBody String body) throws JsonProcessingException, ExecutionException, InterruptedException {
+ 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> actionClazz = meta.byDestination(destination);
if (actionClazz == null) {
throw new UnsupportedOperationException("unsupported destination " + destination);
@@ -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;
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/BasicSpcexResponse.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/BasicSpcexResponse.java
index 78cc506f0..bb3b47597 100644
--- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/BasicSpcexResponse.java
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/BasicSpcexResponse.java
@@ -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() {
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java
index c85304290..da522ad13 100644
--- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java
@@ -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.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");
+ }
}
}
diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java
new file mode 100644
index 000000000..d2b48b879
--- /dev/null
+++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java
@@ -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;
+ }
+}
diff --git a/clearing-parent/backend-api/src/main/resources/application.properties b/clearing-parent/backend-api/src/main/resources/application.properties
index 934e3d6b5..721f33f19 100644
--- a/clearing-parent/backend-api/src/main/resources/application.properties
+++ b/clearing-parent/backend-api/src/main/resources/application.properties
@@ -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/
diff --git a/pom.xml b/pom.xml
index 65d895c46..430ffad39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,6 +39,8 @@
1.7.33
1.2.10
2.8.1
+ 2.9.2
+ 1.5.22
@@ -127,6 +129,21 @@
spring-kafka
2.8.1
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${external_libraries.swagger.version}
+
+
+ io.swagger
+ swagger-annotations
+ ${external_libraries.swagger.annotations.version}
+